新站标「一横」:墨圆 + 一道白横,接进两套 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
@@ -7,7 +7,13 @@
|
||||
<meta name="theme-color" content="#1f1d1a" media="(prefers-color-scheme: dark)" />
|
||||
<title>ONE · 一个博客</title>
|
||||
<meta name="description" content="长文与短文,同一种节奏。" />
|
||||
<!-- 方案 A「一横」:SVG 优先(内部有 prefers-color-scheme,深浅皮肤各自变色),
|
||||
PNG 只给不认 SVG 的老浏览器;apple-touch-icon 必须 PNG(iOS 不支持 SVG,
|
||||
且会把透明压成黑底,所以那张铺了纸色实底)。 -->
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
|
||||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
||||
<!--
|
||||
UI 版本在 <html> 上以 data-ui 表达,服务端设置要等 /api/site 才知道。
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 3.4 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 358 B |
Binary file not shown.
|
After Width: | Height: | Size: 700 B |
+10
-32
@@ -1,32 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 128.81 128.17">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: url(#gradient3);
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #000;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.cls-2 {
|
||||
fill: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<linearGradient id="gradient3" x1="57.54" y1="31.44" x2="128.81" y2="31.44" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#ff4d4d"/>
|
||||
<stop offset=".99" stop-color="#f9cb28"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="b">
|
||||
<g>
|
||||
<path class="cls-2" d="M56.32,100.47c0,15.98-11.84,27.61-27.85,27.61S.33,116.45,.33,100.47s11.83-27.45,28.08-27.45,27.91,11.63,27.91,27.45Z"/>
|
||||
<path class="cls-2" d="M120,101.26v19.31c-4.87,4.63-12.9,7.6-21.65,7.6-18.33,0-30-10.49-30-26.7s12.92-28.34,31.07-28.34v28.13h20.58Z"/>
|
||||
<polygon class="cls-1" points="119.7 21.48 128.81 38.51 83.27 62.88 57.54 14.79 85.17 0 101.79 31.06 119.7 21.48"/>
|
||||
<polygon class="cls-2" points="0 63.11 16.54 32.82 .68 8.17 55.98 8.17 40.12 32.82 56.65 63.11 0 63.11"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="ONE">
|
||||
<!-- 方案 A「一横」:墨圆 + 一道白横,既是字母 O 也是汉字「一」。
|
||||
横杠用 fill-rule="evenodd" 挖成真洞(不是叠一块纸色矩形),
|
||||
所以它在任何底色上都是透明的——不需要为深浅皮肤各出一版。 -->
|
||||
<style>
|
||||
.m { fill: #33302b }
|
||||
@media (prefers-color-scheme: dark) { .m { fill: #e8e3d9 } }
|
||||
</style>
|
||||
<path class="m" 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>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 648 B |
@@ -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