Files
OJ2/apps/web/src/oj/rank/components/MoodPopover.vue
T
xuyueandClaude Opus 5.5 28a09831b5 feat(排名): 个性签名直接写在名单上,不用再指着小引号才看得到
- 桌面:写了签名的同学名字下面多一行,把签名写出来(一行二十来个字,长的指上去看全文);两栏按高度对半分
- 手机:签名从名字后面(只剩三五个字)挪到名字下面一行
- 自己还没写的,名单里自己那行有「写一句个性签名」,和「你」卡点开的是同一个框

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 22:02:15 +08:00

93 lines
2.2 KiB
Vue

<script setup lang="ts">
import { MOOD_MAX } from "@oj2/contract"
import { updateProfile } from "oj/api"
import { useUserStore } from "shared/store/user"
/**
* 就地改个性签名:「你」卡上的签名、赛道里自己那行的「写一句个性签名」点开的是同一个框。
* 触发按钮由调用方放进默认插槽。
*/
const props = defineProps<{ mood: string | null }>()
const emit = defineEmits<{ saved: [mood: string | null] }>()
const message = useMessage()
const userStore = useUserStore()
const inputId = useId()
const editing = ref(false)
const draft = ref("")
const saving = ref(false)
watch(editing, (open) => {
if (open) draft.value = props.mood ?? ""
})
async function save() {
const mood = draft.value.trim()
if (mood.length > MOOD_MAX) {
message.warning(`个性签名最多 ${MOOD_MAX} 个字`)
return
}
saving.value = true
try {
await updateProfile({ mood })
if (userStore.profile) userStore.profile.mood = mood || null
emit("saved", mood || null)
editing.value = false
message.success(mood ? "签名改好了" : "签名清空了")
} catch {
message.error("没保存上,再试一次")
} finally {
saving.value = false
}
}
</script>
<template>
<n-popover
v-model:show="editing"
trigger="click"
placement="bottom-start"
:style="{ width: '300px' }"
>
<template #trigger>
<slot />
</template>
<form class="mood-form" @submit.prevent="save">
<label class="mood-label" :for="inputId">个性签名</label>
<n-input
v-model:value="draft"
:input-props="{ id: inputId }"
:maxlength="MOOD_MAX"
show-count
clearable
placeholder="写点什么,让大家认识你"
autofocus
/>
<div class="mood-actions">
<n-button size="small" @click="editing = false">取消</n-button>
<n-button size="small" type="primary" attr-type="submit" :loading="saving"> 保存 </n-button>
</div>
</form>
</n-popover>
</template>
<style scoped>
.mood-form {
display: flex;
flex-direction: column;
gap: 8px;
}
.mood-label {
font-size: var(--oj-fs-sec);
font-weight: 600;
}
.mood-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
</style>