feat(V0.2): 快速添加输入框三行/失焦收起; ⋯菜单点选即收; 项目图标可设图片
Docker Build and Push / build-image (push) Successful in 1m22s
Docker Build and Push / build-image (push) Successful in 1m22s
- 快速添加改 3 行 textarea, Enter 创建/Shift+Enter 换行/Esc 关闭, 焦点离开且无内容时自动收起 - 任务 ⋯ ActionSheet 点选动作后 handler.close() 收回菜单 - Project.icon (TEXT data URL, 迁移 20261025130000): 项目管理可选图片, 客户端裁为 96x96 cover JPEG (~15KB); 项目列表/最近项目/管理页图标位 显示图片, 保持原尺寸与圆角; 可恢复默认首字色块
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import { Dialog, Input, Popup, Toast } from 'antd-mobile'
|
||||
import { projectApi } from '../../api/task.js'
|
||||
import { useAuth } from '../../auth/AuthContext.jsx'
|
||||
@@ -21,6 +21,8 @@ export default function ProjectManage({ project, onClose, onChanged, onExited })
|
||||
const [kindEdit, setKindEdit] = useState(false)
|
||||
const [kinds, setKinds] = useState([])
|
||||
const [newKind, setNewKind] = useState('')
|
||||
// 项目图标更换: 隐藏 file input
|
||||
const iconInputRef = useRef(null)
|
||||
|
||||
const members = project.members || []
|
||||
const notes = Array.isArray(project.notes) ? project.notes : []
|
||||
@@ -149,6 +151,49 @@ export default function ProjectManage({ project, onClose, onChanged, onExited })
|
||||
}
|
||||
}
|
||||
|
||||
// 项目图标: 图片裁为 96x96 cover JPEG data URL (保持现有尺寸/圆角由 CSS 承担)
|
||||
function pickIcon() { iconInputRef.current?.click() }
|
||||
|
||||
function onIconFile(e) {
|
||||
const file = e.target.files?.[0]
|
||||
e.target.value = ''
|
||||
if (!file || !file.type.startsWith('image/')) return
|
||||
const url = URL.createObjectURL(file)
|
||||
const img = new Image()
|
||||
img.onload = async () => {
|
||||
URL.revokeObjectURL(url)
|
||||
const S = 96
|
||||
const c = document.createElement('canvas')
|
||||
c.width = S
|
||||
c.height = S
|
||||
const ctx = c.getContext('2d')
|
||||
const r = Math.max(S / img.width, S / img.height)
|
||||
const w = img.width * r
|
||||
const h = img.height * r
|
||||
ctx.drawImage(img, (S - w) / 2, (S - h) / 2, w, h)
|
||||
const dataUrl = c.toDataURL('image/jpeg', 0.85)
|
||||
try {
|
||||
await projectApi.update(project.id, { icon: dataUrl })
|
||||
Toast.show({ content: '图标已更新' })
|
||||
onChanged?.()
|
||||
} catch (err) {
|
||||
Toast.show({ content: err.message || '图标保存失败' })
|
||||
}
|
||||
}
|
||||
img.onerror = () => URL.revokeObjectURL(url)
|
||||
img.src = url
|
||||
}
|
||||
|
||||
async function clearIcon() {
|
||||
try {
|
||||
await projectApi.update(project.id, { icon: null })
|
||||
Toast.show({ content: '已恢复默认' })
|
||||
onChanged?.()
|
||||
} catch (e) {
|
||||
Toast.show({ content: e.message })
|
||||
}
|
||||
}
|
||||
|
||||
async function quit() { const ok = await Dialog.confirm({
|
||||
content: '退出该项目?退出后将不再可见。',
|
||||
confirmText: '退出',
|
||||
@@ -222,6 +267,23 @@ export default function ProjectManage({ project, onClose, onChanged, onExited })
|
||||
</div>
|
||||
|
||||
<div className="section-h" style={{ margin: '14px 14px 8px' }}>项目信息</div>
|
||||
<div className="set-row" style={{ padding: '12px 14px' }}>
|
||||
<span className="pn" style={{ flex: 1, fontSize: 13.5 }}>项目图标</span>
|
||||
<div
|
||||
className="pico"
|
||||
style={{
|
||||
width: 34, height: 34, borderRadius: 9, flexShrink: 0,
|
||||
background: project.icon ? `url(${project.icon}) center/cover no-repeat` : '#dfe6f0',
|
||||
color: '#5a6a80', cursor: 'pointer',
|
||||
}}
|
||||
onClick={pickIcon}
|
||||
>
|
||||
{project.icon ? '' : (project.name || '?').slice(0, 1)}
|
||||
</div>
|
||||
{project.icon && <span className="link" style={{ marginLeft: 10 }} onClick={clearIcon}>恢复</span>}
|
||||
<span className="link" style={{ marginLeft: 10 }} onClick={pickIcon}>更换</span>
|
||||
<input ref={iconInputRef} type="file" accept="image/*" hidden onChange={onIconFile} />
|
||||
</div>
|
||||
<div className="set-row" style={{ padding: '12px 14px' }} onClick={() => { setName(project.name); setRenaming(true) }}>
|
||||
<span className="pn" style={{ flex: 1, fontSize: 13.5 }}>项目名称</span>
|
||||
<span style={{ fontSize: 12.5, color: '#999' }}>{project.name}</span>
|
||||
|
||||
Reference in New Issue
Block a user