管理员免登录直接评论:后台会话映射站主身份(免审核、不可被禁言)+ 评论作者字段对齐后端 user

- 公开 API 解析顺序:读者 cookie → 管理员 cookie(provider=admin 站主读者,名字取站点作者名)
- 站主发评论跳过禁言与审核;后台禁言接口拒绝站主身份
- CommentItem 读 c.author 改为 c.user(后端实际字段),站主徽章按 provider 判断
This commit is contained in:
Sakurasan
2026-09-28 00:43:25 +08:00
parent 0929f880e3
commit 1a2db5ddac
5 changed files with 80 additions and 37 deletions
@@ -25,14 +25,14 @@ const props = defineProps({
const s = props.api.s
const EDIT_WINDOW_MS = 10 * 60 * 1000
const name = computed(() => (props.c.author && props.c.author.name) || '已注销用户')
const name = computed(() => (props.c.user && props.c.user.name) || '已注销用户')
const relativeTime = computed(() => relativeDate(props.c.created_at))
const isOwner = computed(() => !!(props.c.author && props.c.author.is_owner))
const isMine = computed(() => !!(reader.user && props.c.author && reader.user.id === props.c.author.id))
const isOwner = computed(() => !!(props.c.user && props.c.user.provider === 'admin'))
const isMine = computed(() => !!(reader.user && props.c.user && reader.user.id === props.c.user.id))
// 外链:优先作者自填的 url,其次 GitHub 主页
const authorHref = computed(() => {
const a = props.c.author
const a = props.c.user
if (!a) return ''
if (a.url) return a.url
if (a.provider === 'github' && a.handle) return `https://github.com/${a.handle}`
@@ -41,12 +41,11 @@ const authorHref = computed(() => {
const canEdit = computed(() => {
if (props.c.is_deleted) return false
if (isOwner.value) return true
if (!isMine.value) return false
const t = new Date(props.c.created_at).getTime()
return Number.isFinite(t) && Date.now() - t <= EDIT_WINDOW_MS
})
const canDelete = computed(() => !props.c.is_deleted && (isMine.value || isOwner.value))
const canDelete = computed(() => !props.c.is_deleted && isMine.value)
const replying = computed(() => s.replyTo && s.replyTo.id === props.c.id)
const editing = computed(() => s.editing && s.editing.id === props.c.id)
@@ -118,7 +117,7 @@ const atInline = computed(
function replyNameOf(r) {
if (!r.parent_id || r.parent_id === props.c.id) return ''
const t = (props.c.replies || []).find((x) => x.id === r.parent_id)
return t ? (t.author && t.author.name) || '' : ''
return t ? (t.user && t.user.name) || '' : ''
}
</script>
@@ -126,15 +125,15 @@ function replyNameOf(r) {
<li class="cm-item" :class="{ 'is-deleted': c.is_deleted, 'is-reply': depth > 0 }">
<div class="cm-av" :class="{ 'is-owner': isOwner }">
<img
v-if="c.author && c.author.avatar_url"
:src="c.author.avatar_url"
v-if="c.user && c.user.avatar_url"
:src="c.user.avatar_url"
:alt="`${name} 的头像`"
loading="lazy"
>
<span v-else class="cm-av-fb">{{ name.slice(0, 1) }}</span>
<i v-if="c.author && c.author.provider" class="cm-pv" :title="PROVIDER_LABEL[c.author.provider] || c.author.provider">
<svg v-if="BRANDS[c.author.provider]" viewBox="0 0 24 24" aria-hidden="true">
<path :d="BRANDS[c.author.provider]" />
<i v-if="c.user && c.user.provider" class="cm-pv" :title="PROVIDER_LABEL[c.user.provider] || c.user.provider">
<svg v-if="BRANDS[c.user.provider]" viewBox="0 0 24 24" aria-hidden="true">
<path :d="BRANDS[c.user.provider]" />
</svg>
</i>
</div>