新站标「一横」:墨圆 + 一道白横,接进两套 UI 与图标
立意:既是字母 O 也是汉字「一」,对应站名 ONE / 一个博客。 - favicon.svg 重画:横杠用 fill-rule=evenodd 挖成真洞而不是叠一块纸色矩形, 所以纸感 / 墨色暗端 / 后台卡片任何底色都直接透过去,不必为皮肤各出一版; SVG 内带 prefers-color-scheme,标签页深浅自动翻色 - 补 favicon-16/32.png(不认 SVG 的老浏览器)与 apple-touch-icon.png 180 (iOS 不支持 SVG 且会把透明压成黑底,故铺纸色实底)。PNG 由临时 Go 程序 按 8x8 子采样光栅化生成,生成器未入库,产物是资产 - LogoMark.vue 内联 SVG 组件:颜色跟 currentColor,尺寸由外层给 - 接入 6 处:classic 桌面左栏品牌位(原来是个排版字符 ○)、移动顶栏 brand、 时间线头像位、详情页头像位、快发盒头像位;vivid 顶栏与底部 dock 品牌标记 (右下角绿色在线点保留,它是「有人在写」的信号,不属于被替换的部分) - 顺带清理:三处只为算首字母的死代码(initial 与只服务于它的 userName)、 vivid 里一条被同特指度靠后规则完全覆盖的 .av 死规则;标记 wrapper 统一加 flex:none,否则站名一长会被压成椭圆
This commit is contained in:
1 parent
e6e4bdc71c
commit
7e302c51a6
13 files changed
+87
-84
No files matched your search
@@ -3,6 +3,7 @@ import { computed } from 'vue'
|
||||
import { site } from '../site'
|
||||
import { socialIcon } from '../socialIcons'
|
||||
import ThemeSwitcher from './ThemeSwitcher.vue'
|
||||
import LogoMark from './LogoMark.vue'
|
||||
|
||||
// vivid 用顶部导航(VividNav)代替左栏。这里直接不渲染。
|
||||
const isVivid = computed(() => site.ui_id === 'vivid')
|
||||
@@ -15,7 +16,7 @@ const social = computed(() => (site.social_links || []).filter((s) => s && s.url
|
||||
<aside v-if="!isVivid" class="rail-left">
|
||||
<div class="inner">
|
||||
<RouterLink to="/" class="brand">
|
||||
<span class="mark">○</span>
|
||||
<span class="mark"><LogoMark /></span>
|
||||
<span class="name">{{ site.site_title || 'ONE' }}</span>
|
||||
</RouterLink>
|
||||
<p class="desc">{{ site.site_desc }}</p>
|
||||
@@ -86,9 +87,13 @@ const social = computed(() => (site.social_links || []).filter((s) => s && s.url
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* 原来这里是一个排版字符 ○ 充当标记,换成真站标。
|
||||
flex:none:它是 .brand(flex)的子项,不锁住会被长站名压成椭圆 */
|
||||
.mark {
|
||||
color: var(--accent);
|
||||
font-size: 18px;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
flex: none;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.name {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<script setup>
|
||||
// 站标「一横」:墨圆 + 一道白横 —— 字母 O 与汉字「一」同形,对应站名 ONE / 一个博客。
|
||||
//
|
||||
// 横杠是 fill-rule="evenodd" 挖出来的真洞,不是叠一块纸色矩形,所以任何底色
|
||||
// (纸感 / 墨色暗端 / 后台卡片)都直接透过去,不必为皮肤各出一版。
|
||||
// 颜色跟随 currentColor,尺寸由外层容器决定。
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<svg class="logo-mark" viewBox="0 0 64 64" aria-hidden="true" focusable="false">
|
||||
<path
|
||||
fill="currentColor"
|
||||
fill-rule="evenodd"
|
||||
d="M32 4a28 28 0 1 0 0 56 28 28 0 1 0 0-56Zm-16 23.5h32a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H16a1 1 0 0 1-1-1v-7a1 1 0 0 1 1-1Z"
|
||||
/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.logo-mark {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
</style>
|
||||
@@ -5,6 +5,7 @@ import { site } from '../site'
|
||||
import { openLightbox } from '../lightbox'
|
||||
import { relativeDate, stripTags, minutesLabel, sanitizeHtml, thumbURL, thumbifyHtml } from '../utils'
|
||||
import LinkCard from './LinkCard.vue'
|
||||
import LogoMark from './LogoMark.vue'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -34,15 +35,13 @@ const summaryText = computed(() => {
|
||||
return text.length > 110 ? text.slice(0, 110) + '…' : text
|
||||
})
|
||||
|
||||
const initial = computed(() => (site.author_name || 'O').trim().slice(0, 1).toUpperCase())
|
||||
|
||||
// 配图缩略图宽度:单图全宽格取宽一些,多图小格 480 足够(2x 屏也清晰)
|
||||
const gridW = computed(() => (props.post.images && props.post.images.length === 1 ? 720 : 480))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<article class="row-feed" :class="{ short: isShort }" @click="openPost">
|
||||
<div class="avatar" aria-hidden="true">{{ initial }}</div>
|
||||
<div class="avatar"><LogoMark /></div>
|
||||
|
||||
<div class="body">
|
||||
<div class="byline">
|
||||
@@ -126,18 +125,12 @@ const gridW = computed(() => (props.post.images && props.post.images.length ===
|
||||
background: var(--paper-sunken);
|
||||
}
|
||||
|
||||
/* 站标本身就是个圆,所以原来那层 accent-soft 圆底 / 衬线首字母都不需要了,
|
||||
只留尺寸与颜色。想换回降饱和蓝只需改 color 一行。 */
|
||||
.avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--serif);
|
||||
font-size: 17px;
|
||||
user-select: none;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.byline {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { adminApi } from '../api'
|
||||
import LogoMark from './LogoMark.vue'
|
||||
|
||||
// Twitter 式短文发布盒,挂在时间线顶部。
|
||||
//
|
||||
@@ -17,7 +18,6 @@ import { adminApi } from '../api'
|
||||
const emit = defineEmits(['published'])
|
||||
|
||||
const shown = ref(false)
|
||||
const userName = ref('')
|
||||
const draft = ref('')
|
||||
const publishing = ref(false)
|
||||
const error = ref('')
|
||||
@@ -53,7 +53,6 @@ function removeImage(i) {
|
||||
images.value.splice(i, 1)
|
||||
}
|
||||
|
||||
const initial = computed(() => (userName.value || 'O').trim().slice(0, 1).toUpperCase())
|
||||
const canPost = computed(
|
||||
() => (draft.value.trim().length > 0 || images.value.length > 0) && !publishing.value
|
||||
)
|
||||
@@ -62,7 +61,6 @@ onMounted(async () => {
|
||||
try {
|
||||
const d = await adminApi.me()
|
||||
if (d.user) {
|
||||
userName.value = String(d.user)
|
||||
shown.value = true
|
||||
}
|
||||
} catch {
|
||||
@@ -110,7 +108,7 @@ async function publish() {
|
||||
<!-- 桌面:内联 -->
|
||||
<div class="qs-inline">
|
||||
<div class="qs-card">
|
||||
<span class="qs-av">{{ initial }}</span>
|
||||
<span class="qs-av"><LogoMark /></span>
|
||||
<div class="qs-body">
|
||||
<textarea v-model="draft" class="qs-input" rows="2" placeholder="记点短的…" @keydown="onKey" />
|
||||
<div v-if="images.length" class="qs-thumbs">
|
||||
@@ -197,17 +195,12 @@ async function publish() {
|
||||
background: var(--card);
|
||||
}
|
||||
|
||||
/* 站标自身是圆,去掉原来的 accent-soft 圆底与首字母字号;flex:none 防被压扁 */
|
||||
.qs-av {
|
||||
flex: none;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
display: grid;
|
||||
place-items: center;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.qs-body {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { site } from '../site'
|
||||
import NavBurger from './NavBurger.vue'
|
||||
import LogoMark from './LogoMark.vue'
|
||||
|
||||
// 手机端导航。原来把 5 个链接平铺在顶栏里:375px 挤成一排小字,
|
||||
// 触点只有十几像素高,320px 的屏还会折行。改成 brand + 汉堡钮,
|
||||
@@ -105,7 +106,10 @@ onBeforeUnmount(() => {
|
||||
<template>
|
||||
<!-- 窄屏时左栏收起,导航回到顶部;下滑隐藏、上滑唤回 -->
|
||||
<header class="topbar" :class="{ hidden }">
|
||||
<RouterLink to="/" class="brand">{{ site.site_title || 'ONE' }}</RouterLink>
|
||||
<RouterLink to="/" class="brand">
|
||||
<span class="mk"><LogoMark /></span>
|
||||
<span>{{ site.site_title || 'ONE' }}</span>
|
||||
</RouterLink>
|
||||
<NavBurger
|
||||
ref="burger"
|
||||
class="burger"
|
||||
@@ -179,6 +183,16 @@ onBeforeUnmount(() => {
|
||||
font-family: var(--serif);
|
||||
font-size: 17px;
|
||||
color: var(--ink);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.brand .mk {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
flex: none;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.burger {
|
||||
|
||||
@@ -3,6 +3,7 @@ import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import { RouterLink, useRoute } from 'vue-router'
|
||||
import { site } from '../../site'
|
||||
import NavBurger from '../../components/NavBurger.vue'
|
||||
import LogoMark from '../../components/LogoMark.vue'
|
||||
|
||||
// 余白顶栏。对应设计稿的 <header class="top">:品牌 / 导航 / 操作三块,
|
||||
// 滚动过 8px 加 .scrolled(设计稿的「四态里的第一态」)。
|
||||
@@ -27,7 +28,6 @@ const links = [
|
||||
{ to: '/about', label: '关于', en: 'About' }
|
||||
]
|
||||
|
||||
const initial = () => (site.author_name || site.site_title || 'O').trim().slice(0, 1).toUpperCase()
|
||||
const title = () => site.site_title?.split(/[·|]/)[0]?.trim() || 'ONE'
|
||||
|
||||
function isOn(l) {
|
||||
@@ -94,7 +94,7 @@ function toggleTheme() {
|
||||
<header class="top" :class="{ scrolled }">
|
||||
<div class="top-in">
|
||||
<RouterLink class="brand" to="/">
|
||||
<span class="av">{{ initial() }}</span>
|
||||
<span class="av"><LogoMark /></span>
|
||||
<span>{{ title() }}</span>
|
||||
</RouterLink>
|
||||
<nav class="nav" aria-label="站点导航">
|
||||
@@ -115,7 +115,7 @@ function toggleTheme() {
|
||||
必须待在 .top 外面:.top 有 backdrop-filter,会给 fixed 后代当包含块。 -->
|
||||
<div class="dock">
|
||||
<RouterLink class="dock-brand" to="/">
|
||||
<span class="av">{{ initial() }}</span>
|
||||
<span class="av"><LogoMark /></span>
|
||||
<span>{{ title() }}</span>
|
||||
</RouterLink>
|
||||
<NavBurger
|
||||
|
||||
@@ -15,15 +15,8 @@ html[data-ui='vivid'] .brand {display:flex;align-items:center;gap:10px;
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
html[data-ui='vivid'] .brand:hover {transform:scale(1.04)}
|
||||
}
|
||||
/* .av 品牌标记:顶栏一枚,菜单里那枚随菜单头一起撤了(顶栏浮在菜单上) */
|
||||
html[data-ui='vivid'] .brand .av {width:30px;height:30px;border-radius:50%;
|
||||
background:linear-gradient(135deg,var(--accent),var(--accent-deep));
|
||||
display:grid;place-items:center;color:#fff;font-size:13px;font-weight:800;
|
||||
box-shadow:0 0 0 2px var(--paper),0 0 0 3.5px var(--accent-soft);
|
||||
position:relative;}
|
||||
html[data-ui='vivid'] .brand .av::after {content:"";position:absolute;right:-1px;bottom:-1px;
|
||||
width:9px;height:9px;border-radius:50%;
|
||||
background:#34c759;border:2px solid var(--paper);}
|
||||
/* .av 品牌标记:原来这里是一条 .brand .av 规则,但它被下面 :is(.brand,.dock-brand)
|
||||
那条同特指度、且位置更靠后的规则完整覆盖了——等于死规则。合并成一条,避免两处漂移。 */
|
||||
html[data-ui='vivid'] .nav {display:flex;gap:2px;flex:1;justify-content:center}
|
||||
html[data-ui='vivid'] .nav a {position:relative;font-size:13.5px;font-weight:600;color:var(--soft);
|
||||
padding:8px 14px;border-radius:999px;
|
||||
@@ -74,9 +67,10 @@ html[data-ui='vivid'] .dock-brand {display:flex;align-items:center;gap:9px;
|
||||
@media (max-width:720px) {
|
||||
html[data-ui='vivid'] .dock {display:flex}
|
||||
}
|
||||
html[data-ui='vivid'] :is(.brand, .dock-brand) .av {width:30px;height:30px;border-radius:50%;
|
||||
background:linear-gradient(135deg,var(--accent),var(--accent-deep));
|
||||
display:grid;place-items:center;color:#fff;font-size:13px;font-weight:800;
|
||||
/* 品牌标记换成站标「一横」:它自身就是圆,所以去掉渐变圆盘与首字母字号;
|
||||
右下角那颗绿色在线点保留(它是「有人在写」的信号,不属于被替换的部分)。 */
|
||||
html[data-ui='vivid'] :is(.brand, .dock-brand) .av {width:30px;height:30px;flex:none;
|
||||
color:var(--ink);
|
||||
box-shadow:0 0 0 2px var(--paper),0 0 0 3.5px var(--accent-soft);
|
||||
position:relative;}
|
||||
html[data-ui='vivid'] :is(.brand, .dock-brand) .av::after {content:"";position:absolute;right:-1px;bottom:-1px;
|
||||
|
||||
@@ -6,6 +6,7 @@ import RightRail from '../components/RightRail.vue'
|
||||
import YohakuArticle from '../ui/yohaku/YohakuArticle.vue'
|
||||
import CommentSection from '../components/comments/CommentSection.vue'
|
||||
import LinkCard from '../components/LinkCard.vue'
|
||||
import LogoMark from '../components/LogoMark.vue'
|
||||
import { openLightbox } from '../lightbox'
|
||||
import { publicApi } from '../api'
|
||||
import { site, applyDocTitle } from '../site'
|
||||
@@ -68,7 +69,6 @@ onBeforeUnmount(() => window.removeEventListener('scroll', onScroll))
|
||||
watch(() => route.params.slug, load)
|
||||
|
||||
const isShort = computed(() => post.value && post.value.kind === 'short')
|
||||
const initial = computed(() => (site.author_name || 'O').trim().slice(0, 1).toUpperCase())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -100,7 +100,7 @@ const initial = computed(() => (site.author_name || 'O').trim().slice(0, 1).toUp
|
||||
<article v-else class="wrap" :class="{ short: isShort }">
|
||||
<header class="head">
|
||||
<div class="byline">
|
||||
<div class="avatar">{{ initial }}</div>
|
||||
<div class="avatar"><LogoMark /></div>
|
||||
<div class="who">
|
||||
<span class="author">{{ site.author_name || 'ONE' }}</span>
|
||||
<span class="sub">
|
||||
@@ -188,17 +188,11 @@ const initial = computed(() => (site.author_name || 'O').trim().slice(0, 1).toUp
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* 站标自身是圆,原来的 accent-soft 圆底与衬线首字母一并去掉,只留尺寸与颜色 */
|
||||
.avatar {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 50%;
|
||||
background: var(--accent-soft);
|
||||
color: var(--accent);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: var(--serif);
|
||||
font-size: 18px;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.who {
|
||||
|
||||
Reference in new issue
Block a user