Spaces:
Paused
Paused
| {% extends "base.html" %} | |
| {% block title %}图床模式 - tgState{% endblock %} | |
| {% block content %} | |
| <div style="display: flex; flex-direction: column; gap: 24px;"> | |
| <!-- Header --> | |
| <div class="flex-between"> | |
| <h1 style="font-size: 24px; font-weight: 700;">图床模式</h1> | |
| <div style="display: flex; gap: 12px; flex: 1; justify-content: flex-end; min-width: 0;"> | |
| <div class="input-group" style="margin-bottom: 0; max-width: 300px; width: 100%;"> | |
| <input type="text" id="file-search" class="input-field" placeholder="搜索图片..." style="width: 100%;"> | |
| </div> | |
| </div> | |
| </div> | |
| {% if not cfg.bot_ready %} | |
| <div class="empty-state"> | |
| <div class="empty-icon"> | |
| <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"></path><line x1="12" y1="9" x2="12" y2="13"></line><line x1="12" y1="17" x2="12.01" y2="17"></line></svg> | |
| </div> | |
| <h3 class="empty-title">需要配置</h3> | |
| <p class="empty-desc">缺少 Bot Token 或频道名,图片功能暂不可用。</p> | |
| <a href="/settings" class="btn btn-primary">前往设置</a> | |
| </div> | |
| {% else %} | |
| <!-- Upload Area --> | |
| <div class="card" style="border-style: dashed; text-align: center; padding: 40px; cursor: pointer; transition: all 0.2s;" | |
| id="upload-zone"> | |
| <input type="file" id="file-picker" hidden multiple accept="image/*"> | |
| <div style="color: var(--primary-color); margin-bottom: 12px;"> | |
| <svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg> | |
| </div> | |
| <h3 style="font-size: 16px; font-weight: 600; margin-bottom: 4px;">上传图片</h3> | |
| <p style="color: var(--text-secondary); font-size: 14px;">拖拽图片到此处或点击选择</p> | |
| </div> | |
| <!-- Progress Area --> | |
| <div id="prog-zone" style="display: flex; flex-direction: column; gap: 12px;"></div> | |
| <div id="done-zone" style="display: flex; flex-direction: column; gap: 12px;"></div> | |
| <!-- Batch Actions --> | |
| <div class="flex-between hidden" id="batch-actions-bar" style="background: var(--bg-surface-hover); padding: 12px 16px; border-radius: var(--radius-md);"> | |
| <span class="text-sm font-medium"><span id="selection-counter">0</span> 项已选</span> | |
| <div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap;"> | |
| <div class="link-format-selector" style="display: flex; gap: 4px; margin-right: 8px;"> | |
| <button class="btn btn-ghost btn-sm active format-option" data-format="url" style="height: 32px; font-size: 12px;">URL</button> | |
| <button class="btn btn-ghost btn-sm format-option" data-format="markdown" style="height: 32px; font-size: 12px;">MD</button> | |
| <button class="btn btn-ghost btn-sm format-option" data-format="html" style="height: 32px; font-size: 12px;">HTML</button> | |
| </div> | |
| <button id="copy-links-btn" class="btn btn-secondary btn-sm" style="height: 32px; font-size: 13px;">复制</button> | |
| <button id="batch-delete-btn" class="btn btn-secondary btn-sm" style="height: 32px; font-size: 13px; color: var(--danger-color);">删除</button> | |
| </div> | |
| </div> | |
| <!-- Image Grid --> | |
| <div class="card image-grid" style="padding: 24px;"> | |
| <input type="checkbox" id="select-all-checkbox" style="display:none;"> <!-- Hidden logic hook --> | |
| <div class="file-list" id="file-list-disk" style="display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 16px;"> | |
| {% if files %} | |
| {% for file in files %} | |
| <div class="file-item image-card" style="border: 1px solid var(--border-color); border-radius: var(--radius-md); overflow: hidden; background: var(--bg-body);" id="file-item-{{ file.file_id | replace(from=':', to='-') }}" data-file-id="{{ file.file_id }}" data-file-url="/d/{{ file.display_id }}" data-filename="{{ file.filename }}" data-short-id="{{ file.short_id }}"> | |
| <div style="position: relative; aspect-ratio: 16/9; background: #000;"> | |
| <img src="/d/{{ file.display_id }}" loading="lazy" style="width: 100%; height: 100%; object-fit: contain;" alt="{{ file.filename }}"> | |
| <div style="position: absolute; top: 8px; left: 8px;"> | |
| <input type="checkbox" class="file-checkbox" data-file-id="{{ file.file_id }}" style="width: 20px; height: 20px; cursor: pointer; border-radius: 4px;"> | |
| </div> | |
| </div> | |
| <div style="padding: 12px;"> | |
| <div class="text-sm font-medium" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 4px;" title="{{ file.filename }}">{{ file.filename }}</div> | |
| <div class="text-sm text-muted" style="margin-bottom: 12px;">{{ file.filesize_mb }} MB</div> | |
| <div style="display: flex; gap: 8px;"> | |
| <button class="btn btn-secondary btn-sm copy-link-btn" style="flex: 1; height: 32px;">复制</button> | |
| <button class="btn btn-secondary btn-sm delete" style="height: 32px; color: var(--danger-color);" onclick="deleteFile('{{ file.file_id }}')"> | |
| <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| {% endfor %} | |
| {% else %} | |
| <div style="grid-column: 1/-1; padding: 40px; text-align: center; color: var(--text-tertiary);"> | |
| <p>暂无图片</p> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </div> | |
| {% endif %} | |
| </div> | |
| <script src="/static/js/main.js?v=4.0"></script> | |
| {% endblock %} | |