This commit is contained in:
@@ -58,9 +58,10 @@ class AliyunTingwuService:
|
|||||||
self.client = None
|
self.client = None
|
||||||
logger.warning("Aliyun AccessKey configuration missing.")
|
logger.warning("Aliyun AccessKey configuration missing.")
|
||||||
|
|
||||||
def upload_to_oss(self, file_obj, file_name):
|
def upload_to_oss(self, file_obj, file_name, day=7):
|
||||||
"""
|
"""
|
||||||
上传文件到 OSS 并返回带签名的 URL (有效期 3 小时)
|
上传文件到 OSS 并返回带签名的 URL
|
||||||
|
默认生成有效期为 7 天 (3600 * 24 * day) 的签名URL,方便评委在一段时间内都能播放。
|
||||||
"""
|
"""
|
||||||
if not self.bucket:
|
if not self.bucket:
|
||||||
raise Exception("OSS Client not initialized")
|
raise Exception("OSS Client not initialized")
|
||||||
@@ -70,8 +71,8 @@ class AliyunTingwuService:
|
|||||||
# file_obj 应该是打开的文件对象或字节流
|
# file_obj 应该是打开的文件对象或字节流
|
||||||
self.bucket.put_object(file_name, file_obj)
|
self.bucket.put_object(file_name, file_obj)
|
||||||
|
|
||||||
# 生成签名 URL,有效期 3 小时 (3600 * 3)
|
# 生成签名 URL,有效期 7 天 (3600 * 24 * 7 = 604800 秒)
|
||||||
url = self.bucket.sign_url('GET', file_name, 3600 * 3)
|
url = self.bucket.sign_url('GET', file_name, 3600 * 24 * day)
|
||||||
return url
|
return url
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"OSS Upload failed: {e}")
|
logger.error(f"OSS Upload failed: {e}")
|
||||||
|
|||||||
@@ -2,6 +2,23 @@
|
|||||||
|
|
||||||
{% block title %}项目列表 - 评委系统{% endblock %}
|
{% block title %}项目列表 - 评委系统{% endblock %}
|
||||||
|
|
||||||
|
{% block extra_css %}
|
||||||
|
<style>
|
||||||
|
.markdown-body p { margin-bottom: 0.5em; }
|
||||||
|
.markdown-body ul { list-style-type: disc; padding-left: 1.5em; margin-bottom: 0.5em; }
|
||||||
|
.markdown-body ol { list-style-type: decimal; padding-left: 1.5em; margin-bottom: 0.5em; }
|
||||||
|
.markdown-body strong { font-weight: 600; }
|
||||||
|
.markdown-body h1, .markdown-body h2, .markdown-body h3, .markdown-body h4 { font-weight: 600; margin-top: 1em; margin-bottom: 0.5em; }
|
||||||
|
.markdown-body { overflow: hidden; }
|
||||||
|
.line-clamp-5 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-line-clamp: 5;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="flex flex-col sm:flex-row justify-between items-center mb-8 gap-4">
|
<div class="flex flex-col sm:flex-row justify-between items-center mb-8 gap-4">
|
||||||
<div>
|
<div>
|
||||||
@@ -104,7 +121,12 @@
|
|||||||
<div class="p-4 bg-white space-y-4">
|
<div class="p-4 bg-white space-y-4">
|
||||||
<div>
|
<div>
|
||||||
<p class="text-xs font-semibold text-gray-500 uppercase mb-1">AI 总结</p>
|
<p class="text-xs font-semibold text-gray-500 uppercase mb-1">AI 总结</p>
|
||||||
<p class="text-sm text-gray-800" id="modalAiSummary"></p>
|
<div class="relative">
|
||||||
|
<div class="text-sm text-gray-800 markdown-body line-clamp-5 transition-all duration-300" id="modalAiSummary"></div>
|
||||||
|
<button id="toggleAiSummaryBtn" type="button" onclick="toggleAiSummary()" class="text-xs text-blue-600 hover:text-blue-800 focus:outline-none flex items-center mt-2 hidden">
|
||||||
|
<i class="fas fa-chevron-down mr-1" id="toggleAiSummaryIcon"></i> <span id="toggleAiSummaryText">点击完整显示</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-t border-gray-100 pt-3 relative">
|
<div class="border-t border-gray-100 pt-3 relative">
|
||||||
<div class="flex justify-between items-center mb-1">
|
<div class="flex justify-between items-center mb-1">
|
||||||
@@ -248,7 +270,28 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block extra_js %}
|
{% block extra_js %}
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
/**
|
||||||
|
* 切换 AI 总结内容的显示状态(折叠/展开)
|
||||||
|
* 通过添加或移除 line-clamp-5 类来实现截断或完整显示,并更新按钮的文字和图标。
|
||||||
|
*/
|
||||||
|
function toggleAiSummary() {
|
||||||
|
const summaryDiv = document.getElementById('modalAiSummary');
|
||||||
|
const toggleText = document.getElementById('toggleAiSummaryText');
|
||||||
|
const toggleIcon = document.getElementById('toggleAiSummaryIcon');
|
||||||
|
|
||||||
|
if (summaryDiv.classList.contains('line-clamp-5')) {
|
||||||
|
summaryDiv.classList.remove('line-clamp-5');
|
||||||
|
toggleText.innerText = '收起内容';
|
||||||
|
toggleIcon.className = 'fas fa-chevron-up mr-1';
|
||||||
|
} else {
|
||||||
|
summaryDiv.classList.add('line-clamp-5');
|
||||||
|
toggleText.innerText = '点击完整显示';
|
||||||
|
toggleIcon.className = 'fas fa-chevron-down mr-1';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function updateFileName(input) {
|
function updateFileName(input) {
|
||||||
const display = document.getElementById('fileNameDisplay');
|
const display = document.getElementById('fileNameDisplay');
|
||||||
if (input.files.length > 0) {
|
if (input.files.length > 0) {
|
||||||
@@ -359,7 +402,29 @@ async function viewProject(id) {
|
|||||||
const aiSection = document.getElementById('aiResultSection');
|
const aiSection = document.getElementById('aiResultSection');
|
||||||
if (data.ai_result) {
|
if (data.ai_result) {
|
||||||
aiSection.style.display = 'block';
|
aiSection.style.display = 'block';
|
||||||
document.getElementById('modalAiSummary').innerText = (data.ai_result.summary || '暂无总结').substring(0, 300) + (data.ai_result.summary && data.ai_result.summary.length > 300 ? '...' : '');
|
|
||||||
|
const summaryDiv = document.getElementById('modalAiSummary');
|
||||||
|
const toggleBtn = document.getElementById('toggleAiSummaryBtn');
|
||||||
|
const toggleText = document.getElementById('toggleAiSummaryText');
|
||||||
|
const toggleIcon = document.getElementById('toggleAiSummaryIcon');
|
||||||
|
|
||||||
|
const summaryText = data.ai_result.summary || '暂无总结';
|
||||||
|
summaryDiv.innerHTML = marked.parse(summaryText);
|
||||||
|
|
||||||
|
// Reset to collapsed state
|
||||||
|
summaryDiv.classList.add('line-clamp-5');
|
||||||
|
toggleText.innerText = '点击完整显示';
|
||||||
|
toggleIcon.className = 'fas fa-chevron-down mr-1';
|
||||||
|
|
||||||
|
// Show/hide toggle button based on content height
|
||||||
|
setTimeout(() => {
|
||||||
|
if (summaryDiv.scrollHeight > summaryDiv.clientHeight) {
|
||||||
|
toggleBtn.classList.remove('hidden');
|
||||||
|
} else {
|
||||||
|
toggleBtn.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
|
||||||
document.getElementById('modalAiTrans').innerText = (data.ai_result.transcription || '暂无内容').substring(0, 150) + '...';
|
document.getElementById('modalAiTrans').innerText = (data.ai_result.transcription || '暂无内容').substring(0, 150) + '...';
|
||||||
|
|
||||||
// Store full data for full transcription modal
|
// Store full data for full transcription modal
|
||||||
|
|||||||
Reference in New Issue
Block a user