添加背景页面增加收藏背景色功能

This commit is contained in:
jingrow 2026-01-21 17:46:14 +08:00
parent 951813a539
commit 27b7d65e45
2 changed files with 208 additions and 3 deletions

View File

@ -1113,6 +1113,12 @@
"Add custom background color to images. Free online tool to add background to transparent images. Supports JPG, PNG, WebP formats.": "为图片添加自定义背景颜色。免费在线工具,可为透明背景图片添加背景。支持 JPG、PNG、WebP 格式。",
"add background, background color, image background, transparent background, online background tool, image processing, background editor, free tool": "添加背景、背景颜色、图片背景、透明背景、在线背景工具、图片处理、背景编辑器、免费工具",
"Background Color": "背景颜色",
"Add to favorites": "添加到收藏",
"Remove from favorites": "从收藏中移除",
"Favorite Colors": "收藏颜色",
"Color already in favorites": "颜色已在收藏中",
"Maximum 12 favorite colors allowed. Please remove one first.": "最多允许12个收藏颜色请先移除一个",
"Color added to favorites": "颜色已添加到收藏",
"Color Tones": "色调",
"Common Colors": "常用颜色",
"Apply Background": "应用背景",

View File

@ -161,7 +161,17 @@
<div v-if="uploadedImage" class="right-sidebar">
<div class="sidebar-content">
<div class="color-picker-section">
<h4 class="section-title">{{ t('Background Color') }}</h4>
<div class="section-header">
<h4 class="section-title">{{ t('Background Color') }}</h4>
<button
class="add-favorite-btn"
@click="addToFavorites"
:title="t('Add to favorites')"
:disabled="favoriteColors.length >= MAX_FAVORITE_COLORS"
>
<i class="fa fa-star"></i>
</button>
</div>
<div class="color-picker-container">
<input
v-model="backgroundColor"
@ -180,6 +190,29 @@
</div>
</div>
<div v-if="favoriteColors.length > 0" class="favorite-colors-section">
<h4 class="section-title">{{ t('Favorite Colors') }}</h4>
<div class="favorite-colors-grid">
<div
v-for="(color, index) in favoriteColors"
:key="index"
class="favorite-color-item"
:class="{ 'active': color === backgroundColor }"
:style="{ backgroundColor: color }"
@click="selectCommonColor(color)"
:title="color"
>
<button
type="button"
class="remove-favorite-btn"
@click.stop="removeFavoriteColor(color)"
:title="t('Remove from favorites')"
:aria-label="t('Remove from favorites')"
></button>
</div>
</div>
</div>
<div class="common-colors-section">
<h4 class="section-title">{{ t('Common Colors') }}</h4>
<div class="common-colors-grid">
@ -251,6 +284,65 @@ const colorShades = computed(() => {
return generateColorShades(backgroundColor.value)
})
// Favorite colors - persisted in localStorage
const favoriteColors = ref<string[]>([])
const MAX_FAVORITE_COLORS = 12
// Load favorite colors from localStorage
const loadFavoriteColors = () => {
try {
const saved = localStorage.getItem('add_background_favorite_colors')
if (saved) {
const parsed = JSON.parse(saved)
if (Array.isArray(parsed)) {
favoriteColors.value = parsed.slice(0, MAX_FAVORITE_COLORS)
}
}
} catch (error) {
console.error('Failed to load favorite colors:', error)
}
}
// Save favorite colors to localStorage
const saveFavoriteColors = () => {
try {
localStorage.setItem('add_background_favorite_colors', JSON.stringify(favoriteColors.value))
} catch (error) {
console.error('Failed to save favorite colors:', error)
}
}
// Add current color to favorites
const addToFavorites = () => {
const color = backgroundColor.value.toUpperCase()
// Check if color already exists
if (favoriteColors.value.includes(color)) {
message.info(t('Color already in favorites'))
return
}
// Check if favorites is full
if (favoriteColors.value.length >= MAX_FAVORITE_COLORS) {
message.warning(t('Maximum 12 favorite colors allowed. Please remove one first.'))
return
}
// Add to beginning of array
favoriteColors.value.unshift(color)
saveFavoriteColors()
message.success(t('Color added to favorites'))
}
// Remove color from favorites
const removeFavoriteColor = (color: string) => {
const index = favoriteColors.value.indexOf(color)
if (index > -1) {
favoriteColors.value.splice(index, 1)
saveFavoriteColors()
}
}
// 12 common background colors - light to dark
const commonColors = ref([
'#FFFFFF', // White
@ -547,6 +639,7 @@ const handleUrlSubmit = async () => {
onMounted(() => {
window.addEventListener('resize', handleResize)
window.addEventListener('paste', handlePaste)
loadFavoriteColors()
})
onUnmounted(() => {
@ -1737,19 +1830,65 @@ const removeHistoryItem = (index: number) => {
}
.color-picker-section,
.favorite-colors-section,
.common-colors-section {
display: flex;
flex-direction: column;
gap: 16px;
}
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 8px;
padding-bottom: 12px;
border-bottom: 1px solid #e5e7eb;
}
.section-title {
font-size: 14px;
font-weight: 600;
color: #1f2937;
margin: 0;
padding-bottom: 12px;
border-bottom: 1px solid #e5e7eb;
flex: 1;
}
.add-favorite-btn {
width: 32px;
height: 32px;
border: 1px solid #e5e7eb;
border-radius: 6px;
background: white;
color: #fbbf24;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s ease;
padding: 0;
flex-shrink: 0;
i {
font-size: 14px;
}
&:hover:not(:disabled) {
border-color: #fbbf24;
background: #fffbeb;
transform: scale(1.05);
}
&:active:not(:disabled) {
transform: scale(0.95);
background: #fef3c7;
}
&:disabled {
opacity: 0.4;
cursor: not-allowed;
color: #cbd5e1;
}
}
.color-picker-container {
@ -1800,12 +1939,18 @@ const removeHistoryItem = (index: number) => {
}
}
.favorite-colors-grid,
.common-colors-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 10px;
}
.favorite-colors-grid {
position: relative;
}
.favorite-color-item,
.common-color-item {
aspect-ratio: 1;
border-radius: 8px;
@ -1841,6 +1986,58 @@ const removeHistoryItem = (index: number) => {
}
}
.favorite-color-item {
.remove-favorite-btn {
position: absolute;
top: 2px;
right: 2px;
width: 18px;
height: 18px;
border-radius: 999px;
border: none;
background: rgba(15, 23, 42, 0.75);
color: white;
display: inline-flex;
align-items: center;
justify-content: center;
opacity: 0;
transform: scale(0.8);
transition: all 0.2s ease;
cursor: pointer;
font-size: 0;
line-height: 1;
z-index: 2;
&::before,
&::after {
content: '';
position: absolute;
width: 10px;
height: 2px;
background: white;
border-radius: 999px;
}
&::before {
transform: rotate(45deg);
}
&::after {
transform: rotate(-45deg);
}
&:hover {
background: rgba(239, 68, 68, 0.9);
transform: scale(1);
}
}
&:hover .remove-favorite-btn {
opacity: 1;
transform: scale(1);
}
}
.canvas-processing-overlay {
position: absolute;
top: 0;
@ -2146,6 +2343,7 @@ const removeHistoryItem = (index: number) => {
box-shadow: 0 -2px 8px rgba(0, 0, 0, 0.05);
}
.favorite-colors-grid,
.common-colors-grid {
grid-template-columns: repeat(4, 1fr);
}
@ -2191,6 +2389,7 @@ const removeHistoryItem = (index: number) => {
width: 240px;
}
.favorite-colors-grid,
.common-colors-grid {
grid-template-columns: repeat(4, 1fr);
}