fix(ui+permission): 移除联合投稿 / emoji换SVG / 修复移动端浅色适配 / 已排期显示日期 / 隐藏.env提示 / 公开排期档期游客访问

具体改动:

1. feat(投稿表单): 移除 RequestForm.vue 联合投稿功能整套模板+状态+payload+CSS(10处残留)

2. feat(图标): Icon.vue 新增 sparkles/star 图标; 首页档期卡片📅🎵✨和排期列表空状态🎵📅换成 lucide SVG Icon

3. fix(浅色适配): ScheduleList.vue 日期选择弹窗桌面端+移动端(content/header/h3/close-btn/item)全部改为 bg-primary + var text + indigo 主色, 修复竖屏选择日期标题白字看不见

4. feat(歌曲列表): SongList.vue scheduled-tag 内联追加 formatScheduleDate, 徽章+日期双胶囊显示

5. fix(登录): OAuthButtons.vue showPlaceholderHint 强制 false, 隐藏虚线框 .env 配置提示

6. fix(权限): server/middleware/auth.ts + auth-route-policy.ts 双白名单同步追加 /api/expected-play-dates GET 公共访问, 修复未登录 Authentication expired 401
This commit is contained in:
2026-09-19 00:43:46 +08:00
parent 25c7517405
commit 357876a716
8 changed files with 79 additions and 197 deletions
-155
View File
@@ -128,31 +128,6 @@
<span class="btn-text">从往期导入</span>
</button>
</div>
<!-- 联合投稿人区域 -->
<div v-if="user && enableCollaborativeSubmission" class="collaborators-section">
<div class="section-label">联合投稿</div>
<div class="collaborators-list">
<div v-for="user in collaborators" :key="user.id" class="collaborator-tag">
<span class="collaborator-name">{{ user.name }}</span>
<button
class="remove-collaborator"
type="button"
@click="removeCollaborator(user.id)"
>
<Icon :size="12" name="close" />
</button>
</div>
<button
class="add-collaborator-btn"
type="button"
@click="showUserSearchModal = true"
>
<Icon :size="14" name="plus" />
添加
</button>
</div>
</div>
</div>
<div v-if="expectedPlayDateOptions.length > 0" class="expected-play-section">
@@ -652,16 +627,6 @@
@import-success="handleImportSuccess"
/>
<!-- 用户搜索弹窗 -->
<UserSearchModal
v-if="enableCollaborativeSubmission"
v-model:show="showUserSearchModal"
:exclude-ids="[user?.id, ...collaborators.map((u) => u.id)]"
:multiple="true"
title="添加联合投稿人"
@select="handleUserSelect"
/>
<!-- 手动输入弹窗 -->
<Teleport to="body">
<Transition
@@ -853,7 +818,6 @@ import Icon from '../UI/Icon.vue'
import { convertToHttps, validateUrl } from '~/utils/url'
import ImportSongsModal from './ImportSongsModal.vue'
import UserSearchModal from '../Common/UserSearchModal.vue'
const props = defineProps({
loading: {
@@ -869,7 +833,6 @@ const {
guidelines: submissionGuidelines,
initSiteConfig,
enableReplayRequests,
enableCollaborativeSubmission,
enableSubmissionRemarks
} = useSiteConfig()
@@ -983,8 +946,6 @@ const selectedPodcastName = ref('')
const podcastCookie = ref('')
const showPlaylistModal = ref(false)
const showUserSearchModal = ref(false)
const collaborators = ref([])
const songService = useSongs()
const playTimes = ref([])
@@ -1045,22 +1006,6 @@ const handleImportSuccess = async () => {
}
}
const handleUserSelect = (users) => {
if (Array.isArray(users)) {
// 过滤掉已存在的
const newUsers = users.filter((u) => !collaborators.value.some((c) => c.id === u.id))
collaborators.value.push(...newUsers)
} else if (users) {
if (!collaborators.value.some((c) => c.id === users.id)) {
collaborators.value.push(users)
}
}
}
const removeCollaborator = (userId) => {
collaborators.value = collaborators.value.filter((c) => c.id !== userId)
}
// 获取播出时段
const fetchPlayTimes = async () => {
loadingPlayTimes.value = true
@@ -1456,13 +1401,6 @@ watch(
}
)
watch(enableCollaborativeSubmission, (enabled) => {
if (!enabled) {
showUserSearchModal.value = false
collaborators.value = []
}
})
watch(enableSubmissionRemarks, (enabled) => {
if (!enabled) {
submissionNote.value = ''
@@ -2288,7 +2226,6 @@ const submitSong = async (result, options = {}) => {
playUrl: selectedUrl.value || null,
submissionNote: submissionNote.value.trim() || null,
submissionNotePublic: submissionNotePublic.value,
collaborators: collaborators.value.map((u) => u.id),
bilibiliCid: bilibiliCid || null,
bilibiliPage: bilibiliPage,
expectedPlayDate: expectedPlayDate.value || null,
@@ -2678,7 +2615,6 @@ const resetAfterSubmit = () => {
manualArtist.value = ''
manualCover.value = ''
manualPlayUrl.value = ''
collaborators.value = []
submissionNote.value = ''
submissionNotePublic.value = true
// 重置URL验证状态
@@ -3268,83 +3204,6 @@ defineExpose({
box-shadow: 0 2px 6px rgba(79, 70, 229, 0.1);
}
/* 联合投稿人区域 */
.collaborators-section {
display: flex;
align-items: center;
gap: 1rem;
flex: 1;
min-width: 200px;
}
.section-label {
font-family: 'MiSans', sans-serif;
font-weight: 700;
font-size: 16px;
color: var(--text-primary, #09090b);
white-space: nowrap;
flex-shrink: 0;
}
.collaborators-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
.collaborator-tag {
display: flex;
align-items: center;
gap: 0.5rem;
background: rgba(79, 70, 229, 0.08);
border: 1px solid rgba(79, 70, 229, 0.2);
border-radius: 10px;
padding: 0.3rem 0.6rem;
font-size: 13px;
color: var(--primary, #4f46e5);
font-weight: 600;
}
.remove-collaborator {
background: none;
border: none;
color: var(--primary, #4f46e5);
cursor: pointer;
display: flex;
align-items: center;
padding: 0;
opacity: 0.7;
transition: opacity 0.2s;
}
.remove-collaborator:hover {
opacity: 1;
color: #4338ca;
}
.add-collaborator-btn {
display: flex;
align-items: center;
gap: 0.3rem;
background: var(--bg-secondary, #f4f4f5);
border: 1px solid var(--border-secondary, #e4e4e7);
border-radius: 10px;
padding: 0.45rem 0.9rem;
font-size: 13px;
font-weight: 600;
color: var(--text-secondary, #52525b);
cursor: pointer;
transition: all 0.2s ease;
}
.add-collaborator-btn:hover {
background: var(--primary, #4f46e5);
color: #ffffff;
border-color: var(--primary, #4f46e5);
box-shadow: 0 4px 10px rgba(79, 70, 229, 0.18);
}
/* 自定义复选框样式 */
.custom-checkbox-wrapper {
display: flex;
@@ -5122,20 +4981,6 @@ defineExpose({
min-width: unset; /* 移除桌面端的最小宽度限制 */
}
.collaborators-section {
flex-direction: row;
align-items: center;
gap: 1rem;
margin-bottom: 1rem;
flex: none;
width: 100%;
flex-wrap: wrap;
}
.section-label {
font-size: 14px;
}
.search-label {
font-size: 14px;
}