Skip to content

Commit 6bbe5ef

Browse files
committed
feat(settings): 重构表情管理对话框功能
- 添加 ensureDialogContainer、openSettingsDialog 和 escapeDialogHTML 辅助方法 - 将 createEmojiGroup 方法重构为模态对话框形式,替换原来的 prompt 弹窗 - 实现 confirmCreateEmojiGroup 方法处理分组创建逻辑 - 优化 showEmojiShareResult 方法使用新的对话框样式和 XSS 防护 - 更新 importEmojiShare 方法为模态对话框实现 - 重构 addEmojiByUrl 方法为统一的对话框界面 - 添加表情对话框相关的 SCSS 样式定义 - 优化移动端对话框样式适配 - 为对话框标题区域添加新的 CSS 类定义
1 parent b1dccba commit 6bbe5ef

File tree

6 files changed

+312
-97
lines changed

6 files changed

+312
-97
lines changed

src/main/resources/css/base.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/css/mobile-base.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/js/settings.js

Lines changed: 136 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,20 +1934,76 @@ var Settings = {
19341934
}
19351935
});
19361936
},
1937+
ensureDialogContainer: function (id) {
1938+
var $dialog = $('#' + id);
1939+
if ($dialog.length === 0) {
1940+
$('body').append('<div id="' + id + '"></div>');
1941+
$dialog = $('#' + id);
1942+
}
1943+
return $dialog;
1944+
},
1945+
openSettingsDialog: function (id, options) {
1946+
Settings.ensureDialogContainer(id).html(options.html);
1947+
$('#' + id).dialog({
1948+
'width': $(window).width() > options.width ? options.width : $(window).width() - 50,
1949+
'height': options.height,
1950+
'modal': true,
1951+
'hideFooter': true,
1952+
'title': options.title
1953+
});
1954+
$('#' + id).dialog('open');
1955+
return $('#' + id);
1956+
},
1957+
escapeDialogHTML: function (value) {
1958+
return String(value == null ? '' : value)
1959+
.replace(/&/g, '&amp;')
1960+
.replace(/</g, '&lt;')
1961+
.replace(/>/g, '&gt;')
1962+
.replace(/"/g, '&quot;')
1963+
.replace(/'/g, '&#39;');
1964+
},
19371965
/**
19381966
* 创建新分组
19391967
*/
19401968
createEmojiGroup: function () {
1941-
var groupName = prompt('请输入分组名称:', '');
1942-
if (!groupName || groupName.trim() === '') {
1969+
var html = ''
1970+
+ '<div class="emoji-dialog">'
1971+
+ ' <div class="emoji-dialog__desc">创建后会立即出现在你的表情分组列表中,可继续添加、排序或分享。</div>'
1972+
+ ' <div class="emoji-dialog__field">'
1973+
+ ' <label class="emoji-dialog__label" for="createEmojiGroupName">分组名称</label>'
1974+
+ ' <input id="createEmojiGroupName" class="emoji-dialog__input" type="text" maxlength="20" placeholder="请输入分组名称" />'
1975+
+ ' </div>'
1976+
+ ' <div class="emoji-dialog__actions">'
1977+
+ ' <button type="button" onclick="$(\'#createEmojiGroupDialog\').dialog(\'close\')">取消</button>'
1978+
+ ' <button type="button" class="green" onclick="Settings.confirmCreateEmojiGroup()">确定</button>'
1979+
+ ' </div>'
1980+
+ '</div>';
1981+
1982+
Settings.openSettingsDialog('createEmojiGroupDialog', {
1983+
html: html,
1984+
title: '添加表情分组',
1985+
width: 430,
1986+
height: 260
1987+
});
1988+
1989+
$('#createEmojiGroupName').focus().off('keydown').on('keydown', function (event) {
1990+
if (event.keyCode === 13) {
1991+
Settings.confirmCreateEmojiGroup();
1992+
}
1993+
});
1994+
},
1995+
confirmCreateEmojiGroup: function () {
1996+
var groupName = $('#createEmojiGroupName').val().trim();
1997+
if (!groupName) {
1998+
Util.notice('warning', 2000, '请输入分组名称');
19431999
return;
19442000
}
1945-
2001+
19462002
$.ajax({
19472003
url: Label.servePath + '/api/emoji/group/create',
19482004
type: 'POST',
19492005
data: JSON.stringify({
1950-
name: groupName.trim(),
2006+
name: groupName,
19512007
sort: 0
19522008
}),
19532009
contentType: 'application/json;charset=UTF-8',
@@ -1957,6 +2013,7 @@ var Settings = {
19572013
return;
19582014
}
19592015
Util.notice('success', 1200, '创建分组成功');
2016+
$('#createEmojiGroupDialog').dialog('close');
19602017
Settings.loadEmojiGroups();
19612018
},
19622019
error: function () {
@@ -2003,38 +2060,30 @@ var Settings = {
20032060
});
20042061
},
20052062
showEmojiShareResult: function (data) {
2006-
if ($('#emojiShareDialog').length === 0) {
2007-
$('body').append('<div id="emojiShareDialog"></div>');
2008-
}
2009-
20102063
var shareCode = data.shareCode || '';
20112064
var groupName = data.groupName || '当前分组';
20122065
var emojiCount = data.emojiCount || 0;
2013-
var html = '' +
2014-
'<div class="emoji-share-dialog fn-clear" style="padding: 18px 20px;">' +
2015-
' <div style="margin-bottom: 12px; color: #666; line-height: 1.7;">' +
2016-
' 已为分组 <b>' + groupName + '</b> 生成永久分享码,当前快照共 ' + emojiCount + ' 个表情。<br>' +
2017-
' 该分享是静态快照,后续你再修改分组内容,不会实时影响这次分享。' +
2018-
' </div>' +
2019-
' <label style="display:block; margin: 0 0 8px; float:none; line-height: 1.6;">分享码:</label>' +
2020-
' <div class="fn__flex" style="gap: 8px; align-items: center;">' +
2021-
' <input id="emojiShareCodeValue" type="text" readonly value="' + shareCode + '" style="flex:1; padding:8px; box-sizing:border-box;" />' +
2022-
' <button class="green" onclick="Settings.copyEmojiShareCode()">复制</button>' +
2023-
' </div>' +
2024-
' <div style="margin-top: 16px;">' +
2025-
' <button class="fn-right green" onclick="$(\'#emojiShareDialog\').dialog(\'close\')">关闭</button>' +
2026-
' </div>' +
2027-
'</div>';
2028-
2029-
$('#emojiShareDialog').html(html);
2030-
$('#emojiShareDialog').dialog({
2031-
'width': $(window).width() > 460 ? 460 : $(window).width() - 50,
2032-
'height': 270,
2033-
'modal': true,
2034-
'hideFooter': true,
2035-
'title': '表情集分享码'
2066+
var html = ''
2067+
+ '<div class="emoji-dialog">'
2068+
+ ' <div class="emoji-dialog__desc">已为分组 <b>' + Settings.escapeDialogHTML(groupName) + '</b> 生成永久分享码,当前快照共 ' + emojiCount + ' 个表情。<br>该分享是静态快照,后续你再修改分组内容,不会实时影响这次分享。</div>'
2069+
+ ' <div class="emoji-dialog__field">'
2070+
+ ' <label class="emoji-dialog__label" for="emojiShareCodeValue">分享码</label>'
2071+
+ ' <div class="emoji-dialog__row">'
2072+
+ ' <input id="emojiShareCodeValue" class="emoji-dialog__input emoji-dialog__input--code" type="text" readonly value="' + Settings.escapeDialogHTML(shareCode) + '" />'
2073+
+ ' <button type="button" class="green" onclick="Settings.copyEmojiShareCode()">复制</button>'
2074+
+ ' </div>'
2075+
+ ' </div>'
2076+
+ ' <div class="emoji-dialog__actions">'
2077+
+ ' <button type="button" class="green" onclick="$(\'#emojiShareDialog\').dialog(\'close\')">关闭</button>'
2078+
+ ' </div>'
2079+
+ '</div>';
2080+
2081+
Settings.openSettingsDialog('emojiShareDialog', {
2082+
html: html,
2083+
title: '表情集分享码',
2084+
width: 460,
2085+
height: 292
20362086
});
2037-
$('#emojiShareDialog').dialog('open');
20382087
$('#emojiShareCodeValue').focus().select();
20392088
},
20402089
copyEmojiShareCode: function () {
@@ -2059,31 +2108,30 @@ var Settings = {
20592108
Util.notice('success', 1200, '分享码已复制');
20602109
},
20612110
importEmojiShare: function () {
2062-
if ($('#emojiShareImportDialog').length === 0) {
2063-
$('body').append('<div id="emojiShareImportDialog"></div>');
2064-
}
2065-
2066-
var html = '' +
2067-
'<div class="emoji-share-dialog fn-clear" style="padding: 18px 20px;">' +
2068-
' <div style="margin-bottom: 12px; color: #666; line-height: 1.7;">请输入别人分享给你的表情集分享码,导入后会在你的账号下新建一个分组。</div>' +
2069-
' <label style="display:block; margin: 0 0 8px; float:none; line-height: 1.6;">分享码:</label>' +
2070-
' <input id="emojiShareImportCode" type="text" placeholder="请输入分享码" style="width:100%; padding:8px; box-sizing:border-box;" />' +
2071-
' <div style="margin-top: 16px;">' +
2072-
' <button class="fn-right green" onclick="Settings.confirmImportEmojiShare()">导入</button>' +
2073-
' <button class="fn-right" style="margin-right: 10px;" onclick="$(\'#emojiShareImportDialog\').dialog(\'close\')">取消</button>' +
2074-
' </div>' +
2075-
'</div>';
2076-
2077-
$('#emojiShareImportDialog').html(html);
2078-
$('#emojiShareImportDialog').dialog({
2079-
'width': $(window).width() > 460 ? 460 : $(window).width() - 50,
2080-
'height': 270,
2081-
'modal': true,
2082-
'hideFooter': true,
2083-
'title': '导入表情集分享码'
2111+
var html = ''
2112+
+ '<div class="emoji-dialog">'
2113+
+ ' <div class="emoji-dialog__desc">请输入别人分享给你的表情集分享码,导入后会在你的账号下新建一个分组。</div>'
2114+
+ ' <div class="emoji-dialog__field">'
2115+
+ ' <label class="emoji-dialog__label" for="emojiShareImportCode">分享码</label>'
2116+
+ ' <input id="emojiShareImportCode" class="emoji-dialog__input emoji-dialog__input--code" type="text" placeholder="请输入分享码" />'
2117+
+ ' </div>'
2118+
+ ' <div class="emoji-dialog__actions">'
2119+
+ ' <button type="button" onclick="$(\'#emojiShareImportDialog\').dialog(\'close\')">取消</button>'
2120+
+ ' <button type="button" class="green" onclick="Settings.confirmImportEmojiShare()">导入</button>'
2121+
+ ' </div>'
2122+
+ '</div>';
2123+
2124+
Settings.openSettingsDialog('emojiShareImportDialog', {
2125+
html: html,
2126+
title: '导入表情集分享码',
2127+
width: 460,
2128+
height: 284
2129+
});
2130+
$('#emojiShareImportCode').focus().off('keydown').on('keydown', function (event) {
2131+
if (event.keyCode === 13) {
2132+
Settings.confirmImportEmojiShare();
2133+
}
20842134
});
2085-
$('#emojiShareImportDialog').dialog('open');
2086-
$('#emojiShareImportCode').focus();
20872135
},
20882136
confirmImportEmojiShare: function () {
20892137
var shareCode = $('#emojiShareImportCode').val().trim();
@@ -2239,36 +2287,40 @@ var Settings = {
22392287
* 显示通过URL添加表情的弹窗
22402288
*/
22412289
addEmojiByUrl: function () {
2242-
// 生成弹窗HTML
2243-
var html = '<div class="form fn-clear" style="padding:0 20px;">';
2244-
2245-
html += '</select>';
2246-
html += '<label>表情URL:</label><br>';
2247-
html += '<input id="emojiUrl" type="text" placeholder="请输入表情图片URL" style="width: 100%; padding: 8px; margin-bottom: 10px;"/>';
2248-
html += '<label>表情别名(可选):</label><br>';
2249-
html += '<input id="emojiAlias" type="text" placeholder="可选,输入表情别名" style="width: 100%; padding: 8px; margin-bottom: 10px;"/>';
2250-
html += '<br><br>';
2251-
html += '<button onclick="Settings.confirmAddUrlEmoji()" class="fn-right green">确定</button>';
2252-
html += '<button onclick="$(\'#addUrlEmojiDialog\').dialog(\'close\')" class="fn-right" style="margin-right: 10px;">取消</button>';
2253-
html += '</div>';
2254-
2255-
// 检查弹窗是否存在,如果不存在则创建
2256-
if ($('#addUrlEmojiDialog').length === 0) {
2257-
$('body').append('<div id="addUrlEmojiDialog"></div>');
2290+
if (!Settings.currentEmojiGroupId) {
2291+
Util.notice('warning', 2000, '请先选择一个分组');
2292+
return;
22582293
}
2259-
2260-
$('#addUrlEmojiDialog').html(html);
2261-
2262-
// 初始化弹窗
2263-
$('#addUrlEmojiDialog').dialog({
2264-
'width': $(window).width() > 400 ? 400 : $(window).width() - 50,
2265-
'height':300,
2266-
'modal': true,
2267-
'hideFooter': true,
2268-
'title': '通过URL添加表情'
2294+
2295+
var html = ''
2296+
+ '<div class="emoji-dialog">'
2297+
+ ' <div class="emoji-dialog__desc">粘贴可直接访问的图片地址,保存后会添加到当前选中的表情分组。</div>'
2298+
+ ' <div class="emoji-dialog__field">'
2299+
+ ' <label class="emoji-dialog__label" for="emojiUrl">表情 URL</label>'
2300+
+ ' <input id="emojiUrl" class="emoji-dialog__input" type="text" placeholder="请输入表情图片 URL" />'
2301+
+ ' </div>'
2302+
+ ' <div class="emoji-dialog__field">'
2303+
+ ' <label class="emoji-dialog__label" for="emojiAlias">表情别名(可选)</label>'
2304+
+ ' <input id="emojiAlias" class="emoji-dialog__input" type="text" maxlength="20" placeholder="可选,输入表情别名" />'
2305+
+ ' </div>'
2306+
+ ' <div class="emoji-dialog__actions">'
2307+
+ ' <button type="button" onclick="$(\'#addUrlEmojiDialog\').dialog(\'close\')">取消</button>'
2308+
+ ' <button type="button" class="green" onclick="Settings.confirmAddUrlEmoji()">确定</button>'
2309+
+ ' </div>'
2310+
+ '</div>';
2311+
2312+
Settings.openSettingsDialog('addUrlEmojiDialog', {
2313+
html: html,
2314+
title: '通过URL添加表情',
2315+
width: 430,
2316+
height: 340
2317+
});
2318+
2319+
$('#emojiUrl').focus().off('keydown').on('keydown', function (event) {
2320+
if (event.keyCode === 13) {
2321+
Settings.confirmAddUrlEmoji();
2322+
}
22692323
});
2270-
2271-
$('#addUrlEmojiDialog').dialog('open');
22722324
},
22732325
/**
22742326
* 确认通过URL添加表情到分组

src/main/resources/js/settings.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/resources/scss/base.scss

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -876,13 +876,32 @@ a[class*=" icon-"]:hover {
876876
}
877877

878878
.dialog-header-bg {
879-
padding: 15px 15px 12px 15px;
879+
display: flex;
880+
align-items: center;
881+
justify-content: space-between;
882+
min-height: 52px;
883+
padding: 0 15px;
884+
}
885+
886+
.dialog-title {
887+
flex: 1;
888+
display: flex;
889+
align-items: center;
890+
min-height: 52px;
891+
font-size: 16px;
892+
font-weight: 600;
893+
line-height: 1.4;
880894
}
881895

882896
.dialog-header-bg .icon-close {
883897
color: rgba(0, 0, 0, 0.25);
884-
font-size: 12px;
885-
float: right;
898+
display: inline-flex;
899+
align-items: center;
900+
justify-content: center;
901+
flex-shrink: 0;
902+
width: 32px;
903+
height: 32px;
904+
margin-left: 12px;
886905
font-weight: bold;
887906
-webkit-user-drag: none;
888907
}
@@ -891,6 +910,11 @@ a[class*=" icon-"]:hover {
891910
color: $black-text;
892911
}
893912

913+
.dialog-main {
914+
padding: 14px;
915+
box-sizing: border-box;
916+
}
917+
894918
.dialog-panel button,
895919
.dialog-panel .btn {
896920
background: rgba(248, 250, 252, 0.1);
@@ -911,6 +935,72 @@ a[class*=" icon-"]:hover {
911935
box-shadow: 0 4px 16px rgba(60,80,120,0.15);
912936
}
913937

938+
.emoji-dialog {
939+
padding: 6px 8px 10px;
940+
}
941+
942+
.emoji-dialog__desc {
943+
margin-bottom: 16px;
944+
color: $theme-secondary;
945+
line-height: 1.7;
946+
}
947+
948+
.emoji-dialog__field + .emoji-dialog__field {
949+
margin-top: 14px;
950+
}
951+
952+
.emoji-dialog__label {
953+
display: block;
954+
margin-bottom: 8px;
955+
color: $theme-secondary;
956+
font-size: 14px;
957+
line-height: 1.5;
958+
}
959+
960+
.emoji-dialog__row {
961+
display: flex;
962+
align-items: center;
963+
gap: 10px;
964+
}
965+
966+
.emoji-dialog__input {
967+
width: 100%;
968+
padding: 10px 12px;
969+
border: 1px solid #d8e1eb;
970+
border-radius: 10px;
971+
box-sizing: border-box;
972+
background: #fff;
973+
color: #222;
974+
box-shadow: inset 0 1px 2px rgba(15, 23, 42, 0.04);
975+
transition: border-color 0.18s ease, box-shadow 0.18s ease, background-color 0.18s ease;
976+
}
977+
978+
.emoji-dialog__input:hover {
979+
border-color: rgba(25, 140, 255, 0.45);
980+
}
981+
982+
.emoji-dialog__input:focus {
983+
border-color: rgba(25, 140, 255, 0.65);
984+
box-shadow: 0 0 0 3px rgba(25, 140, 255, 0.14);
985+
}
986+
987+
.emoji-dialog__input[readonly] {
988+
background: #f6f8fb;
989+
color: #2c3e50;
990+
}
991+
992+
.emoji-dialog__input--code {
993+
letter-spacing: 0.08em;
994+
font-weight: 600;
995+
}
996+
997+
.emoji-dialog__actions {
998+
margin-top: 18px;
999+
display: flex;
1000+
justify-content: flex-end;
1001+
gap: 10px;
1002+
}
1003+
9141004
/* end dialog */
9151005

9161006
/* start framework */

0 commit comments

Comments
 (0)