Repo .git was damaged (refs/ missing, index truncated, object store near-empty). Repaired via git init (rebuilt refs), stale index preserved as .git/index.corrupt-20260910.bak, then full worktree committed as a rollback baseline.
136 lines
6.5 KiB
HTML
136 lines
6.5 KiB
HTML
<!--
|
||
功能控制表单部分模板:提问 / 私聊 / 投票 三个功能面板共用。
|
||
渲染时「点」为单个功能视图(Key / Control / State / Mode / CSRFTokenHTML ...),
|
||
因此所有文案与令牌都可自取,无需访问根数据。
|
||
|
||
收集模式(mode)三选一,保存时互斥、后端同步清理未选模式的字段:
|
||
- always 长期开放:不限时间,保持开放直到手动关闭(仍受收集上限约束);
|
||
- window 定时收集:一次性开放 / 关闭时间窗口;
|
||
- recurring 循环定时:每周固定开放日 + 每日时间段循环。
|
||
私聊(chat)不提供收集上限:配额字段与重置计数按钮按 Key 条件隐藏,后端强制清零。
|
||
「保存」与「重置计数」同行:重置按钮通过 HTML5 form 属性指向独立的 reset 表单。
|
||
-->
|
||
<div class="feat-card">
|
||
<div class="feat-card-head">
|
||
<h3 class="uk-margin-remove">{{ .NameText }}</h3>
|
||
<span class="feat-status {{ if .State.Open }}is-open{{ else }}is-closed{{ end }}">{{ .StatusText }}</span>
|
||
</div>
|
||
<span class="feat-hint">{{t .LangCode (print "admin.featureHint." .Key)}}</span>
|
||
|
||
<form method="post" action="/user/profile/features/update">
|
||
{{ .CSRFTokenHTML }}
|
||
<input type="hidden" name="feature" value="{{ .Key }}">
|
||
<div class="uk-margin-small">
|
||
<label>
|
||
<input name="enabled" class="uk-checkbox" type="checkbox" {{ if .Control.Enabled }}checked{{ end }}>
|
||
<span class="uk-text-small">{{t .LangCode "admin.featureEnabled"}}</span>
|
||
</label>
|
||
</div>
|
||
<div class="uk-margin-small feat-field">
|
||
<span class="feat-field-label">{{t .LangCode "admin.featureMode"}}</span>
|
||
<div class="feat-modes">
|
||
<label class="feat-day{{ if eq .Mode "always" }} is-on{{ end }}">
|
||
<input name="mode" type="radio" value="always" {{ if eq .Mode "always" }}checked{{ end }}>
|
||
<span>{{t .LangCode "admin.featureModeAlways"}}</span>
|
||
</label>
|
||
<label class="feat-day{{ if eq .Mode "window" }} is-on{{ end }}">
|
||
<input name="mode" type="radio" value="window" {{ if eq .Mode "window" }}checked{{ end }}>
|
||
<span>{{t .LangCode "admin.featureModeWindow"}}</span>
|
||
</label>
|
||
<label class="feat-day{{ if eq .Mode "recurring" }} is-on{{ end }}">
|
||
<input name="mode" type="radio" value="recurring" {{ if eq .Mode "recurring" }}checked{{ end }}>
|
||
<span>{{t .LangCode "admin.featureModeRecurring"}}</span>
|
||
</label>
|
||
</div>
|
||
<span class="feat-hint">{{t .LangCode "admin.featureModeHint"}}</span>
|
||
</div>
|
||
<div class="uk-margin-small feat-field feat-window-fields">
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureOpenAt"}}</span>
|
||
<input name="open_at" class="uk-input" type="datetime-local" value="{{ .OpenAtStr }}">
|
||
</label>
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureCloseAt"}}</span>
|
||
<input name="close_at" class="uk-input" type="datetime-local" value="{{ .CloseAtStr }}">
|
||
</label>
|
||
<span class="feat-hint">{{t .LangCode "admin.featureTimeHint"}}</span>
|
||
</div>
|
||
<div class="uk-margin-small feat-field feat-recurring-fields">
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureSchedule"}}</span>
|
||
</label>
|
||
<div class="feat-schedule">
|
||
<div class="feat-schedule-days">
|
||
{{ range $i := loop 7 }}
|
||
<label class="feat-day{{ if hasDay $.ScheduleDays (sub $i 1) }} is-on{{ end }}">
|
||
<input name="schedule_days" class="uk-checkbox" type="checkbox" value="{{ sub $i 1 }}" {{ if hasDay $.ScheduleDays (sub $i 1) }}checked{{ end }}>
|
||
<span>{{t $.LangCode (printf "weekday.%d" (sub $i 1))}}</span>
|
||
</label>
|
||
{{ end }}
|
||
</div>
|
||
<div class="feat-schedule-times">
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureScheduleStart"}}</span>
|
||
<input name="schedule_start" class="uk-input" type="time" value="{{ .ScheduleStart }}">
|
||
</label>
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureScheduleEnd"}}</span>
|
||
<input name="schedule_end" class="uk-input" type="time" value="{{ .ScheduleEnd }}">
|
||
</label>
|
||
</div>
|
||
<span class="feat-hint">{{t .LangCode "admin.featureScheduleHint"}}</span>
|
||
</div>
|
||
</div>
|
||
{{ if ne .Key "chat" }}
|
||
<div class="uk-margin-small feat-field">
|
||
<label>
|
||
<span>{{t .LangCode "admin.featureQuotaLimit"}}</span>
|
||
<input name="quota_limit" class="uk-input" type="number" min="0" max="1000000" value="{{ .Control.QuotaLimit }}">
|
||
</label>
|
||
<span class="feat-hint">{{t .LangCode "admin.featureQuotaHint"}}</span>
|
||
</div>
|
||
<div class="feat-quota-line">
|
||
{{t .LangCode "admin.featureQuotaCount"}}:{{ .State.QuotaCount }}
|
||
{{ if .Control.QuotaLimit }}/ {{ .Control.QuotaLimit }}{{ else }}<span class="uk-text-muted">({{t .LangCode "admin.featureQuotaUnlimited"}})</span>{{ end }}
|
||
{{ if .Control.QuotaResetAt }}<br>{{t .LangCode "admin.featureQuotaResetAt"}} {{ .QuotaResetAtStr }}{{ end }}
|
||
</div>
|
||
{{ end }}
|
||
<div class="feat-actions">
|
||
{{ if ne .Key "chat" }}
|
||
<button type="submit" class="uk-button uk-button-default" form="feat-reset-{{ .Key }}">{{t .LangCode "admin.featureResetQuota"}}</button>
|
||
{{ end }}
|
||
<button type="submit" class="uk-button uk-button-primary">{{t .LangCode "admin.featureSave"}}</button>
|
||
</div>
|
||
</form>
|
||
|
||
{{ if ne .Key "chat" }}
|
||
<form id="feat-reset-{{ .Key }}" method="post" action="/user/profile/features/reset-quota">
|
||
{{ .CSRFTokenHTML }}
|
||
<input type="hidden" name="feature" value="{{ .Key }}">
|
||
</form>
|
||
{{ end }}
|
||
|
||
<script>
|
||
(function () {
|
||
var card = document.currentScript && document.currentScript.closest('.feat-card');
|
||
if (!card) return;
|
||
var radios = card.querySelectorAll('input[name="mode"]');
|
||
var windowFields = card.querySelector('.feat-window-fields');
|
||
var recurringFields = card.querySelector('.feat-recurring-fields');
|
||
if (!radios.length) return;
|
||
function sync() {
|
||
var mode = '';
|
||
radios.forEach(function (r) {
|
||
var pill = r.closest('.feat-day');
|
||
if (pill) pill.classList.toggle('is-on', r.checked);
|
||
if (r.checked) mode = r.value;
|
||
});
|
||
if (windowFields) windowFields.classList.toggle('is-hidden', mode !== 'window');
|
||
if (recurringFields) recurringFields.classList.toggle('is-hidden', mode !== 'recurring');
|
||
}
|
||
radios.forEach(function (r) { r.addEventListener('change', sync); });
|
||
sync();
|
||
})();
|
||
</script>
|
||
</div>
|