Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
ai-box
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
青山
ai-box
Commits
60a3d72a
Commit
60a3d72a
authored
Nov 08, 2024
by
fisherdaddy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feature: 增加名言卡片生成器
parent
fea1a0f5
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
310 additions
and
1 deletion
+310
-1
App.jsx
src/App.jsx
+2
-0
QuoteCard.jsx
src/components/QuoteCard.jsx
+290
-0
i18n.json
src/data/i18n.json
+16
-0
Home.jsx
src/pages/Home.jsx
+2
-1
No files found.
src/App.jsx
View file @
60a3d72a
...
...
@@ -14,6 +14,7 @@ const OpenAITimeline = lazy(() => import('./components/OpenAITimeline'));
const
PricingCharts
=
lazy
(()
=>
import
(
'./components/PricingCharts'
));
const
HandwriteGen
=
lazy
(()
=>
import
(
'./components/HandwriteGen'
));
const
ImageBase64Converter
=
lazy
(()
=>
import
(
'./components/ImageBase64Converter'
));
const
QuoteCard
=
lazy
(()
=>
import
(
'./components/QuoteCard'
));
function
App
()
{
return
(
...
...
@@ -33,6 +34,7 @@ function App() {
<
Route
path=
"/llm-model-price"
element=
{
<
PricingCharts
/>
}
/>
<
Route
path=
"/handwriting"
element=
{
<
HandwriteGen
/>
}
/>
<
Route
path=
"/image-base64"
element=
{
<
ImageBase64Converter
/>
}
/>
<
Route
path=
"/quote-card"
element=
{
<
QuoteCard
/>
}
/>
<
Route
path=
"*"
element=
{
<
NotFound
/>
}
/>
</
Routes
>
</
Suspense
>
...
...
src/components/QuoteCard.jsx
0 → 100644
View file @
60a3d72a
import
React
,
{
useState
,
useRef
}
from
'react'
;
import
styled
from
'styled-components'
;
import
html2canvas
from
'html2canvas'
;
// 更新中文字体数组,包含显示名称和 CSS 字体族名称
const
chineseFonts
=
[
{
name
:
'系统默认'
,
value
:
'-apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif'
},
{
name
:
'无衬线'
,
value
:
'"PingFang SC", "Microsoft YaHei", "Helvetica Neue", Helvetica, Arial, sans-serif'
},
{
name
:
'衬线'
,
value
:
'Georgia, "Nimbus Roman No9 L", "Songti SC", "Noto Serif CJK SC", "Source Han Serif SC", "Source Han Serif CN", STSong, "AR PL New Sung", "AR PL SungtiL GB", NSimSun, SimSun, serif'
},
{
name
:
'等宽'
,
value
:
'"SF Mono", SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, "Noto Sans Mono CJK SC", monospace'
},
];
// 定义可选的英文字体
const
englishFonts
=
[
{
name
:
'Arial'
,
value
:
'Arial'
},
{
name
:
'Times New Roman'
,
value
:
'Times New Roman'
},
{
name
:
'Georgia'
,
value
:
'Georgia'
},
{
name
:
'Verdana'
,
value
:
'Verdana'
},
{
name
:
'Courier New'
,
value
:
'Courier New'
},
];
// 定义可选的背景颜色
const
backgroundOptions
=
[
{
name
:
'白色'
,
value
:
'#FFFFFF'
},
{
name
:
'黑色'
,
value
:
'#333333'
},
// 修改为深灰色
{
name
:
'黄色纸张'
,
value
:
'#fdf6e3'
},
{
name
:
'自定义'
,
value
:
'custom'
},
];
const
Container
=
styled
.
div
`
display: flex;
flex-direction: row;
gap: 20px;
padding: 20px;
justify-content: center;
background-color: #f5f5f5;
min-height: 100vh;
`
;
const
TitleLabel
=
styled
.
label
`
font-size: 16px; // 增大字体大小
color: #1677FF; // 设置字体颜色为深色
`
;
const
InputContainer
=
styled
.
div
`
flex: 1;
display: flex;
flex-direction: column;
gap: 15px;
`
;
const
PreviewContainer
=
styled
.
div
`
flex: 1;
background-color:
${(
props
)
=>
props
.
$bgColor
||
'#333333'
}
; // 使用短暂属性
padding: 20px;
border-radius: 12px;
border: 1px solid #333;
color:
${(
props
)
=>
props
.
$fontColor
||
'#b8b83b'
}
; // 使用短暂属性
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
height: 100%;
`
;
const
QuoteText
=
styled
.
div
`
font-size: clamp(16px, 2.5vw, 24px);
margin-bottom: 16px;
color:
${(
props
)
=>
props
.
$color
||
'#b8b83b'
}
; // 使用短暂属性
text-align: center;
line-height: 1.5;
font-family:
${(
props
)
=>
props
.
$fontFamily
}
, serif; // 使用短暂属性
white-space: pre-wrap;
word-wrap: break-word;
`
;
const
QuoteAuthor
=
styled
.
div
`
font-size: clamp(14px, 2vw, 18px);
color:
${(
props
)
=>
props
.
$color
||
'#888'
}
; // 使用短暂属性
text-align: center;
font-family:
${(
props
)
=>
props
.
$fontFamily
}
, sans-serif; // 使用短暂属性
margin-top: 20px;
`
;
const
InputText
=
styled
.
textarea
`
width: 100%;
height: 80px;
padding: 10px;
border-radius: 8px;
border: 1px solid #dadce0;
font-size: 16px;
font-family: Arial, sans-serif;
resize: vertical;
`
;
const
InputField
=
styled
.
input
`
width: 100%;
padding: 10px;
border-radius: 8px;
border: 1px solid #dadce0;
font-size: 16px;
`
;
const
Select
=
styled
.
select
`
width: 100%;
padding: 10px;
border-radius: 8px;
border: 1px solid #dadce0;
font-size: 16px;
background-color: #fff;
`
;
const
ColorInput
=
styled
.
input
`
width: 100%;
padding: 5px;
border: none;
background-color: transparent;
`
;
const
Label
=
styled
.
label
`
font-size: 14px;
margin-bottom: 5px;
`
;
const
DownloadButton
=
styled
.
button
`
padding: 10px 20px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 16px;
margin-top: 20px;
&:hover {
background-color: #45a049;
}
`
;
function
QuoteCard
()
{
const
[
chineseText
,
setChineseText
]
=
useState
(
''
);
const
[
englishText
,
setEnglishText
]
=
useState
(
''
);
const
[
author
,
setAuthor
]
=
useState
(
''
);
const
[
chineseFont
,
setChineseFont
]
=
useState
(
'SimSun'
);
const
[
englishFont
,
setEnglishFont
]
=
useState
(
'Arial'
);
const
[
fontColor
,
setFontColor
]
=
useState
(
'#b8b83b'
);
const
[
authorColor
,
setAuthorColor
]
=
useState
(
'#b8b83b'
);
const
[
bgColor
,
setBgColor
]
=
useState
(
'#333333'
);
const
[
customBgColor
,
setCustomBgColor
]
=
useState
(
'#FFFFFF'
);
const
previewRef
=
useRef
(
null
);
const
handleBackgroundChange
=
(
e
)
=>
{
const
value
=
e
.
target
.
value
;
if
(
value
!==
'custom'
)
{
setBgColor
(
value
);
}
};
const
handleDownload
=
()
=>
{
if
(
previewRef
.
current
)
{
html2canvas
(
previewRef
.
current
,
{
backgroundColor
:
null
,
useCORS
:
true
,
}).
then
((
canvas
)
=>
{
const
link
=
document
.
createElement
(
'a'
);
link
.
download
=
'quote_card.png'
;
link
.
href
=
canvas
.
toDataURL
(
'image/png'
);
link
.
click
();
}).
catch
((
err
)
=>
{
console
.
error
(
'图片下载失败:'
,
err
);
});
}
};
return
(
<
Container
>
{
/* 左侧输入区域 */
}
<
InputContainer
>
<
TitleLabel
>
名言卡片生成器
</
TitleLabel
>
<
InputText
placeholder=
"请输入中文名人名言"
value=
{
chineseText
}
onChange=
{
(
e
)
=>
setChineseText
(
e
.
target
.
value
)
}
/>
<
InputText
placeholder=
"请输入英文翻译"
value=
{
englishText
}
onChange=
{
(
e
)
=>
setEnglishText
(
e
.
target
.
value
)
}
/>
<
InputField
placeholder=
"请输入作者姓名"
value=
{
author
}
onChange=
{
(
e
)
=>
setAuthor
(
e
.
target
.
value
)
}
/>
{
/* 字体选择 */
}
<
Label
>
选择中文字体:
</
Label
>
<
Select
value=
{
chineseFont
}
onChange=
{
(
e
)
=>
setChineseFont
(
e
.
target
.
value
)
}
>
{
chineseFonts
.
map
((
font
)
=>
(
<
option
key=
{
font
.
value
}
value=
{
font
.
value
}
>
{
font
.
name
}
</
option
>
))
}
</
Select
>
<
Label
>
选择英文字体:
</
Label
>
<
Select
value=
{
englishFont
}
onChange=
{
(
e
)
=>
setEnglishFont
(
e
.
target
.
value
)
}
>
{
englishFonts
.
map
((
font
)
=>
(
<
option
key=
{
font
.
value
}
value=
{
font
.
value
}
>
{
font
.
name
}
</
option
>
))
}
</
Select
>
{
/* 字体颜色选择 */
}
<
Label
>
选择字体颜色:
</
Label
>
<
ColorInput
type=
"color"
value=
{
fontColor
}
onChange=
{
(
e
)
=>
setFontColor
(
e
.
target
.
value
)
}
/>
{
/* 作者颜色选择 */
}
<
Label
>
选择作者颜色:
</
Label
>
<
ColorInput
type=
"color"
value=
{
authorColor
}
onChange=
{
(
e
)
=>
setAuthorColor
(
e
.
target
.
value
)
}
/>
{
/* 背景色选择 */
}
<
Label
>
选择背景颜色:
</
Label
>
<
Select
value=
{
backgroundOptions
.
some
((
option
)
=>
option
.
value
===
bgColor
)
?
bgColor
:
'custom'
}
onChange=
{
handleBackgroundChange
}
>
{
backgroundOptions
.
map
((
option
)
=>
(
<
option
key=
{
option
.
name
}
value=
{
option
.
value
}
>
{
option
.
name
}
</
option
>
))
}
</
Select
>
{
bgColor
===
'custom'
&&
(
<>
<
Label
>
选择自定义背景颜色:
</
Label
>
<
ColorInput
type=
"color"
value=
{
customBgColor
}
onChange=
{
(
e
)
=>
setBgColor
(
e
.
target
.
value
)
}
title=
"选择自定义背景颜色"
/>
</>
)
}
{
/* 下载按钮 */
}
<
DownloadButton
onClick=
{
handleDownload
}
>
下载图片
</
DownloadButton
>
</
InputContainer
>
{
/* 右侧预览区域 */
}
<
PreviewContainer
$bgColor=
{
bgColor
}
$fontColor=
{
fontColor
}
ref=
{
previewRef
}
>
<
QuoteText
$color=
{
fontColor
}
$fontFamily=
{
chineseFont
}
>
{
chineseText
||
'请输入中文名人名言'
}
</
QuoteText
>
<
QuoteText
$color=
{
fontColor
}
$fontFamily=
{
englishFont
}
>
{
englishText
||
'Enter the English translation here.'
}
</
QuoteText
>
<
QuoteAuthor
$color=
{
authorColor
}
$fontFamily=
{
englishFont
}
>
——
{
author
||
'作者姓名'
}
</
QuoteAuthor
>
</
PreviewContainer
>
</
Container
>
);
}
export
default
QuoteCard
;
src/data/i18n.json
View file @
60a3d72a
...
...
@@ -61,6 +61,10 @@
"fisherai"
:
{
"title"
:
"One-Click Summary Plugin"
,
"description"
:
"The Best Summary Extension for Chrome Browser"
},
"quotecard"
:
{
"title"
:
"Famous Quote Card Generator"
,
"description"
:
"Convert bilingual famous quotes into cards"
}
},
"notFound"
:
{
...
...
@@ -146,6 +150,10 @@
"fisherai"
:
{
"title"
:
"一键摘要插件"
,
"description"
:
"最好用的 Chrome 浏览器摘要插件"
},
"quotecard"
:
{
"title"
:
"名言卡片生成器"
,
"description"
:
"名言双语文本转为卡片"
}
},
"notFound"
:
{
...
...
@@ -231,6 +239,10 @@
"fisherai"
:
{
"title"
:
"ワンクリック要約プラグイン"
,
"description"
:
"最高のChromeブラウザ用要約プラグイン"
},
"quotecard"
:
{
"title"
:
"名言カード生成器"
,
"description"
:
"名言のバイリンガルテキストをカードに変換"
}
},
"notFound"
:
{
...
...
@@ -316,6 +328,10 @@
"fisherai"
:
{
"title"
:
"원클릭 요약 플러그인"
,
"description"
:
"가장 유용한 Chrome 브라우저 요약 확장 프로그램"
},
"quotecard"
:
{
"title"
:
"명언 카드 생성기"
,
"description"
:
"명언 이중 언어 텍스트를 카드로 변환"
}
},
"notFound"
:
{
...
...
src/pages/Home.jsx
View file @
60a3d72a
...
...
@@ -4,12 +4,13 @@ import { useTranslation } from '../js/i18n';
import
SEO
from
'../components/SEO'
;
const
tools
=
[
{
id
:
'handwrite'
,
icon
:
'fa-handwrite'
,
path
:
'/handwriting'
},
{
id
:
'quotecard'
,
icon
:
'fa-quotecard'
,
path
:
'/quote-card'
},
{
id
:
'text2image'
,
icon
:
'fa-image'
,
path
:
'/text2image'
},
{
id
:
'jsonFormatter'
,
icon
:
'fa-jsonformat'
,
path
:
'/json-formatter'
},
{
id
:
'urlDecode'
,
icon
:
'fa-decode'
,
path
:
'/url-decode'
},
{
id
:
'urlEncode'
,
icon
:
'fa-encode'
,
path
:
'/url-encode'
},
{
id
:
'imageBase64Converter'
,
icon
:
'fa-image-base64'
,
path
:
'/image-base64'
},
{
id
:
'handwrite'
,
icon
:
'fa-handwrite'
,
path
:
'/handwriting'
},
{
id
:
'openAITimeline'
,
icon
:
'fa-openai-timeline'
,
path
:
'/openai-timeline'
},
{
id
:
'modelPrice'
,
icon
:
'fa-model-price'
,
path
:
'/llm-model-price'
},
{
id
:
'fisherai'
,
icon
:
'fa-fisherai'
,
path
:
'https://chromewebstore.google.com/detail/fisherai-your-best-summar/ipfiijaobcenaibdpaacbbpbjefgekbj'
,
external
:
true
}
// 新增外部链接
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment