fix(V0.2): 智能截断去尾部标点; 看板左列收窄; 项目头像三处统一
Docker Build and Push / build-image (push) Successful in 1m7s
Docker Build and Push / build-image (push) Successful in 1m7s
- splitTitle: 截断后用 \p{P} 去掉标题尾部连续分隔符 (原字符类重组有
转义坑, 换 Unicode 属性类)
- 看板卡片左列 (状态点+⋯) 收窄至 14px 并负外距悬进卡片内边距
- 项目头像统一: 新增 .pavatar 基类与 projectIcon.colorOfProject,
项目管理预览改用同配色/同圆角/居中首字, 修复灰底与文字歪斜
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||||
import { getRecentIds, getRecentOrder, setRecentOrder } from '../../pages/task/prefs.js'
|
import { getRecentIds, getRecentOrder, setRecentOrder } from '../../pages/task/prefs.js'
|
||||||
|
import { colorOfProject } from '../../pages/task/projectIcon.js'
|
||||||
|
|
||||||
// 首屏最近项目条 (T-VW-08/10)
|
// 首屏最近项目条 (T-VW-08/10)
|
||||||
// - 展示最近使用的 3 个项目 + 「更多项目」入口
|
// - 展示最近使用的 3 个项目 + 「更多项目」入口
|
||||||
// - 顺序: 手动排序(recentOrder)优先, 其次最近访问(recentIds), 兜底列表顺序
|
// - 顺序: 手动排序(recentOrder)优先, 其次最近访问(recentIds), 兜底列表顺序
|
||||||
// - 长按卡片 300ms 进入拖拽态, 水平拖动实时换位, 松手持久化(设备端)
|
// - 长按卡片 300ms 进入拖拽态, 水平拖动实时换位, 松手持久化(设备端)
|
||||||
const COLORS = ['#1677ff', '#00b578', '#ff8f1f', '#a855f7', '#14b8a6', '#f43f9e']
|
|
||||||
const colorOf = (id) => COLORS[Math.abs(id) % COLORS.length]
|
|
||||||
const LONG_PRESS = 300
|
const LONG_PRESS = 300
|
||||||
const MOVE_TOLERANCE = 8
|
const MOVE_TOLERANCE = 8
|
||||||
|
|
||||||
@@ -127,7 +126,7 @@ export default function RecentProjects({ projects, currentId, onSelect, onMore }
|
|||||||
className="rp-ico"
|
className="rp-ico"
|
||||||
style={p.icon
|
style={p.icon
|
||||||
? { background: `url(${p.icon}) center/cover no-repeat` }
|
? { background: `url(${p.icon}) center/cover no-repeat` }
|
||||||
: { background: colorOf(p.id) }}
|
: { background: colorOfProject(p) }}
|
||||||
>
|
>
|
||||||
{p.icon ? '' : (p.name || '?').slice(0, 1)}
|
{p.icon ? '' : (p.name || '?').slice(0, 1)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import useOverlayBack from '../../hooks/useOverlayBack.js'
|
|||||||
import ColumnSettings from './ColumnSettings.jsx'
|
import ColumnSettings from './ColumnSettings.jsx'
|
||||||
import ProjectMembers from './ProjectMembers.jsx'
|
import ProjectMembers from './ProjectMembers.jsx'
|
||||||
import { DEFAULT_KINDS, kindColor } from './kind.js'
|
import { DEFAULT_KINDS, kindColor } from './kind.js'
|
||||||
|
import { colorOfProject } from './projectIcon.js'
|
||||||
|
|
||||||
// 项目管理 (T-PJ-11/12): 成员 / 看板列 / 项目信息 三个分区的统一入口
|
// 项目管理 (T-PJ-11/12): 成员 / 看板列 / 项目信息 三个分区的统一入口
|
||||||
// onExited: 项目被删除/退出/归档后, 上层应离开该项目(回落个人默认项目)
|
// onExited: 项目被删除/退出/归档后, 上层应离开该项目(回落个人默认项目)
|
||||||
@@ -270,11 +271,13 @@ export default function ProjectManage({ project, onClose, onChanged, onExited })
|
|||||||
<div className="set-row" style={{ padding: '12px 14px' }}>
|
<div className="set-row" style={{ padding: '12px 14px' }}>
|
||||||
<span className="pn" style={{ flex: 1, fontSize: 13.5 }}>项目图标</span>
|
<span className="pn" style={{ flex: 1, fontSize: 13.5 }}>项目图标</span>
|
||||||
<div
|
<div
|
||||||
className="pico"
|
className="pavatar"
|
||||||
style={{
|
style={{
|
||||||
width: 34, height: 34, borderRadius: 9, flexShrink: 0,
|
width: 34, height: 34, borderRadius: 9, fontSize: 14,
|
||||||
background: project.icon ? `url(${project.icon}) center/cover no-repeat` : '#dfe6f0',
|
background: project.icon
|
||||||
color: '#5a6a80', cursor: 'pointer',
|
? `url(${project.icon}) center/cover no-repeat`
|
||||||
|
: colorOfProject(project),
|
||||||
|
cursor: 'pointer',
|
||||||
}}
|
}}
|
||||||
onClick={pickIcon}
|
onClick={pickIcon}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -126,8 +126,7 @@ export default function TaskPage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const COLORS = ['#1677ff', '#00b578', '#ff8f1f', '#a855f7', '#14b8a6', '#f43f9e']
|
import { colorOfProject } from './projectIcon.js'
|
||||||
const colorOf = (p) => COLORS[Math.abs(p.id) % COLORS.length]
|
|
||||||
const LONG_PRESS = 300
|
const LONG_PRESS = 300
|
||||||
const MOVE_TOLERANCE = 8
|
const MOVE_TOLERANCE = 8
|
||||||
|
|
||||||
@@ -290,7 +289,7 @@ function ProjectList({ projects, err, onRetry, onOpen, onChanged, createSignal,
|
|||||||
className="pico"
|
className="pico"
|
||||||
style={p.icon
|
style={p.icon
|
||||||
? { background: `url(${p.icon}) center/cover no-repeat` }
|
? { background: `url(${p.icon}) center/cover no-repeat` }
|
||||||
: { background: colorOf(p) }}
|
: { background: colorOfProject(p) }}
|
||||||
>
|
>
|
||||||
{p.icon ? '' : (p.name || '?').slice(0, 1)}
|
{p.icon ? '' : (p.name || '?').slice(0, 1)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// 项目头像配色: 项目列表 / 最近项目 / 项目管理 三处共用, 保证观感一致
|
||||||
|
export const PROJECT_COLORS = ['#1677ff', '#00b578', '#ff8f1f', '#a855f7', '#14b8a6', '#f43f9e']
|
||||||
|
|
||||||
|
export const colorOfProject = (p) => PROJECT_COLORS[Math.abs(p.id) % PROJECT_COLORS.length]
|
||||||
@@ -16,7 +16,10 @@ export function splitTitle(raw) {
|
|||||||
if (SEPARATOR.test(text[i - 1])) { cut = i; break }
|
if (SEPARATOR.test(text[i - 1])) { cut = i; break }
|
||||||
}
|
}
|
||||||
if (cut < 0) cut = MAX_TITLE
|
if (cut < 0) cut = MAX_TITLE
|
||||||
return { title: text.slice(0, cut).trim(), desc: text }
|
// 截断落在分隔符上: 分隔符留在标题末尾很难看, 去掉尾部连续分隔符/空白
|
||||||
|
// (\p{P} 覆盖中英文全部标点; 之前用 SEPARATOR.source 重组字符类有转义坑)
|
||||||
|
const title = text.slice(0, cut).replace(/[\s\p{P}]+$/u, '').trim()
|
||||||
|
return { title, desc: text }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 时间词 → 日期 (返回 YYYY-MM-DD):
|
// 时间词 → 日期 (返回 YYYY-MM-DD):
|
||||||
|
|||||||
+10
-1
@@ -985,6 +985,12 @@ body.me-safe-top .app-safe-top { height: 0; }
|
|||||||
width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center;
|
width: 34px; height: 34px; border-radius: 9px; display: flex; align-items: center;
|
||||||
justify-content: center; color: #fff; font-size: 14px; font-weight: 700; flex-shrink: 0;
|
justify-content: center; color: #fff; font-size: 14px; font-weight: 700; flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
/* 项目头像基类 (不依赖 .proj-item 作用域): 项目管理编辑页预览等裸用场景 */
|
||||||
|
.pavatar {
|
||||||
|
display: flex; align-items: center; justify-content: center;
|
||||||
|
color: #fff; font-weight: 700; flex-shrink: 0;
|
||||||
|
background-size: cover; background-position: center; background-repeat: no-repeat;
|
||||||
|
}
|
||||||
.proj-item .pmain { flex: 1; min-width: 0; }
|
.proj-item .pmain { flex: 1; min-width: 0; }
|
||||||
.proj-item .ptitle {
|
.proj-item .ptitle {
|
||||||
font-size: 14.5px; font-weight: 600; display: flex; align-items: center; gap: 6px;
|
font-size: 14.5px; font-weight: 600; display: flex; align-items: center; gap: 6px;
|
||||||
@@ -1085,11 +1091,14 @@ body.me-safe-top .app-safe-top { height: 0; }
|
|||||||
box-shadow: 0 1px 2px rgba(0,0,0,.05); cursor: pointer; flex-shrink: 0;
|
box-shadow: 0 1px 2px rgba(0,0,0,.05); cursor: pointer; flex-shrink: 0;
|
||||||
display: flex; gap: 7px; align-items: flex-start;
|
display: flex; gap: 7px; align-items: flex-start;
|
||||||
}
|
}
|
||||||
/* 左侧竖排操作列: 状态点在上, ⋯ 沉到左下角 */
|
/* 左侧竖排操作列: 状态点在上, ⋯ 沉到左下角; 负外距悬进卡片内边距, 少占横向空间 */
|
||||||
.bcard-left {
|
.bcard-left {
|
||||||
display: flex; flex-direction: column; align-items: center; flex-shrink: 0;
|
display: flex; flex-direction: column; align-items: center; flex-shrink: 0;
|
||||||
align-self: stretch; justify-content: space-between; padding: 1px 0 2px;
|
align-self: stretch; justify-content: space-between; padding: 1px 0 2px;
|
||||||
|
margin: 0 -5px; width: 14px;
|
||||||
}
|
}
|
||||||
|
.bcard-left .bstat { padding: 0; }
|
||||||
|
.bcard-left .bmore-btn { font-size: 12px; padding: 0; line-height: 1.1; }
|
||||||
.bcard-body { flex: 1; min-width: 0; }
|
.bcard-body { flex: 1; min-width: 0; }
|
||||||
.bcard.hl { outline: 2px solid var(--color-primary); outline-offset: 1px; }
|
.bcard.hl { outline: 2px solid var(--color-primary); outline-offset: 1px; }
|
||||||
.brow1 { display: flex; align-items: flex-start; gap: 6px; }
|
.brow1 { display: flex; align-items: flex-start; gap: 6px; }
|
||||||
|
|||||||
Reference in New Issue
Block a user