321
This commit is contained in:
parent
e8816c1ffb
commit
c3c9eb1acd
|
|
@ -107,7 +107,7 @@
|
|||
|
||||
---
|
||||
|
||||
## 三、前端重构计划
|
||||
## 三、前端重构计划(已完成)
|
||||
|
||||
### 3.1 需要修改的文件清单
|
||||
|
||||
|
|
@ -674,12 +674,26 @@ function renderSearchResult(bookmark) {
|
|||
- 标签管理入口
|
||||
- [x] 构建验证通过
|
||||
|
||||
### 8.3 浏览器插件重构(待开始)
|
||||
### 8.3 浏览器插件重构(已完成 ✅)
|
||||
|
||||
- [ ] 修改 shared/api.js
|
||||
- [ ] 修改 content/content.js 搜索结果渲染
|
||||
- [ ] 修改 newtab/index.html 书签显示
|
||||
- [ ] 修改 popup/popup.js 保存功能
|
||||
- [x] 修改 shared/api.js
|
||||
- getBookmarks 新增 folderId 参数
|
||||
- 新增 getFolders() 方法
|
||||
- 新增 createTag() 方法
|
||||
- [x] 修改 content/content.js 搜索结果渲染
|
||||
- 适配新的 Tag 对象结构(tag.name, tag.color)
|
||||
- [x] 修改 newtab/index.html 书签显示
|
||||
- 搜索结果中添加标签显示
|
||||
- 支持标签颜色
|
||||
- [x] 修改 popup/popup.js 保存功能
|
||||
- 新增文件夹选择器
|
||||
- 保存时支持 folderId
|
||||
- [x] 修改 background/background.js
|
||||
- 新增 getFolders 消息处理
|
||||
- [x] 修改 popup/popup.html
|
||||
- 新增文件夹选择器 UI
|
||||
- [x] 修改 popup/popup.css
|
||||
- 新增文件夹选择器样式
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -695,8 +709,8 @@ function renderSearchResult(bookmark) {
|
|||
|
||||
## 十、版本信息
|
||||
|
||||
- 文档版本:v2.1
|
||||
- 文档版本:v2.2
|
||||
- 创建日期:2024-12-25
|
||||
- 最后更新:2024-12-25
|
||||
- 最后更新:2025-12-25
|
||||
- 作者:Claude Code
|
||||
- 更新说明:完成前端重构
|
||||
- 更新说明:完成浏览器插件重构
|
||||
|
|
|
|||
|
|
@ -159,6 +159,13 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|||
})
|
||||
return true
|
||||
}
|
||||
|
||||
if (request.action === 'getFolders') {
|
||||
api.getFolders().then(result => {
|
||||
sendResponse(result)
|
||||
})
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
console.log('Bookmark extension background script loaded')
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ function updateSearchResults(results) {
|
|||
</div>
|
||||
${item.tags.length > 0 ? `
|
||||
<div class="bm-search-item-tags">
|
||||
${item.tags.slice(0, 2).map(tag => `<span class="bm-search-tag">${escapeHtml(tag)}</span>`).join('')}
|
||||
${item.tags.slice(0, 2).map(tag => `<span class="bm-search-tag"${tag.color ? ` style="background-color: ${tag.color}"` : ''}>${escapeHtml(tag.name)}</span>`).join('')}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -195,6 +195,20 @@
|
|||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.result-tags {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.result-tag {
|
||||
font-size: 10px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
background: #e0e7ff;
|
||||
color: #4f46e5;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
|
@ -292,6 +306,11 @@
|
|||
<div class="result-content">
|
||||
<div class="result-title">${escapeHtml(b.title)}</div>
|
||||
<div class="result-url">${escapeHtml(b.url)}</div>
|
||||
${b.tags && b.tags.length > 0 ? `
|
||||
<div class="result-tags">
|
||||
${b.tags.slice(0, 3).map(tag => `<span class="result-tag"${tag.color ? ` style="background-color: ${tag.color}; color: #fff"` : ''}>${escapeHtml(tag.name)}</span>`).join('')}
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</a>
|
||||
`).join('')}
|
||||
|
|
|
|||
|
|
@ -135,6 +135,20 @@ body {
|
|||
border-color: #667eea;
|
||||
}
|
||||
|
||||
#quick-save select {
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
outline: none;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#quick-save select:focus {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
#save-btn {
|
||||
padding: 8px 12px;
|
||||
background: #667eea;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@
|
|||
<input type="text" id="bookmark-title" placeholder="标题" />
|
||||
<input type="url" id="bookmark-url" placeholder="URL" />
|
||||
<input type="text" id="bookmark-tags" placeholder="标签(逗号分隔)" />
|
||||
<select id="bookmark-folder">
|
||||
<option value="">选择文件夹(可选)</option>
|
||||
</select>
|
||||
<button id="save-btn">收藏当前页</button>
|
||||
</div>
|
||||
<div id="save-result"></div>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ const deviceName = document.getElementById('device-name')
|
|||
const bookmarkTitle = document.getElementById('bookmark-title')
|
||||
const bookmarkUrl = document.getElementById('bookmark-url')
|
||||
const bookmarkTags = document.getElementById('bookmark-tags')
|
||||
const bookmarkFolder = document.getElementById('bookmark-folder')
|
||||
const saveBtn = document.getElementById('save-btn')
|
||||
const saveResult = document.getElementById('save-result')
|
||||
const autoSyncCheckbox = document.getElementById('auto-sync')
|
||||
|
|
@ -25,6 +26,7 @@ async function init() {
|
|||
await loadUserInfo()
|
||||
await loadCurrentTab()
|
||||
await loadSettings()
|
||||
await loadFolders()
|
||||
} else {
|
||||
showLoginView()
|
||||
}
|
||||
|
|
@ -76,6 +78,37 @@ async function loadSettings() {
|
|||
showNotificationCheckbox.checked = settings.showNotification
|
||||
}
|
||||
|
||||
// 加载文件夹列表
|
||||
async function loadFolders() {
|
||||
try {
|
||||
const result = await chrome.runtime.sendMessage({ action: 'getFolders' })
|
||||
if (result.success && result.data) {
|
||||
// 清空现有选项(保留第一个默认选项)
|
||||
while (bookmarkFolder.options.length > 1) {
|
||||
bookmarkFolder.remove(1)
|
||||
}
|
||||
// 添加文件夹选项
|
||||
renderFolderOptions(result.data, 0)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load folders:', e)
|
||||
}
|
||||
}
|
||||
|
||||
// 递归渲染文件夹选项
|
||||
function renderFolderOptions(folders, level) {
|
||||
folders.forEach(folder => {
|
||||
const option = document.createElement('option')
|
||||
option.value = folder.id
|
||||
option.textContent = ' '.repeat(level) + (level > 0 ? '└ ' : '') + folder.name
|
||||
bookmarkFolder.appendChild(option)
|
||||
// 递归渲染子文件夹
|
||||
if (folder.children && folder.children.length > 0) {
|
||||
renderFolderOptions(folder.children, level + 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 保存设置
|
||||
async function saveSettings() {
|
||||
await storage.setSettings({
|
||||
|
|
@ -130,16 +163,17 @@ saveBtn.addEventListener('click', async () => {
|
|||
const title = bookmarkTitle.value.trim()
|
||||
const url = bookmarkUrl.value.trim()
|
||||
const tags = bookmarkTags.value.split(',').map(t => t.trim()).filter(Boolean)
|
||||
|
||||
const folderId = bookmarkFolder.value || null
|
||||
|
||||
if (!title || !url) {
|
||||
showSaveResult('请填写标题和URL', false)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const result = await chrome.runtime.sendMessage({
|
||||
action: 'createBookmark',
|
||||
data: { title, url, tags }
|
||||
data: { title, url, tags, folderId }
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
|
|
|
|||
|
|
@ -104,9 +104,12 @@ export const api = {
|
|||
},
|
||||
|
||||
// 获取书签列表
|
||||
async getBookmarks(tag) {
|
||||
const params = tag ? `?tag=${encodeURIComponent(tag)}` : ''
|
||||
return request(`/bookmarks${params}`)
|
||||
async getBookmarks(tag = null, folderId = null) {
|
||||
const params = new URLSearchParams()
|
||||
if (tag) params.append('tag', tag)
|
||||
if (folderId) params.append('folderId', folderId)
|
||||
const queryString = params.toString()
|
||||
return request(`/bookmarks${queryString ? '?' + queryString : ''}`)
|
||||
},
|
||||
|
||||
// 搜索书签
|
||||
|
|
@ -135,6 +138,19 @@ export const api = {
|
|||
// 获取标签列表
|
||||
async getTags() {
|
||||
return request('/tags')
|
||||
},
|
||||
|
||||
// 获取文件夹列表
|
||||
async getFolders() {
|
||||
return request('/folders')
|
||||
},
|
||||
|
||||
// 创建标签
|
||||
async createTag(name, color = null, icon = null) {
|
||||
return request('/tags', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name, color, icon })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user