71 lines
6.3 KiB
HTML
71 lines
6.3 KiB
HTML
{{define "app"}}<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<meta name="color-scheme" content="light">
|
|
<meta name="csrf-token" content="{{.CSRFToken}}">
|
|
<meta name="htmx-config" content='{"includeIndicatorStyles":false}'>
|
|
<meta name="max-prompt-bytes" content="{{.MaxPromptBytes}}">
|
|
<meta name="max-images" content="{{.MaxImages}}">
|
|
<title>{{.Title}} - Chorus</title>
|
|
<link rel="stylesheet" href="/static/app.css">
|
|
<script defer src="/static/vendor/icons.min.js"></script>
|
|
<script defer src="/static/vendor/htmx.min.js"></script>
|
|
<script defer src="/static/app.js"></script>
|
|
<script defer src="/static/vendor/alpine-csp.min.js"></script>
|
|
</head>
|
|
<body data-page="app">
|
|
<a class="skip-link" href="#main-content">跳到主要内容</a>
|
|
<header class="topbar">
|
|
<a class="brand" href="/" aria-label="Chorus 新建生成"><span class="brand-mark" aria-hidden="true">C</span><span>CHORUS</span></a>
|
|
<nav class="primary-nav" aria-label="主导航"><a class="nav-item" href="/" aria-current="page"><i class="icon" data-lucide="plus"></i>生成工作台</a></nav>
|
|
<div class="account-actions"><span class="user-name">{{.DisplayName}}</span><button class="icon-button" id="logout-button" type="button" aria-label="退出登录" title="退出登录"><i class="icon" data-lucide="log-out"></i></button></div>
|
|
</header>
|
|
<div class="workspace">
|
|
<aside class="history-panel" aria-labelledby="history-title">
|
|
<div class="history-sticky">
|
|
<a class="button button-primary button-block" href="/"><i class="icon" data-lucide="plus"></i>新建生成</a>
|
|
<label class="field-label history-search-label" for="history-search">搜索历史</label>
|
|
<div class="search-field"><i class="icon" data-lucide="search"></i><input class="input" id="history-search" type="search" placeholder="搜索历史" autocomplete="off"></div>
|
|
<h2 class="sr-only" id="history-title">生成历史</h2>
|
|
{{if .History}}<ul class="history-list" id="history-list">
|
|
{{range .History}}<li data-history-search="{{.UserPrompt}} {{kindLabel .Kind}}">
|
|
<a class="history-item" href="/generations/{{.ID}}" {{if $.Current}}{{if eq .ID $.Current.Generation.ID}}aria-current="page"{{end}}{{end}}>
|
|
<span class="history-icon"><i class="icon" data-lucide="{{kindIcon .Kind}}"></i></span>
|
|
<span class="history-copy"><span class="history-title">{{shortPrompt .UserPrompt}}</span><span class="history-meta"><span class="status-dot {{statusTone .Status}}"></span>{{kindLabel .Kind}} · {{relativeTime .CreatedAt}}</span></span>
|
|
</a>
|
|
</li>{{end}}
|
|
</ul><p class="history-end">已显示全部历史,没有更多记录</p>{{else}}<p class="history-empty">还没有生成记录</p>{{end}}
|
|
</div>
|
|
</aside>
|
|
<main class="main" id="main-content" tabindex="-1">
|
|
<div class="main-inner">
|
|
<div class="page-heading"><div><p class="eyebrow">生成工作台</p><h1>{{if .Current}}{{shortPrompt .Current.Generation.UserPrompt}}{{else}}新建生成{{end}}</h1></div></div>
|
|
<div class="content-grid">
|
|
<section class="panel result-panel" aria-labelledby="result-title">{{template "result" .}}</section>
|
|
<section class="panel composer" aria-labelledby="composer-title" x-data="composer">
|
|
<div class="panel-header"><div class="panel-heading-group"><h2 id="composer-title">生成内容</h2><p>选择类型并描述需要的结果</p></div></div>
|
|
<form class="composer-body" id="composer-form" novalidate>
|
|
<div class="mode-switch" role="group" aria-label="生成类型">
|
|
<button class="mode-button" type="button" data-mode="text" x-on:click="setText" x-bind:aria-pressed="textPressed"><i class="icon" data-lucide="file-text"></i>文本</button>
|
|
<button class="mode-button" type="button" data-mode="image" x-on:click="setImage" x-bind:aria-pressed="imagePressed"><i class="icon" data-lucide="image"></i>图片</button>
|
|
</div>
|
|
<input id="generation-kind" type="hidden" value="image">
|
|
<div class="form-field"><label class="field-label" for="prompt">描述你想要的结果</label><textarea class="textarea" id="prompt" name="prompt" required></textarea><p class="field-help"><span id="prompt-count">0</span> 字节</p><p class="field-error hidden" id="prompt-error" role="alert">请输入生成要求。</p></div>
|
|
<div id="image-fields" x-bind:class="imageClass" x-cloak>
|
|
<div class="form-field"><span class="field-label">参考图片</span><label class="upload-zone"><input id="image-upload" type="file" accept="image/jpeg,image/png,image/webp" multiple><span><i class="icon" data-lucide="plus"></i><strong>添加图片</strong>JPG、PNG 或 WebP,第一张为主图</span></label><p class="field-error hidden" id="upload-error" role="alert"></p></div>
|
|
<div class="upload-list" id="upload-list"></div>
|
|
</div>
|
|
<div class="composer-footer"><button class="button button-primary button-block" id="generate-button" type="submit"><i class="icon" data-lucide="plus"></i><span>开始生成</span></button><p class="privacy-note"><i class="icon" data-lucide="shield-check"></i>任务和结果仅对当前账户可见。</p></div>
|
|
</form>
|
|
</section>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
</div>
|
|
<div class="modal-backdrop hidden" id="auth-modal" role="presentation"><section class="modal" role="dialog" aria-modal="true" aria-labelledby="auth-title" aria-describedby="auth-description"><div class="state-icon danger"><i class="icon" data-lucide="alert-circle"></i></div><h2 id="auth-title">登录状态已失效</h2><p id="auth-description">当前内容已保留。重新登录后会返回这个任务,不会把任务误标为失败。</p><div class="modal-actions"><button class="button button-secondary" id="dismiss-auth" type="button">稍后处理</button><button class="button button-primary" id="relogin-button" type="button">重新登录</button></div></section></div>
|
|
<div class="toast hidden" id="toast" role="status" aria-live="polite"><i class="icon" data-lucide="check"></i><span id="toast-text">操作已完成</span></div>
|
|
</body>
|
|
</html>{{end}}
|