Merge branch 'dev'
Deploy / deploy (push) Failing after 14m34s

This commit is contained in:
ByungCheol
2026-06-28 12:45:29 +09:00
2 changed files with 79 additions and 101 deletions
+53 -80
View File
@@ -141,9 +141,6 @@ const recommenders = computed(() => post.value?.recommenders || [])
const previewRecommenders = computed(() => recommenders.value.slice(0, 10)) const previewRecommenders = computed(() => recommenders.value.slice(0, 10))
const extraRecommenders = computed(() => Math.max(0, (post.value?.upCount || 0) - 10)) const extraRecommenders = computed(() => Math.max(0, (post.value?.upCount || 0) - 10))
const showRecommenders = ref(false) const showRecommenders = ref(false)
function openRecommenders() {
if (post.value?.upCount) showRecommenders.value = true
}
onMounted(load) onMounted(load)
</script> </script>
@@ -161,11 +158,12 @@ onMounted(load)
:name="post.authorName" :name="post.authorName"
:google-picture="post.authorGooglePicture" :google-picture="post.authorGooglePicture"
:profile-image="post.authorProfileImage" :profile-image="post.authorProfileImage"
:size="26" :size="16"
/> />
<span class="meta-author">{{ post.authorName }}</span> <span class="meta-author">{{ post.authorName }}</span>
<span>· {{ formatRelative(post.createdAt) }}</span> <span>· {{ formatRelative(post.createdAt) }}</span>
<span>· 조회 {{ post.viewCount }}</span> <span>· 조회 {{ post.viewCount }}</span>
<span>· 추천 {{ post.upCount || 0 }}</span>
</div> </div>
</header> </header>
@@ -194,23 +192,37 @@ onMounted(load)
>👎 비추천 <b>{{ post.downCount || 0 }}</b></button> >👎 비추천 <b>{{ post.downCount || 0 }}</b></button>
</div> </div>
<!-- 추천자 (아바타 최대 10 + 초과 안내, 클릭 전체 목록) --> <!-- 추천자 (아바타 최대 10 + 초과 안내, 클릭 하단에 전체 목록 펼침) -->
<div v-if="!restricted && post.upCount" class="recommenders" @click="openRecommenders"> <div v-if="!restricted && post.upCount" class="recommenders-wrap">
<div class="rec-avatars"> <button type="button" class="recommenders" @click="showRecommenders = !showRecommenders">
<span class="rec-avatars">
<UserAvatar <UserAvatar
v-for="r in previewRecommenders" v-for="r in previewRecommenders"
:key="r.memberId" :key="r.memberId"
:name="r.name" :name="r.name"
:google-picture="r.googlePicture" :google-picture="r.googlePicture"
:profile-image="r.profileImage" :profile-image="r.profileImage"
:size="28" :size="16"
class="rec-avatar" class="rec-avatar"
/> />
</div> </span>
<span class="rec-label"> <span class="rec-label">
<template v-if="extraRecommenders > 0">+{{ extraRecommenders }}명이 추천했습니다</template> <template v-if="extraRecommenders > 0">+{{ extraRecommenders }}명이 추천했습니다</template>
<template v-else>{{ post.upCount }}명이 추천했습니다</template> <template v-else>{{ post.upCount }}명이 추천했습니다</template>
</span> </span>
<span class="rec-toggle">{{ showRecommenders ? '▲' : '▼' }}</span>
</button>
<ul v-if="showRecommenders" class="rec-inline-list">
<li v-for="r in recommenders" :key="r.memberId">
<UserAvatar
:name="r.name"
:google-picture="r.googlePicture"
:profile-image="r.profileImage"
:size="16"
/>
<span class="rec-name">{{ r.name }}</span>
</li>
</ul>
</div> </div>
<!-- 태그 (본문 아래) --> <!-- 태그 (본문 아래) -->
@@ -243,7 +255,7 @@ onMounted(load)
:name="c.authorName" :name="c.authorName"
:google-picture="c.authorGooglePicture" :google-picture="c.authorGooglePicture"
:profile-image="c.authorProfileImage" :profile-image="c.authorProfileImage"
:size="24" :size="16"
/> />
<strong>{{ c.authorName }}</strong> <strong>{{ c.authorName }}</strong>
<span class="comment-date">{{ formatRelative(c.createdAt) }}</span> <span class="comment-date">{{ formatRelative(c.createdAt) }}</span>
@@ -279,29 +291,6 @@ onMounted(load)
</form> </form>
</section> </section>
</article> </article>
<!-- 추천자 전체 목록 (아바타 + 이름) -->
<Teleport to="body">
<div v-if="showRecommenders" class="rec-modal-backdrop" @click.self="showRecommenders = false">
<div class="rec-modal" role="dialog" aria-modal="true" aria-label="추천한 사람">
<div class="rec-modal-head">
<strong>추천한 사람 {{ post?.upCount || 0 }}</strong>
<IconBtn icon="close" title="닫기" size="sm" @click="showRecommenders = false" />
</div>
<ul class="rec-modal-list">
<li v-for="r in recommenders" :key="r.memberId">
<UserAvatar
:name="r.name"
:google-picture="r.googlePicture"
:profile-image="r.profileImage"
:size="32"
/>
<span class="rec-name">{{ r.name }}</span>
</li>
</ul>
</div>
</div>
</Teleport>
</section> </section>
</template> </template>
@@ -362,26 +351,30 @@ h1 {
background: rgba(230, 126, 34, 0.08); background: rgba(230, 126, 34, 0.08);
} }
/* 추천자 */ /* 추천자 */
.recommenders-wrap {
margin-bottom: 0.75rem;
}
.recommenders { .recommenders {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 0.6rem; gap: 0.6rem;
flex-wrap: wrap; flex-wrap: wrap;
width: 100%;
padding: 0.6rem 0.8rem; padding: 0.6rem 0.8rem;
border: 1px solid var(--color-border); border: 1px solid var(--color-border);
border-radius: 8px; border-radius: 8px;
background: var(--color-background-soft); background: var(--color-background-soft);
cursor: pointer; cursor: pointer;
margin-bottom: 0.5rem; text-align: left;
} }
.recommenders:hover { .recommenders:hover {
background: var(--color-background-mute); background: var(--color-background-mute);
} }
.rec-avatars { .rec-avatars {
display: flex; display: inline-flex;
} }
.rec-avatar { .rec-avatar {
margin-left: -6px; margin-left: -4px;
box-shadow: 0 0 0 2px var(--color-background-soft); box-shadow: 0 0 0 2px var(--color-background-soft);
} }
.rec-avatar:first-child { .rec-avatar:first-child {
@@ -392,6 +385,30 @@ h1 {
color: var(--color-text); color: var(--color-text);
opacity: 0.85; opacity: 0.85;
} }
.rec-toggle {
margin-left: auto;
font-size: 0.7rem;
opacity: 0.6;
}
.rec-inline-list {
list-style: none;
margin: 0.4rem 0 0;
padding: 0.3rem 0.5rem;
border: 1px solid var(--color-border);
border-radius: 8px;
display: flex;
flex-direction: column;
gap: 0.1rem;
}
.rec-inline-list li {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.35rem 0.4rem;
}
.rec-name {
font-size: 0.9rem;
}
.tags { .tags {
display: flex; display: flex;
gap: 0.4rem; gap: 0.4rem;
@@ -520,50 +537,6 @@ button.notice-btn {
border-color: #e67e22; border-color: #e67e22;
color: #e67e22; color: #e67e22;
} }
/* 추천자 모달 */
.rec-modal-backdrop {
position: fixed;
inset: 0;
z-index: 2000;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
}
.rec-modal {
width: 100%;
max-width: 360px;
max-height: 70vh;
display: flex;
flex-direction: column;
background: var(--color-background);
border: 1px solid var(--color-border);
border-radius: 10px;
overflow: hidden;
}
.rec-modal-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.85rem 1rem;
border-bottom: 1px solid var(--color-border);
}
.rec-modal-list {
list-style: none;
margin: 0;
padding: 0.5rem 0;
overflow-y: auto;
}
.rec-modal-list li {
display: flex;
align-items: center;
gap: 0.6rem;
padding: 0.5rem 1rem;
}
.rec-name {
font-size: 0.95rem;
}
.comment-form { .comment-form {
margin-top: 1rem; margin-top: 1rem;
} }
+14 -9
View File
@@ -157,6 +157,7 @@ onMounted(loadTags)
<th>제목</th> <th>제목</th>
<th class="col-author">작성자</th> <th class="col-author">작성자</th>
<th class="col-num">조회</th> <th class="col-num">조회</th>
<th class="col-recommend">추천</th>
<th class="col-date">작성일</th> <th class="col-date">작성일</th>
</tr> </tr>
</thead> </thead>
@@ -171,7 +172,6 @@ onMounted(loadTags)
<span class="title">{{ p.title }}</span> <span class="title">{{ p.title }}</span>
<span v-if="p.blocked" class="blocked-badge">제한</span> <span v-if="p.blocked" class="blocked-badge">제한</span>
<span v-if="p.commentCount" class="comment-count">[{{ p.commentCount }}]</span> <span v-if="p.commentCount" class="comment-count">[{{ p.commentCount }}]</span>
<span v-if="p.upCount" class="recommend-count">👍 {{ p.upCount }}</span>
</template> </template>
</td> </td>
<td class="col-author"> <td class="col-author">
@@ -180,12 +180,13 @@ onMounted(loadTags)
:name="p.authorName" :name="p.authorName"
:google-picture="p.authorGooglePicture" :google-picture="p.authorGooglePicture"
:profile-image="p.authorProfileImage" :profile-image="p.authorProfileImage"
:size="22" :size="16"
/> />
<span class="author-name">{{ p.authorName }}</span> <span class="author-name">{{ p.authorName }}</span>
</span> </span>
</td> </td>
<td class="col-num">{{ p.viewCount }}</td> <td class="col-num">{{ p.viewCount }}</td>
<td class="col-recommend">{{ p.upCount || 0 }}</td>
<td class="col-date">{{ formatRelative(p.createdAt) }}</td> <td class="col-date">{{ formatRelative(p.createdAt) }}</td>
</tr> </tr>
</tbody> </tbody>
@@ -318,6 +319,10 @@ button:disabled {
width: 60px; width: 60px;
text-align: center; text-align: center;
} }
.col-recommend {
width: 56px;
text-align: center;
}
.col-author { .col-author {
width: 130px; width: 130px;
} }
@@ -341,12 +346,6 @@ button:disabled {
color: hsla(160, 100%, 37%, 1); color: hsla(160, 100%, 37%, 1);
font-size: 0.85rem; font-size: 0.85rem;
} }
.recommend-count {
margin-left: 0.35rem;
color: var(--color-text);
opacity: 0.7;
font-size: 0.82rem;
}
.blocked-msg { .blocked-msg {
color: #c0392b; color: #c0392b;
font-size: 0.9rem; font-size: 0.9rem;
@@ -517,9 +516,15 @@ button:disabled {
.post-table .col-num::before { .post-table .col-num::before {
content: '· 조회 '; content: '· 조회 ';
} }
.post-table .col-date { .post-table .col-recommend {
order: 4; order: 4;
} }
.post-table .col-recommend::before {
content: '· 추천 ';
}
.post-table .col-date {
order: 5;
}
.post-table .col-date::before { .post-table .col-date::before {
content: '· '; content: '· ';
} }