feat: add portfolio external links
This commit is contained in:
+34
-2
@@ -15,6 +15,16 @@ const el = (tag, className, html) => {
|
||||
return node;
|
||||
};
|
||||
|
||||
const externalLink = (className, href, text, ariaLabel = text) => {
|
||||
const node = el("a", className);
|
||||
node.href = href;
|
||||
node.target = "_blank";
|
||||
node.rel = "noreferrer";
|
||||
node.textContent = text;
|
||||
node.setAttribute("aria-label", ariaLabel);
|
||||
return node;
|
||||
};
|
||||
|
||||
/* ---------- 各轮回答内容 ---------- */
|
||||
|
||||
function bootContent(answer) {
|
||||
@@ -70,9 +80,24 @@ function projectsContent(answer) {
|
||||
projects.forEach((p) => {
|
||||
const block = el("article", "project-block gen");
|
||||
const head = el("div", "project-head");
|
||||
const meta = el("div", "project-meta");
|
||||
meta.append(
|
||||
p.url
|
||||
? externalLink("name entity-link", p.url, p.name, `打开 ${p.name}`)
|
||||
: el("span", "name", p.name),
|
||||
);
|
||||
if (p.links?.length > 1) {
|
||||
const links = el("div", "project-links");
|
||||
p.links.forEach((link) => {
|
||||
links.append(
|
||||
externalLink("mini-link", link.url, link.label, `打开 ${link.label}`),
|
||||
);
|
||||
});
|
||||
meta.append(links);
|
||||
}
|
||||
head.append(
|
||||
Object.assign(el("img"), { src: p.logo, alt: p.name, loading: "lazy" }),
|
||||
el("span", "name", p.name),
|
||||
meta,
|
||||
el("span", "period", p.period),
|
||||
);
|
||||
block.append(
|
||||
@@ -125,7 +150,14 @@ function experienceContent(answer) {
|
||||
alt: exp.company,
|
||||
loading: "lazy",
|
||||
}),
|
||||
el("span", "co", exp.company),
|
||||
exp.url
|
||||
? externalLink(
|
||||
"co entity-link",
|
||||
exp.url,
|
||||
exp.company,
|
||||
`打开 ${exp.company}`,
|
||||
)
|
||||
: el("span", "co", exp.company),
|
||||
el("span", "period", exp.period),
|
||||
);
|
||||
item.append(head, el("div", "exp-role", exp.role));
|
||||
|
||||
@@ -73,6 +73,11 @@ export const projects = [
|
||||
id: "vtrix",
|
||||
name: "SeaCloud / Vtrix",
|
||||
logo: "/logos/vtrix.png",
|
||||
url: "https://cloud.seaart.ai/",
|
||||
links: [
|
||||
{ label: "SeaCloud", url: "https://cloud.seaart.ai/" },
|
||||
{ label: "Vtrix", url: "https://www.vtrix.ai/" },
|
||||
],
|
||||
period: "2025.09 - 至今",
|
||||
subtitle: "模型服务平台控制台",
|
||||
summary:
|
||||
@@ -89,6 +94,7 @@ export const projects = [
|
||||
id: "seabuzz",
|
||||
name: "SeaBuzz",
|
||||
logo: "/logos/seabuzz.webp",
|
||||
url: "https://play.google.com/store/apps/details?id=app.seahot.ai",
|
||||
period: "2025.05 - 至今",
|
||||
subtitle: "资讯、搜索与对话应用",
|
||||
summary:
|
||||
@@ -106,6 +112,7 @@ export const projects = [
|
||||
id: "bawang",
|
||||
name: "霸王功夫",
|
||||
logo: "/logos/chagee.png",
|
||||
url: "https://bwcj.com/",
|
||||
period: "2024.03 - 2025.03",
|
||||
subtitle: "门店、食安与供应链系统",
|
||||
summary:
|
||||
@@ -122,6 +129,7 @@ export const projects = [
|
||||
id: "jingyingbang",
|
||||
name: "经营帮平台 + 经营帮拉新",
|
||||
logo: "/logos/jingyingbang.png",
|
||||
url: "https://jingyingbang.com/",
|
||||
period: "2022.04 - 2024.03",
|
||||
subtitle: "微前端平台与小程序",
|
||||
summary:
|
||||
@@ -140,6 +148,7 @@ export const experiences = [
|
||||
{
|
||||
company: "成都海艺互娱科技有限公司",
|
||||
logo: "/logos/seaart.webp",
|
||||
url: "https://www.seaart.ai/",
|
||||
role: "React Native 开发工程师",
|
||||
period: "2025.05 - 至今",
|
||||
points: [
|
||||
@@ -151,6 +160,7 @@ export const experiences = [
|
||||
{
|
||||
company: "四川茶姬企业管理有限公司",
|
||||
logo: "/logos/chagee.png",
|
||||
url: "https://bwcj.com/",
|
||||
role: "高级 Web 前端开发",
|
||||
period: "2024.03 - 2025.03",
|
||||
points: [
|
||||
@@ -162,6 +172,7 @@ export const experiences = [
|
||||
{
|
||||
company: "中钧科技有限公司四川分公司",
|
||||
logo: "/logos/zhongjun.png",
|
||||
url: "https://zhongjunkeji.com/",
|
||||
role: "前端开发组长",
|
||||
period: "2022.04 - 2024.03",
|
||||
points: [
|
||||
|
||||
@@ -43,6 +43,27 @@ a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.entity-link {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: var(--ink);
|
||||
transition: color 0.18s ease;
|
||||
}
|
||||
|
||||
.entity-link::after {
|
||||
content: "↗";
|
||||
font-family: var(--mono);
|
||||
font-size: 10px;
|
||||
color: var(--cyan);
|
||||
opacity: 0.72;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.entity-link:hover {
|
||||
color: var(--cyan);
|
||||
}
|
||||
|
||||
/* ============ 底层画布与氛围 ============ */
|
||||
#mind-canvas {
|
||||
position: fixed;
|
||||
@@ -470,6 +491,7 @@ main {
|
||||
.project-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: 14px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
@@ -487,6 +509,37 @@ main {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.project-meta {
|
||||
min-width: 0;
|
||||
flex: 1 1 220px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.project-links {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.mini-link {
|
||||
font-family: var(--mono);
|
||||
font-size: 10px;
|
||||
line-height: 1.4;
|
||||
padding: 2px 7px;
|
||||
border-radius: 999px;
|
||||
border: 1px solid rgba(34, 211, 238, 0.28);
|
||||
color: var(--cyan);
|
||||
background: rgba(34, 211, 238, 0.06);
|
||||
transition: border-color 0.18s ease, background 0.18s ease;
|
||||
}
|
||||
|
||||
.mini-link:hover {
|
||||
border-color: rgba(34, 211, 238, 0.62);
|
||||
background: rgba(34, 211, 238, 0.12);
|
||||
}
|
||||
|
||||
.project-head .period {
|
||||
margin-left: auto;
|
||||
font-family: var(--mono);
|
||||
|
||||
Reference in New Issue
Block a user