choices;
38 |
39 | /**
40 | * The API usage for this request.
41 | */
42 | Usage usage;
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/model/completion/chat/ChatMessage.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.model.completion.chat;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.NoArgsConstructor;
6 |
7 | /**
8 | * Each object has a role (either “system”, “user”, or “assistant”) and content (the content of the message). Conversations can be as short as 1 message or fill many pages.
9 | * Typically, a conversation is formatted with a system message first, followed by alternating user and assistant messages.
10 | * The system message helps set the behavior of the assistant. In the example above, the assistant was instructed with “You are a helpful assistant.”
11 | * The user messages help instruct the assistant. They can be generated by the end users of an application, or set by a developer as an instruction.
12 | * The assistant messages help store prior responses. They can also be written by a developer to help give examples of desired behavior.
13 | *
14 | *
15 | * see OpenAi documentation
16 | */
17 | @Data
18 | @NoArgsConstructor
19 | @AllArgsConstructor
20 | public class ChatMessage {
21 |
22 | /**
23 | * Must be either 'system', 'user', or 'assistant'.
24 | * You may use {@link ChatMessageRole} enum.
25 | */
26 | String role;
27 | String content;
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/model/completion/chat/ChatMessageRole.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.model.completion.chat;
2 |
3 | /**
4 | * see {@link ChatMessage} documentation.
5 | */
6 | public enum ChatMessageRole {
7 | SYSTEM("system"),
8 | USER("user"),
9 | ASSISTANT("assistant");
10 |
11 | private final String value;
12 |
13 | ChatMessageRole(final String value) {
14 | this.value = value;
15 | }
16 |
17 | public String value() {
18 | return value;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/model/model/Model.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.model.model;
2 |
3 | import lombok.Data;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * GPT-3 model details
9 | *
10 | * https://beta.openai.com/docs/api-reference/models
11 | */
12 | @Data
13 | public class Model {
14 | /**
15 | * An identifier for this model, used to specify the model when making completions, etc
16 | */
17 | public String id;
18 |
19 | /**
20 | * The type of object returned, should be "model"
21 | */
22 | public String object;
23 |
24 | /**
25 | * The owner of the GPT-3 model, typically "openai"
26 | */
27 | public String ownedBy;
28 |
29 | /**
30 | * List of permissions for this model
31 | */
32 | public List permission;
33 |
34 | /**
35 | * The root model that this and its parent (if applicable) are based on
36 | */
37 | public String root;
38 |
39 | /**
40 | * The parent model that this is based on
41 | */
42 | public String parent;
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/model/model/Permission.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.model.model;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * GPT-3 model permissions
7 | * I couldn't find documentation for the specific permissions, and I've elected to leave them undocumented rather than
8 | * write something incorrect.
9 | *
10 | * https://beta.openai.com/docs/api-reference/models
11 | */
12 | @Data
13 | public class Permission {
14 | /**
15 | * An identifier for this model permission
16 | */
17 | public String id;
18 |
19 | /**
20 | * The type of object returned, should be "model_permission"
21 | */
22 | public String object;
23 |
24 | /**
25 | * The creation time in epoch seconds.
26 | */
27 | public long created;
28 |
29 | public boolean allowCreateEngine;
30 |
31 | public boolean allowSampling;
32 |
33 | public boolean allowLogProbs;
34 |
35 | public boolean allowSearchIndices;
36 |
37 | public boolean allowView;
38 |
39 | public boolean allowFineTuning;
40 |
41 | public String organization;
42 |
43 | public String group;
44 |
45 | public boolean isBlocking;
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/service/ChatService.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.service;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 |
8 | public interface ChatService {
9 | public JSONObject createChatCompletion(HttpServletRequest request, HttpServletResponse response);
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/service/impl/ChatServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.service.impl;
2 |
3 | import com.alibaba.fastjson.JSONObject;
4 | import com.chatweb.comm.PathConstant;
5 | import com.chatweb.core.OpenAiApi;
6 | import com.chatweb.mapper.UserContentDao;
7 | import com.chatweb.model.ExecuteRet;
8 | import com.chatweb.model.UserContent;
9 | import com.chatweb.model.completion.chat.ChatCompletionChoice;
10 | import com.chatweb.model.completion.chat.ChatCompletionRequest;
11 | import com.chatweb.model.completion.chat.ChatMessage;
12 | import com.chatweb.model.completion.chat.ChatMessageRole;
13 | import com.chatweb.service.ChatService;
14 | import com.chatweb.utils.DateUtils;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.beans.factory.annotation.Value;
17 | import org.springframework.stereotype.Service;
18 |
19 | import javax.servlet.http.HttpServletRequest;
20 | import javax.servlet.http.HttpServletResponse;
21 | import java.util.Date;
22 | import java.util.List;
23 |
24 | @Service
25 | public class ChatServiceImpl implements ChatService {
26 | @Value("${session.num}")
27 | private int size;
28 | @Value("${session.time}")
29 | private int sessionTime;
30 | @Value("${token.num}")
31 | private int tokenNum;
32 |
33 | @Autowired
34 | private UserContentDao userContentDao;
35 |
36 | @Autowired
37 | private OpenAiApi openAiApi;
38 |
39 |
40 | public JSONObject createChatCompletion(HttpServletRequest request, HttpServletResponse response) {
41 | String user = "user";
42 | String content = request.getParameter("content");
43 | final List messages = userContentDao.selectMessageForUser(user, size, DateUtils.getBeforeByHourTime(sessionTime));
44 | final ChatMessage systemMessage = new ChatMessage(ChatMessageRole.USER.value(), content);
45 | //消息入库
46 | UserContent userContent = new UserContent();
47 | userContent.setContent(content);
48 | userContent.setRole(ChatMessageRole.USER.value());
49 | userContent.setUser(user);
50 | userContent.setCreateTime(new Date());
51 | userContentDao.insertSelective(userContent);
52 | messages.add(systemMessage);
53 |
54 | ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()
55 | .model("gpt-3.5-turbo-0301")
56 | .messages(messages)
57 | .user("testing")
58 | .max_tokens(tokenNum)
59 | .temperature(1.0)
60 | .build();
61 |
62 | ExecuteRet executeRet = openAiApi.post(PathConstant.COMPLETIONS.CREATE_CHAT_COMPLETION, JSONObject.toJSONString(chatCompletionRequest),
63 | null);
64 | JSONObject result = JSONObject.parseObject(executeRet.getRespStr());
65 | List choices = result.getJSONArray("choices").toJavaList(ChatCompletionChoice.class);
66 | System.out.println(choices.get(0).getMessage().getContent());
67 | ChatMessage context = new ChatMessage(choices.get(0).getMessage().getRole(), choices.get(0).getMessage().getContent());
68 | //消息入库
69 | UserContent aiContent = new UserContent();
70 | aiContent.setContent(context.getContent());
71 | aiContent.setRole(context.getRole());
72 | aiContent.setUser(user);
73 | aiContent.setCreateTime(new Date());
74 | userContentDao.insertSelective(aiContent);
75 | return JSONObject.parseObject(JSONObject.toJSONString(context));
76 |
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/utils/DateUtils.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.utils;
2 |
3 | import java.text.SimpleDateFormat;
4 | import java.util.Calendar;
5 | import java.util.Date;
6 |
7 | public class DateUtils {
8 |
9 | private final static long minute = 60 * 1000;// 1分钟
10 | private final static long hour = 60 * minute;// 1小时
11 | private final static long day = 24 * hour;// 1天
12 | private final static long month = 31 * day;// 月
13 | private final static long year = 12 * month;// 年
14 |
15 | public final static String YYYYMMDDHHMMSS = "yyyyMMddHHmmssSSS";
16 |
17 | /**
18 | * @return
19 | * @author neo
20 | * @date 2015-5-21
21 | */
22 | public static String getDateSequence() {
23 | return new SimpleDateFormat(YYYYMMDDHHMMSS).format(new Date());
24 | }
25 |
26 |
27 | /**
28 | * @return
29 | * @author neo
30 | * @date 2016年8月10日
31 | */
32 | public static long getCurrentTime() {
33 | return System.currentTimeMillis();
34 | }
35 |
36 |
37 | public static String getTimeFormatText(Long date) {
38 | if (date == null) {
39 | return null;
40 | }
41 | long diff = new Date().getTime() - date;
42 | long r = 0;
43 | if (diff > year) {
44 | r = (diff / year);
45 | return r + "年前";
46 | }
47 | if (diff > month) {
48 | r = (diff / month);
49 | return r + "个月前";
50 | }
51 | if (diff > day) {
52 | r = (diff / day);
53 | return r + "天前";
54 | }
55 | if (diff > hour) {
56 | r = (diff / hour);
57 | return r + "个小时前";
58 | }
59 | if (diff > minute) {
60 | r = (diff / minute);
61 | return r + "分钟前";
62 | }
63 | return "刚刚";
64 | }
65 |
66 | /**
67 | * 将时间戳转换成当天0点
68 | *
69 | * @param timestamp
70 | * @return
71 | */
72 | public static long getDayBegin(long timestamp) {
73 | String format = "yyyy-MM-DD";
74 | String toDayString = new SimpleDateFormat(format).format(new Date(timestamp));
75 | Date toDay = null;
76 | try {
77 | toDay = org.apache.commons.lang3.time.DateUtils.parseDate(toDayString, new String[]{format});
78 |
79 | } catch (Exception e) {
80 | throw new RuntimeException(e);
81 | }
82 | return toDay.getTime();
83 | }
84 |
85 | /**
86 | * 获取一个月之前的时间戳
87 | *
88 | * @return
89 | */
90 | public static long getLastMonthTime() {
91 | return getDayBegin(getCurrentTime()) - 86400000l * 30;
92 | }
93 |
94 | public static Date getBeforeByHourTime(int hour) {
95 | Calendar calendar = Calendar.getInstance();
96 | calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - hour);
97 | return calendar.getTime();
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/web/ChatController.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.web;
2 |
3 | import com.chatweb.comm.aop.LoggerManage;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 |
9 | @Controller
10 | @RequestMapping("/")
11 | public class ChatController {
12 |
13 | @RequestMapping(value = "/chat", method = RequestMethod.GET)
14 | @LoggerManage(description = "首页")
15 | public String index(Model model) {
16 | return "chat";
17 | }
18 |
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/web/IndexController.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.web;
2 |
3 | import com.chatweb.comm.aop.LoggerManage;
4 | import org.springframework.stereotype.Controller;
5 | import org.springframework.ui.Model;
6 | import org.springframework.web.bind.annotation.RequestMapping;
7 | import org.springframework.web.bind.annotation.RequestMethod;
8 |
9 | @Controller
10 | @RequestMapping("/")
11 | public class IndexController {
12 |
13 | @RequestMapping(value = "/", method = RequestMethod.GET)
14 | @LoggerManage(description = "首页")
15 | public String index(Model model) {
16 | return "chat";
17 | }
18 | }
--------------------------------------------------------------------------------
/src/main/java/com/chatweb/web/api/RestChatController.java:
--------------------------------------------------------------------------------
1 | package com.chatweb.web.api;
2 |
3 |
4 | import com.alibaba.fastjson.JSONObject;
5 | import com.chatweb.service.ChatService;
6 | import org.springframework.beans.factory.annotation.Autowired;
7 | import org.springframework.web.bind.annotation.RequestMapping;
8 | import org.springframework.web.bind.annotation.RestController;
9 |
10 | import javax.servlet.http.HttpServletRequest;
11 | import javax.servlet.http.HttpServletResponse;
12 |
13 | /**
14 | *
15 | *
16 | * @author wzq 2023/3/7 13:55
17 | * @version V1.0
18 | * @modificationHistory=========================逻辑或功能性重大变更记录
19 | * @modify by user: {修改人} 2023/3/7
20 | * @modify by reason:{方法名}:{原因}
21 | */
22 | @RestController
23 | public class RestChatController {
24 |
25 | @Autowired
26 | private ChatService chatService;
27 |
28 | @RequestMapping("/createChatCompletion")
29 | public JSONObject createChatCompletion(HttpServletRequest request, HttpServletResponse response) {
30 | return chatService.createChatCompletion(request, response);
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 | #spring.profiles.active=dev
2 | server.port=8999
3 | spring.application.name=OpenAi
4 | ###### db config start ######
5 | spring.datasource.url=jdbc:mysql://XXXX:3306/chatweb?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
6 | spring.datasource.username=XXXX
7 | spring.datasource.password=XXX
8 | #spring.datasource.password=Robotbird@123
9 | spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
10 | #mybatis
11 | mybatis.mapper-locations=classpath:mapper/*.xml
12 | mybatis.type-aliases-package=com.wentap.mapper
13 | mybatis.configuration.map-underscore-to-camel-case=true
14 | mybatis.configuration.call-setters-on-nulls=true
15 | ###### logging config start ######
16 | logging.file=./log/service.log
17 | logging.level.com.chatweb=INFO
18 | logging.level.org.springframework.web=INFO
19 | ##### mail setting end #####
20 | spring.thymeleaf.cache=false
21 | ## openAi访问地址,直接访问不通,需要搭建nginx代理进行访问
22 | open.ai.url=https://api.openai.com/
23 | ## API-Key
24 | open.ai.token=XXX
25 | ## 连续会话支持长度
26 | session.num=10
27 | ## 连续会话有效时间(单位:小时)
28 | session.time=4
29 | ## token长度,结果返回的长度
30 | token.num=500
31 | spring.thymeleaf.mode=LEGACYHTML5
--------------------------------------------------------------------------------
/src/main/resources/mapper/UserContentDao.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | id, `user`, `role`, content, create_time
13 |
14 |
15 | select
16 |
17 | from user_content
18 | where id = #{id,jdbcType=BIGINT}
19 |
20 |
21 | select
22 |
23 | from user_content
24 | where user = #{user,jdbcType=BIGINT}
25 | order by create_time desc limit #{size}
26 |
27 |
29 | SELECT a.role,a.content from(
30 | select
31 | id,role,content
32 | from user_content
33 | where user = #{user} and create_time>=#{time}
34 | order by create_time desc
35 | LIMIT 10) AS a
36 | order by id
37 |
38 |
39 | delete from user_content
40 | where id = #{id,jdbcType=BIGINT}
41 |
42 |
44 | insert into user_content (`user`, `role`, content,
45 | create_time)
46 | values (#{user,jdbcType=VARCHAR}, #{role,jdbcType=VARCHAR}, #{content,jdbcType=VARCHAR},
47 | #{createTime,jdbcType=TIMESTAMP})
48 |
49 |
51 | insert into user_content
52 |
53 |
54 | `user`,
55 |
56 |
57 | `role`,
58 |
59 |
60 | content,
61 |
62 |
63 | create_time,
64 |
65 |
66 |
67 |
68 | #{user,jdbcType=VARCHAR},
69 |
70 |
71 | #{role,jdbcType=VARCHAR},
72 |
73 |
74 | #{content,jdbcType=VARCHAR},
75 |
76 |
77 | #{createTime,jdbcType=TIMESTAMP},
78 |
79 |
80 |
81 |
82 | update user_content
83 |
84 |
85 | `user` = #{user,jdbcType=VARCHAR},
86 |
87 |
88 | `role` = #{role,jdbcType=VARCHAR},
89 |
90 |
91 | content = #{content,jdbcType=VARCHAR},
92 |
93 |
94 | create_time = #{createTime,jdbcType=TIMESTAMP},
95 |
96 |
97 | where id = #{id,jdbcType=BIGINT}
98 |
99 |
100 | update user_content
101 | set `user` = #{user,jdbcType=VARCHAR},
102 | `role` = #{role,jdbcType=VARCHAR},
103 | content = #{content,jdbcType=VARCHAR},
104 | create_time = #{createTime,jdbcType=TIMESTAMP}
105 | where id = #{id,jdbcType=BIGINT}
106 |
107 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/litewebchat.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */@charset "UTF-8";
6 | /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
7 | /* Document
8 | ========================================================================== */
9 | /**
10 | * 1. Correct the line height in all browsers.
11 | * 2. Prevent adjustments of font size after orientation changes in iOS.
12 | */
13 | html {
14 | line-height: 1.15; /* 1 */
15 | -webkit-text-size-adjust: 100%; /* 2 */
16 | }
17 |
18 | /* Sections
19 | ========================================================================== */
20 | /**
21 | * Remove the margin in all browsers.
22 | */
23 | body {
24 | margin: 0;
25 | }
26 |
27 | /**
28 | * Render the `main` element consistently in IE.
29 | */
30 | main {
31 | display: block;
32 | }
33 |
34 | /**
35 | * Correct the font size and margin on `h1` elements within `section` and
36 | * `article` contexts in Chrome, Firefox, and Safari.
37 | */
38 | h1 {
39 | font-size: 2em;
40 | margin: 0.67em 0;
41 | }
42 |
43 | /* Grouping content
44 | ========================================================================== */
45 | /**
46 | * 1. Add the correct box sizing in Firefox.
47 | * 2. Show the overflow in Edge and IE.
48 | */
49 | hr {
50 | -webkit-box-sizing: content-box;
51 | box-sizing: content-box; /* 1 */
52 | height: 0; /* 1 */
53 | overflow: visible; /* 2 */
54 | }
55 |
56 | /**
57 | * 1. Correct the inheritance and scaling of font size in all browsers.
58 | * 2. Correct the odd `em` font sizing in all browsers.
59 | */
60 | pre {
61 | font-family: monospace, monospace; /* 1 */
62 | font-size: 1em; /* 2 */
63 | }
64 |
65 | /* Text-level semantics
66 | ========================================================================== */
67 | /**
68 | * Remove the gray background on active links in IE 10.
69 | */
70 | a {
71 | background-color: transparent;
72 | }
73 |
74 | /**
75 | * 1. Remove the bottom border in Chrome 57-
76 | * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
77 | */
78 | abbr[title] {
79 | border-bottom: none; /* 1 */
80 | text-decoration: underline; /* 2 */
81 | -webkit-text-decoration: underline dotted;
82 | text-decoration: underline dotted; /* 2 */
83 | }
84 |
85 | /**
86 | * Add the correct font weight in Chrome, Edge, and Safari.
87 | */
88 | b,
89 | strong {
90 | font-weight: bolder;
91 | }
92 |
93 | /**
94 | * 1. Correct the inheritance and scaling of font size in all browsers.
95 | * 2. Correct the odd `em` font sizing in all browsers.
96 | */
97 | code,
98 | kbd,
99 | samp {
100 | font-family: monospace, monospace; /* 1 */
101 | font-size: 1em; /* 2 */
102 | }
103 |
104 | /**
105 | * Add the correct font size in all browsers.
106 | */
107 | small {
108 | font-size: 80%;
109 | }
110 |
111 | /**
112 | * Prevent `sub` and `sup` elements from affecting the line height in
113 | * all browsers.
114 | */
115 | sub,
116 | sup {
117 | font-size: 75%;
118 | line-height: 0;
119 | position: relative;
120 | vertical-align: baseline;
121 | }
122 |
123 | sub {
124 | bottom: -0.25em;
125 | }
126 |
127 | sup {
128 | top: -0.5em;
129 | }
130 |
131 | /* Embedded content
132 | ========================================================================== */
133 | /**
134 | * Remove the border on images inside links in IE 10.
135 | */
136 | img {
137 | border-style: none;
138 | }
139 |
140 | /* Forms
141 | ========================================================================== */
142 | /**
143 | * 1. Change the font styles in all browsers.
144 | * 2. Remove the margin in Firefox and Safari.
145 | */
146 | button,
147 | input,
148 | optgroup,
149 | select,
150 | textarea {
151 | font-family: inherit; /* 1 */
152 | font-size: 100%; /* 1 */
153 | line-height: 1.15; /* 1 */
154 | margin: 0; /* 2 */
155 | }
156 |
157 | /**
158 | * Show the overflow in IE.
159 | * 1. Show the overflow in Edge.
160 | */
161 | button,
162 | input { /* 1 */
163 | overflow: visible;
164 | }
165 |
166 | /**
167 | * Remove the inheritance of text transform in Edge, Firefox, and IE.
168 | * 1. Remove the inheritance of text transform in Firefox.
169 | */
170 | button,
171 | select { /* 1 */
172 | text-transform: none;
173 | }
174 |
175 | /**
176 | * Correct the inability to style clickable types in iOS and Safari.
177 | */
178 | button,
179 | [type=button],
180 | [type=reset],
181 | [type=submit] {
182 | -webkit-appearance: button;
183 | }
184 |
185 | /**
186 | * Remove the inner border and padding in Firefox.
187 | */
188 | button::-moz-focus-inner,
189 | [type=button]::-moz-focus-inner,
190 | [type=reset]::-moz-focus-inner,
191 | [type=submit]::-moz-focus-inner {
192 | border-style: none;
193 | padding: 0;
194 | }
195 |
196 | /**
197 | * Restore the focus styles unset by the previous rule.
198 | */
199 | button:-moz-focusring,
200 | [type=button]:-moz-focusring,
201 | [type=reset]:-moz-focusring,
202 | [type=submit]:-moz-focusring {
203 | outline: 1px dotted ButtonText;
204 | }
205 |
206 | /**
207 | * Correct the padding in Firefox.
208 | */
209 | fieldset {
210 | padding: 0.35em 0.75em 0.625em;
211 | }
212 |
213 | /**
214 | * 1. Correct the text wrapping in Edge and IE.
215 | * 2. Correct the color inheritance from `fieldset` elements in IE.
216 | * 3. Remove the padding so developers are not caught out when they zero out
217 | * `fieldset` elements in all browsers.
218 | */
219 | legend {
220 | -webkit-box-sizing: border-box;
221 | box-sizing: border-box; /* 1 */
222 | color: inherit; /* 2 */
223 | display: table; /* 1 */
224 | max-width: 100%; /* 1 */
225 | padding: 0; /* 3 */
226 | white-space: normal; /* 1 */
227 | }
228 |
229 | /**
230 | * Add the correct vertical alignment in Chrome, Firefox, and Opera.
231 | */
232 | progress {
233 | vertical-align: baseline;
234 | }
235 |
236 | /**
237 | * Remove the default vertical scrollbar in IE 10+.
238 | */
239 | textarea {
240 | overflow: auto;
241 | }
242 |
243 | /**
244 | * 1. Add the correct box sizing in IE 10.
245 | * 2. Remove the padding in IE 10.
246 | */
247 | [type=checkbox],
248 | [type=radio] {
249 | -webkit-box-sizing: border-box;
250 | box-sizing: border-box; /* 1 */
251 | padding: 0; /* 2 */
252 | }
253 |
254 | /**
255 | * Correct the cursor style of increment and decrement buttons in Chrome.
256 | */
257 | [type=number]::-webkit-inner-spin-button,
258 | [type=number]::-webkit-outer-spin-button {
259 | height: auto;
260 | }
261 |
262 | /**
263 | * 1. Correct the odd appearance in Chrome and Safari.
264 | * 2. Correct the outline style in Safari.
265 | */
266 | [type=search] {
267 | -webkit-appearance: textfield; /* 1 */
268 | outline-offset: -2px; /* 2 */
269 | }
270 |
271 | /**
272 | * Remove the inner padding in Chrome and Safari on macOS.
273 | */
274 | [type=search]::-webkit-search-decoration {
275 | -webkit-appearance: none;
276 | }
277 |
278 | /**
279 | * 1. Correct the inability to style clickable types in iOS and Safari.
280 | * 2. Change font properties to `inherit` in Safari.
281 | */
282 | ::-webkit-file-upload-button {
283 | -webkit-appearance: button; /* 1 */
284 | font: inherit; /* 2 */
285 | }
286 |
287 | /* Interactive
288 | ========================================================================== */
289 | /*
290 | * Add the correct display in Edge, IE 10+, and Firefox.
291 | */
292 | details {
293 | display: block;
294 | }
295 |
296 | /*
297 | * Add the correct display in all browsers.
298 | */
299 | summary {
300 | display: list-item;
301 | }
302 |
303 | /* Misc
304 | ========================================================================== */
305 | /**
306 | * Add the correct display in IE 10+.
307 | */
308 | template {
309 | display: none;
310 | }
311 |
312 | /**
313 | * Add the correct display in IE 10.
314 | */
315 | [hidden] {
316 | display: none;
317 | }
318 |
319 | * {
320 | scrollbar-color: #5c6163 rgba(56, 59, 60, 0.031372549);
321 | }
322 |
323 | /* else broswer */
324 | ::-webkit-scrollbar {
325 | /* 滚动条整体样式 */
326 | width: 7px;
327 | /* 高宽分别对应横竖滚动条的尺寸 */
328 | height: 1px;
329 | }
330 |
331 | ::-webkit-scrollbar-thumb {
332 | /*滚动条里面小方块*/
333 | border-radius: 10px;
334 | background-color: rgba(144, 147, 153, 0.5);
335 | border: 0;
336 | }
337 | [litewebchat-theme=dark] ::-webkit-scrollbar-thumb {
338 | background-color: rgba(84, 91, 95, 0.5);
339 | }
340 |
341 | ::-webkit-scrollbar-track {
342 | /*滚动条里面轨道*/
343 | background: #fff;
344 | min-height: 50%;
345 | min-height: 20px;
346 | }
347 | [litewebchat-theme=dark] ::-webkit-scrollbar-track {
348 | background: rgb(24, 26, 27);
349 | }
350 |
351 | ::-webkit-scrollbar-corner {
352 | background-color: transparent;
353 | }
354 |
355 | ::-moz-selection {
356 | background-color: #1963bd !important;
357 | color: #f8f6f3 !important;
358 | }
359 |
360 | ::selection {
361 | background-color: #1963bd !important;
362 | color: #f8f6f3 !important;
363 | }
364 |
365 | body {
366 | font-family: Helvetica, "PingFang SC", "Microsoft YaHei", sans-serif;
367 | }
368 |
369 | .lite-chatbox {
370 | scroll-behavior: smooth;
371 | padding: 0px;
372 | width: 100%;
373 | position: relative;
374 | font-size: 18px;
375 | background-color: #f8f9fa;
376 | overflow-y: auto;
377 | overflow-x: hidden;
378 | }
379 | .lite-chatbox .tips {
380 | margin: 12px;
381 | text-align: center;
382 | font-size: 12px;
383 | }
384 | .lite-chatbox .tips span {
385 | display: inline-block;
386 | padding: 4px;
387 | background-color: #ccc;
388 | color: #fff;
389 | border-radius: 6px;
390 | }
391 | [litewebchat-theme=dark] .lite-chatbox .tips span {
392 | background-color: rgba(0, 0, 0, 0.3);
393 | }
394 | [litewebchat-theme=dark] .lite-chatbox .tips span {
395 | color: #bec5cc;
396 | }
397 | .lite-chatbox .tips .tips-primary {
398 | background-color: #3986c8;
399 | }
400 | [litewebchat-theme=dark] .lite-chatbox .tips .tips-primary {
401 | background-color: rgb(68, 127, 178);
402 | }
403 | .lite-chatbox .tips .tips-success {
404 | background-color: #49b649;
405 | }
406 | [litewebchat-theme=dark] .lite-chatbox .tips .tips-success {
407 | background-color: rgb(102, 166, 81);
408 | }
409 | .lite-chatbox .tips .tips-info {
410 | background-color: #5bb6d1;
411 | }
412 | [litewebchat-theme=dark] .lite-chatbox .tips .tips-info {
413 | background-color: rgb(63, 136, 158);
414 | }
415 | .lite-chatbox .tips .tips-warning {
416 | background-color: #eea948;
417 | }
418 | [litewebchat-theme=dark] .lite-chatbox .tips .tips-warning {
419 | background-color: rgb(175, 119, 40);
420 | }
421 | .lite-chatbox .tips .tips-danger {
422 | background-color: #e24d48;
423 | }
424 | [litewebchat-theme=dark] .lite-chatbox .tips .tips-danger {
425 | background-color: rgb(173, 53, 49);
426 | }
427 | [litewebchat-theme=dark] .lite-chatbox {
428 | background-color: #131415;
429 | }
430 | .lite-chatbox .cmsg {
431 | position: relative;
432 | margin: 4px 7px;
433 | min-height: 50px;
434 | border: 0;
435 | }
436 | .lite-chatbox .cright {
437 | text-align: right;
438 | margin-left: 64px;
439 | }
440 | .lite-chatbox .cright img.headIcon {
441 | right: 0;
442 | }
443 | .lite-chatbox .cright .name {
444 | margin: 0 48px 2px 0;
445 | }
446 | .lite-chatbox .cright .content {
447 | margin: 0 48px 0 0;
448 | border-radius: 20px 0 20px 20px;
449 | color: white;
450 | background: -o-linear-gradient(70deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);
451 | background: linear-gradient(20deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);
452 | -webkit-box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.15);
453 | box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.15);
454 | }
455 | [litewebchat-theme=dark] .lite-chatbox .cright .content {
456 | background: -o-linear-gradient(70deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);
457 | background: linear-gradient(20deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);
458 | }
459 | .lite-chatbox .cright .content::after {
460 | left: -12px;
461 | top: 8px;
462 | }
463 | .lite-chatbox .cleft {
464 | text-align: left;
465 | margin-right: 64px;
466 | }
467 | .lite-chatbox .cleft img.headIcon {
468 | left: 0;
469 | }
470 | .lite-chatbox .cleft .name {
471 | margin: 0 0 2px 48px;
472 | }
473 | .lite-chatbox .cleft .content {
474 | margin: 0 0 0 48px;
475 | border-radius: 0 20px 20px 20px;
476 | background: #fff;
477 | color: #373737;
478 | border: 1px solid rgba(0, 0, 0, 0.05);
479 | -webkit-box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);
480 | box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);
481 | }
482 | [litewebchat-theme=dark] .lite-chatbox .cleft .content {
483 | background: #22242a;
484 | }
485 | [litewebchat-theme=dark] .lite-chatbox .cleft .content {
486 | color: #d4d4d4;
487 | }
488 | .lite-chatbox .cleft .content::after {
489 | left: -12px;
490 | top: 8px;
491 | }
492 | .lite-chatbox img.headIcon {
493 | width: 34px;
494 | height: 34px;
495 | top: 9px;
496 | position: absolute;
497 | }
498 | .lite-chatbox img.radius {
499 | border-radius: 50%;
500 | }
501 | .lite-chatbox .name {
502 | color: #8b8b8b;
503 | font-size: 12px;
504 | display: block;
505 | line-height: 18px;
506 | }
507 | .lite-chatbox .name > span {
508 | vertical-align: middle;
509 | }
510 | .lite-chatbox .name .htitle {
511 | display: inline-block;
512 | padding: 0 3px 0 3px;
513 | background-color: #cccccc;
514 | color: #ffffff;
515 | border-radius: 4px;
516 | margin-right: 4px;
517 | font-size: 11px;
518 | overflow: hidden;
519 | -o-text-overflow: ellipsis;
520 | text-overflow: ellipsis;
521 | white-space: nowrap;
522 | vertical-align: middle;
523 | max-width: 50px;
524 | }
525 | [litewebchat-theme=dark] .lite-chatbox .name .htitle {
526 | background-color: rgb(76, 80, 82);
527 | }
528 | .lite-chatbox .name .htitle.admin {
529 | background-color: #72D6A0;
530 | }
531 | [litewebchat-theme=dark] .lite-chatbox .name .htitle.admin {
532 | background-color: rgb(60, 145, 110);
533 | }
534 | .lite-chatbox .name .htitle.owner {
535 | background-color: #F2BF25;
536 | }
537 | [litewebchat-theme=dark] .lite-chatbox .name .htitle.owner {
538 | background-color: rgb(154, 124, 33);
539 | }
540 | .lite-chatbox .content {
541 | word-break: break-all;
542 | word-wrap: break-word;
543 | text-align: left;
544 | position: relative;
545 | display: inline-block;
546 | font-size: 15px;
547 | padding: 10px 15px;
548 | line-height: 20px;
549 | white-space: pre-wrap;
550 | min-width: 9px;
551 | min-height: 18px;
552 | }
553 | .lite-chatbox .content img {
554 | width: 100%;
555 | height: auto;
556 | }
557 | .lite-chatbox .content a {
558 | color: #0072C1;
559 | margin: 0 5px;
560 | cursor: hand;
561 | }
562 | [litewebchat-theme=dark] .lite-chatbox .content a {
563 | color: #00c3ff;
564 | }
565 | /*# sourceMappingURL=map/litewebchat.css.map */
566 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/litewebchat.min.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";/*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | *//*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}*{scrollbar-color:#5c6163 rgba(56,59,60,.031372549)}::-webkit-scrollbar{width:7px;height:1px}::-webkit-scrollbar-thumb{border-radius:10px;background-color:rgba(144,147,153,.5);border:0}[litewebchat-theme=dark] ::-webkit-scrollbar-thumb{background-color:rgba(84,91,95,.5)}::-webkit-scrollbar-track{background:#fff;min-height:50%;min-height:20px}[litewebchat-theme=dark] ::-webkit-scrollbar-track{background:#181a1b}::-webkit-scrollbar-corner{background-color:transparent}::-moz-selection{background-color:#1963bd!important;color:#f8f6f3!important}::selection{background-color:#1963bd!important;color:#f8f6f3!important}body{font-family:Helvetica,"PingFang SC","Microsoft YaHei",sans-serif}.lite-chatbox{scroll-behavior:smooth;padding:0;width:100%;position:relative;font-size:18px;background-color:#f8f9fa;overflow-y:auto;overflow-x:hidden}.lite-chatbox .tips{margin:12px;text-align:center;font-size:12px}.lite-chatbox .tips span{display:inline-block;padding:4px;background-color:#ccc;color:#fff;border-radius:6px}[litewebchat-theme=dark] .lite-chatbox .tips span{background-color:rgba(0,0,0,.3)}[litewebchat-theme=dark] .lite-chatbox .tips span{color:#bec5cc}.lite-chatbox .tips .tips-primary{background-color:#3986c8}[litewebchat-theme=dark] .lite-chatbox .tips .tips-primary{background-color:#447fb2}.lite-chatbox .tips .tips-success{background-color:#49b649}[litewebchat-theme=dark] .lite-chatbox .tips .tips-success{background-color:#66a651}.lite-chatbox .tips .tips-info{background-color:#5bb6d1}[litewebchat-theme=dark] .lite-chatbox .tips .tips-info{background-color:#3f889e}.lite-chatbox .tips .tips-warning{background-color:#eea948}[litewebchat-theme=dark] .lite-chatbox .tips .tips-warning{background-color:#af7728}.lite-chatbox .tips .tips-danger{background-color:#e24d48}[litewebchat-theme=dark] .lite-chatbox .tips .tips-danger{background-color:#ad3531}[litewebchat-theme=dark] .lite-chatbox{background-color:#131415}.lite-chatbox .cmsg{position:relative;margin:4px 7px;min-height:50px;border:0}.lite-chatbox .cright{text-align:right;margin-left:64px}.lite-chatbox .cright img.headIcon{right:0}.lite-chatbox .cright .name{margin:0 48px 2px 0}.lite-chatbox .cright .content{margin:0 48px 0 0;border-radius:20px 0 20px 20px;color:#fff;background:-o-linear-gradient(70deg,rgba(63,143,225,.8) 0,#44d7c9 100%);background:linear-gradient(20deg,rgba(63,143,225,.8) 0,#44d7c9 100%);-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,.15);box-shadow:5px 5px 15px 0 rgba(102,102,102,.15)}[litewebchat-theme=dark] .lite-chatbox .cright .content{background:-o-linear-gradient(70deg,rgba(25,91,159,.8) 0,#219a92 100%);background:linear-gradient(20deg,rgba(25,91,159,.8) 0,#219a92 100%)}.lite-chatbox .cright .content::after{left:-12px;top:8px}.lite-chatbox .cleft{text-align:left;margin-right:64px}.lite-chatbox .cleft img.headIcon{left:0}.lite-chatbox .cleft .name{margin:0 0 2px 48px}.lite-chatbox .cleft .content{margin:0 0 0 48px;border-radius:0 20px 20px 20px;background:#fff;color:#373737;border:1px solid rgba(0,0,0,.05);-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,.1);box-shadow:5px 5px 15px 0 rgba(102,102,102,.1)}[litewebchat-theme=dark] .lite-chatbox .cleft .content{background:#22242a}[litewebchat-theme=dark] .lite-chatbox .cleft .content{color:#d4d4d4}.lite-chatbox .cleft .content::after{left:-12px;top:8px}.lite-chatbox img.headIcon{width:34px;height:34px;top:9px;position:absolute}.lite-chatbox img.radius{border-radius:50%}.lite-chatbox .name{color:#8b8b8b;font-size:12px;display:block;line-height:18px}.lite-chatbox .name>span{vertical-align:middle}.lite-chatbox .name .htitle{display:inline-block;padding:0 3px 0 3px;background-color:#ccc;color:#fff;border-radius:4px;margin-right:4px;font-size:11px;overflow:hidden;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:50px}[litewebchat-theme=dark] .lite-chatbox .name .htitle{background-color:#4c5052}.lite-chatbox .name .htitle.admin{background-color:#72d6a0}[litewebchat-theme=dark] .lite-chatbox .name .htitle.admin{background-color:#3c916e}.lite-chatbox .name .htitle.owner{background-color:#f2bf25}[litewebchat-theme=dark] .lite-chatbox .name .htitle.owner{background-color:#9a7c21}.lite-chatbox .content{word-break:break-all;word-wrap:break-word;text-align:left;position:relative;display:inline-block;font-size:15px;padding:10px 15px;line-height:20px;white-space:pre-wrap;min-width:9px;min-height:18px}.lite-chatbox .content img{width:100%;height:auto}.lite-chatbox .content a{color:#0072c1;margin:0 5px;cursor:hand}[litewebchat-theme=dark] .lite-chatbox .content a{color:#00c3ff}
6 | /*# sourceMappingURL=map/litewebchat.min.css.map */
7 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/litewebchat_input.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */@charset "UTF-8";
6 | .lite-chatbox {
7 | height: calc(100% - 150px);
8 | }
9 | .lite-chatbox > div:last-child {
10 | margin-bottom: 20px;
11 | }
12 |
13 | .lite-chatinput {
14 | width: 100%;
15 | height: 150px;
16 | position: relative;
17 | bottom: 0px;
18 | background-color: #fff;
19 | }
20 | [litewebchat-theme=dark] .lite-chatinput {
21 | background-color: #202223;
22 | }
23 | .lite-chatinput img {
24 | max-width: 150px;
25 | max-height: 150px;
26 | -o-object-fit: contain;
27 | object-fit: contain;
28 | }
29 | .lite-chatinput .boundary {
30 | cursor: s-resize;
31 | margin: 0 auto;
32 | border-width: 1px 0px 0px 0px;
33 | border-color: rgba(0, 0, 0, 0.2);
34 | height: 5px;
35 | background: #fff;
36 | }
37 | [litewebchat-theme=dark] .lite-chatinput .boundary {
38 | background: #202223;
39 | }
40 | .lite-chatinput > .chatinput {
41 | position: relative;
42 | overflow-y: scroll;
43 | /* margin: 0px 3px 0px 3px; */
44 | width: calc(100% - 6px);
45 | margin: auto;
46 | /* width: 100%; */
47 | height: calc(100% - 75px);
48 | /* height: 100%; */
49 | border: none;
50 | outline: none;
51 | resize: none;
52 | font-size: 18px;
53 | color: #373737;
54 | word-break: break-all;
55 | overflow-wrap: break-word;
56 | padding: 5px;
57 | outline: none;
58 | }
59 | [litewebchat-theme=dark] .lite-chatinput > .chatinput {
60 | color: #d4d4d4;
61 | }
62 | .lite-chatinput .send {
63 | float: right;
64 | padding: 4px 20px 4px 20px;
65 | margin-right: 12px;
66 | margin-top: -2px;
67 | color: white;
68 | background: -o-linear-gradient(70deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);
69 | background: linear-gradient(20deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);
70 | -webkit-box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);
71 | box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);
72 | border: none;
73 | border-radius: 4px;
74 | -webkit-transition: all 0.2s;
75 | -o-transition: all 0.2s;
76 | transition: all 0.2s;
77 | }
78 | [litewebchat-theme=dark] .lite-chatinput .send {
79 | background: -o-linear-gradient(70deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);
80 | background: linear-gradient(20deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);
81 | }
82 | .lite-chatinput .send:hover {
83 | -webkit-transform: scale(1.1);
84 | -ms-transform: scale(1.1);
85 | transform: scale(1.1);
86 | opacity: 0.7;
87 | }
88 | .lite-chatinput .send:active {
89 | -webkit-transform: scale(0.9);
90 | -ms-transform: scale(0.9);
91 | transform: scale(0.9);
92 | opacity: 1;
93 | }
94 | .lite-chatinput .tool-button {
95 | padding: 0px 3px 0px 3px;
96 | background: none;
97 | border: none;
98 | margin: 5px;
99 | margin-bottom: 0px;
100 | -webkit-transition: all 0.2s;
101 | -o-transition: all 0.2s;
102 | transition: all 0.2s;
103 | }
104 | .lite-chatinput .tool-button:hover {
105 | -webkit-transform: scale(1.1);
106 | -ms-transform: scale(1.1);
107 | transform: scale(1.1);
108 | opacity: 0.7;
109 | }
110 | .lite-chatinput .tool-button:active {
111 | -webkit-transform: scale(0.9);
112 | -ms-transform: scale(0.9);
113 | transform: scale(0.9);
114 | opacity: 1;
115 | }
116 | .lite-chatinput .tool-button path {
117 | fill: rgb(139, 135, 153);
118 | }
119 | .lite-chatinput .tool-button svg {
120 | width: 18px;
121 | }
122 |
123 | /* 由功能按钮唤起的功能页面 */
124 | .lite-chatbox-tool {
125 | /* border: 5px solid red; */
126 | position: absolute;
127 | /* bottom: 20px; */
128 | margin-left: 3px;
129 | z-index: 3;
130 | }
131 |
132 | /* 部分功能页面需要用到的遮罩 */
133 | #toolMusk {
134 | /* border: 3px solid red; */
135 | position: absolute;
136 | width: 100vw;
137 | height: 100vh;
138 | top: 0;
139 | left: 0;
140 | z-index: 2;
141 | }
142 |
143 | .float-left {
144 | float: left;
145 | }
146 |
147 | .float-right {
148 | float: right;
149 | }
150 | /*# sourceMappingURL=map/litewebchat_input.css.map */
151 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/litewebchat_input.min.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";/*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */.lite-chatbox{height:calc(100% - 150px)}.lite-chatbox>div:last-child{margin-bottom:20px}.lite-chatinput{width:100%;height:150px;position:relative;bottom:0;background-color:#fff}[litewebchat-theme=dark] .lite-chatinput{background-color:#202223}.lite-chatinput img{max-width:150px;max-height:150px;-o-object-fit:contain;object-fit:contain}.lite-chatinput .boundary{cursor:s-resize;margin:0 auto;border-width:1px 0 0 0;border-color:rgba(0,0,0,.2);height:5px;background:#fff}[litewebchat-theme=dark] .lite-chatinput .boundary{background:#202223}.lite-chatinput>.chatinput{position:relative;overflow-y:scroll;width:calc(100% - 6px);margin:auto;height:calc(100% - 75px);border:none;outline:0;resize:none;font-size:18px;color:#373737;word-break:break-all;overflow-wrap:break-word;padding:5px;outline:0}[litewebchat-theme=dark] .lite-chatinput>.chatinput{color:#d4d4d4}.lite-chatinput .send{float:right;padding:4px 20px 4px 20px;margin-right:12px;margin-top:-2px;color:#fff;background:-o-linear-gradient(70deg,rgba(63,143,225,.8) 0,#44d7c9 100%);background:linear-gradient(20deg,rgba(63,143,225,.8) 0,#44d7c9 100%);-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,.1);box-shadow:5px 5px 15px 0 rgba(102,102,102,.1);border:none;border-radius:4px;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}[litewebchat-theme=dark] .lite-chatinput .send{background:-o-linear-gradient(70deg,rgba(25,91,159,.8) 0,#219a92 100%);background:linear-gradient(20deg,rgba(25,91,159,.8) 0,#219a92 100%)}.lite-chatinput .send:hover{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1);opacity:.7}.lite-chatinput .send:active{-webkit-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9);opacity:1}.lite-chatinput .tool-button{padding:0 3px 0 3px;background:0 0;border:none;margin:5px;margin-bottom:0;-webkit-transition:all .2s;-o-transition:all .2s;transition:all .2s}.lite-chatinput .tool-button:hover{-webkit-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1);opacity:.7}.lite-chatinput .tool-button:active{-webkit-transform:scale(.9);-ms-transform:scale(.9);transform:scale(.9);opacity:1}.lite-chatinput .tool-button path{fill:#8b8799}.lite-chatinput .tool-button svg{width:18px}.lite-chatbox-tool{position:absolute;margin-left:3px;z-index:3}#toolMusk{position:absolute;width:100vw;height:100vh;top:0;left:0;z-index:2}.float-left{float:left}.float-right{float:right}
6 | /*# sourceMappingURL=map/litewebchat_input.min.css.map */
7 |
--------------------------------------------------------------------------------
/src/main/resources/static/css/map/litewebchat_input.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["chatinput.css","chatinput.scss","mixin/_theme.scss","mixin/_helper.scss"],"names":[],"mappings":"AAAA;;;;EAIE,CAAC,gBAAgB;ACEnB;EACE,0BAAA;ADAF;ACGE;EACE,mBAAA;ADDJ;;ACMA;EACE,WAAA;EACA,aAAA;EACA,kBAAA;EACA,WAAA;ECZI,sBAAA;AFUN;AEJM;EACE,yBAAA;AFMR;ACGE;EACE,gBAAA;EACA,iBAAA;EACA,sBAAA;KAAA,mBAAA;ADDJ;ACKE;EACE,gBAAA;EACA,cAAA;EACA,6BAAA;EACA,gCAAA;EACA,WAAA;EC5BE,gBAAA;AF0BN;AEpBM;EACE,mBAAA;AFsBR;ACIE;EACE,kBAAA;EACA,kBAAA;EACA,6BAAA;EACA,uBAAA;EACA,YAAA;EACA,iBAAA;EACA,yBAAA;EACA,kBAAA;EACA,YAAA;EACA,aAAA;EACA,YAAA;EACA,eAAA;EC7CE,cAAA;ED+CF,qBAAA;EACA,yBAAA;EACA,YAAA;EACA,aAAA;ADFJ;AE1CM;EACE,cAAA;AF4CR;ACGE;EACE,YAAA;EACA,0BAAA;EAGE,kBAAA;EACA,gBAAA;EAGF,YAAA;EC/DE,+EAAA;EAAA,4EAAA;EDiEF,2DAAA;UAAA,mDAAA;EACA,YAAA;EACA,kBAAA;EElEF,4BAAA;EAAA,uBAAA;EAAA,oBAAA;AH8DF;AEzDM;EACE,yFAAA;EAAA,sFAAA;AF2DR;AG/DE;EACE,6BAAA;MAAA,yBAAA;UAAA,qBAAA;EACA,YAAA;AHiEJ;AG9DE;EACE,6BAAA;MAAA,yBAAA;UAAA,qBAAA;EACA,UAAA;AHgEJ;ACFE;EACE,wBAAA;EACA,gBAAA;EACA,YAAA;EACA,WAAA;EACA,kBAAA;EE5EF,4BAAA;EAAA,uBAAA;EAAA,oBAAA;AHiFF;AG/EE;EACE,6BAAA;MAAA,yBAAA;UAAA,qBAAA;EACA,YAAA;AHiFJ;AG9EE;EACE,6BAAA;MAAA,yBAAA;UAAA,qBAAA;EACA,UAAA;AHgFJ;ACVI;EACE,wBAAA;ADYN;ACTI;EACE,WAAA;ADWN;;ACJA,iBAAA;AACA;EACE,2BAAA;EACA,kBAAA;EACA,kBAAA;EACA,gBAAA;EACA,UAAA;ADOF;;ACJA,kBAAA;AACA;EACE,2BAAA;EACA,kBAAA;EACA,YAAA;EACA,aAAA;EACA,MAAA;EACA,OAAA;EACA,UAAA;ADOF;;ACJA;EACE,WAAA;ADOF;;ACJA;EACE,YAAA;ADOF","file":"../litewebchat_input.css","sourcesContent":["/*!\n * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)\n * MorFans Lab(c) 2017-2023\n * Licensed under LGPL\n */@charset \"UTF-8\";\n.lite-chatbox {\n height: calc(100% - 150px);\n}\n.lite-chatbox > div:last-child {\n margin-bottom: 20px;\n}\n\n.lite-chatinput {\n width: 100%;\n height: 150px;\n position: relative;\n bottom: 0px;\n background-color: #fff;\n}\n[litewebchat-theme=dark] .lite-chatinput {\n background-color: #202223;\n}\n.lite-chatinput img {\n max-width: 150px;\n max-height: 150px;\n object-fit: contain;\n}\n.lite-chatinput .boundary {\n cursor: s-resize;\n margin: 0 auto;\n border-width: 1px 0px 0px 0px;\n border-color: rgba(0, 0, 0, 0.2);\n height: 5px;\n background: #fff;\n}\n[litewebchat-theme=dark] .lite-chatinput .boundary {\n background: #202223;\n}\n.lite-chatinput > .chatinput {\n position: relative;\n overflow-y: scroll;\n /* margin: 0px 3px 0px 3px; */\n width: calc(100% - 6px);\n margin: auto;\n /* width: 100%; */\n height: calc(100% - 75px);\n /* height: 100%; */\n border: none;\n outline: none;\n resize: none;\n font-size: 18px;\n color: #373737;\n word-break: break-all;\n overflow-wrap: break-word;\n padding: 5px;\n outline: none;\n}\n[litewebchat-theme=dark] .lite-chatinput > .chatinput {\n color: #d4d4d4;\n}\n.lite-chatinput .send {\n float: right;\n padding: 4px 20px 4px 20px;\n margin-right: 12px;\n margin-top: -2px;\n color: white;\n background: linear-gradient(20deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);\n box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);\n border: none;\n border-radius: 4px;\n transition: all 0.2s;\n}\n[litewebchat-theme=dark] .lite-chatinput .send {\n background: linear-gradient(20deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);\n}\n.lite-chatinput .send:hover {\n transform: scale(1.1);\n opacity: 0.7;\n}\n.lite-chatinput .send:active {\n transform: scale(0.9);\n opacity: 1;\n}\n.lite-chatinput .tool-button {\n padding: 0px 3px 0px 3px;\n background: none;\n border: none;\n margin: 5px;\n margin-bottom: 0px;\n transition: all 0.2s;\n}\n.lite-chatinput .tool-button:hover {\n transform: scale(1.1);\n opacity: 0.7;\n}\n.lite-chatinput .tool-button:active {\n transform: scale(0.9);\n opacity: 1;\n}\n.lite-chatinput .tool-button path {\n fill: rgb(139, 135, 153);\n}\n.lite-chatinput .tool-button svg {\n width: 18px;\n}\n\n/* 由功能按钮唤起的功能页面 */\n.lite-chatbox-tool {\n /* border: 5px solid red; */\n position: absolute;\n /* bottom: 20px; */\n margin-left: 3px;\n z-index: 3;\n}\n\n/* 部分功能页面需要用到的遮罩 */\n#toolMusk {\n /* border: 3px solid red; */\n position: absolute;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.float-left {\n float: left;\n}\n\n.float-right {\n float: right;\n}","@import './mixin/theme';\n@import './mixin/helper';\n\n@import './variable';\n\n// 聊天区域\n.lite-chatbox {\n height: calc(100% - 150px);\n\n //.lite-chatbox内的最后一条消息的margin-bottom设置为20px,离下面远一点\n >div:last-child {\n margin-bottom: 20px;\n }\n}\n\n// 输入框\n.lite-chatinput {\n width: 100%;\n height: 150px;\n position: relative;\n bottom: 0px;\n @include theme('background-color', $chat-bg-color-input);\n\n // 缩小输入框内的图片,方便编辑\n img {\n max-width: 150px;\n max-height: 150px;\n object-fit: contain;\n }\n\n // 聊天区域和输入框的分界线\n .boundary {\n cursor: s-resize;\n margin: 0 auto;\n border-width: 1px 0px 0px 0px;\n border-color: rgba(0, 0, 0, 0.2);\n height: 5px;\n @include theme('background', $chat-bg-color-input);\n }\n\n // 输入框\n >.chatinput {\n position: relative;\n overflow-y: scroll;\n /* margin: 0px 3px 0px 3px; */\n width: calc(100% - 6px);\n margin: auto;\n /* width: 100%; */\n height: calc(100% - 75px);\n /* height: 100%; */\n border: none;\n outline: none;\n resize: none;\n font-size: 18px;\n @include theme('color', $chat-color-input);\n word-break: break-all;\n overflow-wrap: break-word;\n padding: 5px;\n outline: none;\n }\n\n // 发送按钮\n .send {\n float: right;\n padding: 4px 20px 4px 20px;\n\n margin: {\n right: 12px;\n top: -2px;\n }\n\n color: white;\n @include theme('background', $chat-message-bg-color-me);\n box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);\n border: none;\n border-radius: 4px;\n @include push-animate;\n }\n\n // 输入框上方的输入表情等功能按钮\n .tool-button {\n padding: 0px 3px 0px 3px;\n background: none;\n border: none;\n margin: 5px;\n margin-bottom: 0px;\n @include push-animate;\n\n path {\n fill: rgb(139, 135, 153);\n }\n\n svg {\n width: 18px;\n }\n }\n\n // end of.tool-button\n}\n\n/* 由功能按钮唤起的功能页面 */\n.lite-chatbox-tool {\n /* border: 5px solid red; */\n position: absolute;\n /* bottom: 20px; */\n margin-left: 3px;\n z-index: 3;\n}\n\n/* 部分功能页面需要用到的遮罩 */\n#toolMusk {\n /* border: 3px solid red; */\n position: absolute;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.float-left {\n float: left;\n}\n\n.float-right {\n float: right;\n}\n","@mixin theme($key, $map_key) {\n $theme_colors: light,\n dark;\n\n @each $theme in $theme_colors {\n\n @if $theme ==light {\n // default light\n #{$key}: map-get($map: $map_key, $key: $theme);\n }\n\n @else {\n\n // 生成其他\n [litewebchat-theme=#{$theme}] & {\n #{$key}: map-get($map: $map_key, $key: $theme);\n }\n }\n }\n}\n","@use \"sass:selector\";\n\n@mixin unify-parent($child) {\n @at-root #{selector.unify(&, $child)} {\n @content;\n }\n}\n\n@mixin push-animate($time: .2, $scaleHover: 1.1, $scalePush: 0.9) {\n transition: all #{$time}s; // 让按下有呼吸感\n\n &:hover {\n transform: scale($scaleHover);\n opacity: .7;\n }\n\n &:active {\n transform: scale($scalePush);\n opacity: 1;\n }\n}\n"]}
--------------------------------------------------------------------------------
/src/main/resources/static/css/map/litewebchat_input.min.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["chatinput.css","chatinput.scss","mixin/_theme.scss","mixin/_helper.scss"],"names":[],"mappings":"iBAAA;;;;ACMA,cACE,OAAA,mBAGA,6BACE,cAAA,KAKJ,gBACE,MAAA,KACA,OAAA,MACA,SAAA,SACA,OAAA,ECZI,iBAAA,KAMA,yCACE,iBAAA,QDSN,oBACE,UAAA,MACA,WAAA,MACA,cAAA,QAAA,WAAA,QAIF,0BACE,OAAA,SACA,OAAA,EAAA,KACA,aAAA,IAAA,EAAA,EAAA,EACA,aAAA,eACA,OAAA,IC5BE,WAAA,KAMA,mDACE,WAAA,QD0BN,2BACE,SAAA,SACA,WAAA,OAEA,MAAA,iBACA,OAAA,KAEA,OAAA,kBAEA,OAAA,KACA,QAAA,EACA,OAAA,KACA,UAAA,KC7CE,MAAA,QD+CF,WAAA,UACA,cAAA,WACA,QAAA,IACA,QAAA,EC5CE,oDACE,MAAA,QD+CN,sBACE,MAAA,MACA,QAAA,IAAA,KAAA,IAAA,KAGE,aAAA,KACA,WAAA,KAGF,MAAA,KC/DE,WAAA,6DAAA,WAAA,0DDiEF,mBAAA,IAAA,IAAA,KAAA,EAAA,qBAAA,WAAA,IAAA,IAAA,KAAA,EAAA,qBACA,OAAA,KACA,cAAA,IElEF,mBAAA,IAAA,IAAA,cAAA,IAAA,IAAA,WAAA,IAAA,IDKI,+CACE,WAAA,4DAAA,WAAA,yDCJN,4BACE,kBAAA,WAAA,cAAA,WAAA,UAAA,WACA,QAAA,GAGF,6BACE,kBAAA,UAAA,cAAA,UAAA,UAAA,UACA,QAAA,EF8DF,6BACE,QAAA,EAAA,IAAA,EAAA,IACA,WAAA,IACA,OAAA,KACA,OAAA,IACA,cAAA,EE5EF,mBAAA,IAAA,IAAA,cAAA,IAAA,IAAA,WAAA,IAAA,IAEA,mCACE,kBAAA,WAAA,cAAA,WAAA,UAAA,WACA,QAAA,GAGF,oCACE,kBAAA,UAAA,cAAA,UAAA,UAAA,UACA,QAAA,EFsEA,kCACE,KAAA,QAGF,iCACE,MAAA,KAQN,mBAEE,SAAA,SAEA,YAAA,IACA,QAAA,EAIF,UAEE,SAAA,SACA,MAAA,MACA,OAAA,MACA,IAAA,EACA,KAAA,EACA,QAAA,EAGF,YACE,MAAA,KAGF,aACE,MAAA","file":"../litewebchat_input.min.css","sourcesContent":["/*!\n * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)\n * MorFans Lab(c) 2017-2023\n * Licensed under LGPL\n */@charset \"UTF-8\";\n.lite-chatbox {\n height: calc(100% - 150px);\n}\n.lite-chatbox > div:last-child {\n margin-bottom: 20px;\n}\n\n.lite-chatinput {\n width: 100%;\n height: 150px;\n position: relative;\n bottom: 0px;\n background-color: #fff;\n}\n[litewebchat-theme=dark] .lite-chatinput {\n background-color: #202223;\n}\n.lite-chatinput img {\n max-width: 150px;\n max-height: 150px;\n object-fit: contain;\n}\n.lite-chatinput .boundary {\n cursor: s-resize;\n margin: 0 auto;\n border-width: 1px 0px 0px 0px;\n border-color: rgba(0, 0, 0, 0.2);\n height: 5px;\n background: #fff;\n}\n[litewebchat-theme=dark] .lite-chatinput .boundary {\n background: #202223;\n}\n.lite-chatinput > .chatinput {\n position: relative;\n overflow-y: scroll;\n /* margin: 0px 3px 0px 3px; */\n width: calc(100% - 6px);\n margin: auto;\n /* width: 100%; */\n height: calc(100% - 75px);\n /* height: 100%; */\n border: none;\n outline: none;\n resize: none;\n font-size: 18px;\n color: #373737;\n word-break: break-all;\n overflow-wrap: break-word;\n padding: 5px;\n outline: none;\n}\n[litewebchat-theme=dark] .lite-chatinput > .chatinput {\n color: #d4d4d4;\n}\n.lite-chatinput .send {\n float: right;\n padding: 4px 20px 4px 20px;\n margin-right: 12px;\n margin-top: -2px;\n color: white;\n background: linear-gradient(20deg, rgba(63, 143, 225, 0.8) 0%, #44d7c9 100%);\n box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);\n border: none;\n border-radius: 4px;\n transition: all 0.2s;\n}\n[litewebchat-theme=dark] .lite-chatinput .send {\n background: linear-gradient(20deg, rgba(25, 91, 159, 0.8) 0px, rgb(33, 154, 146) 100%);\n}\n.lite-chatinput .send:hover {\n transform: scale(1.1);\n opacity: 0.7;\n}\n.lite-chatinput .send:active {\n transform: scale(0.9);\n opacity: 1;\n}\n.lite-chatinput .tool-button {\n padding: 0px 3px 0px 3px;\n background: none;\n border: none;\n margin: 5px;\n margin-bottom: 0px;\n transition: all 0.2s;\n}\n.lite-chatinput .tool-button:hover {\n transform: scale(1.1);\n opacity: 0.7;\n}\n.lite-chatinput .tool-button:active {\n transform: scale(0.9);\n opacity: 1;\n}\n.lite-chatinput .tool-button path {\n fill: rgb(139, 135, 153);\n}\n.lite-chatinput .tool-button svg {\n width: 18px;\n}\n\n/* 由功能按钮唤起的功能页面 */\n.lite-chatbox-tool {\n /* border: 5px solid red; */\n position: absolute;\n /* bottom: 20px; */\n margin-left: 3px;\n z-index: 3;\n}\n\n/* 部分功能页面需要用到的遮罩 */\n#toolMusk {\n /* border: 3px solid red; */\n position: absolute;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.float-left {\n float: left;\n}\n\n.float-right {\n float: right;\n}","@import './mixin/theme';\n@import './mixin/helper';\n\n@import './variable';\n\n// 聊天区域\n.lite-chatbox {\n height: calc(100% - 150px);\n\n //.lite-chatbox内的最后一条消息的margin-bottom设置为20px,离下面远一点\n >div:last-child {\n margin-bottom: 20px;\n }\n}\n\n// 输入框\n.lite-chatinput {\n width: 100%;\n height: 150px;\n position: relative;\n bottom: 0px;\n @include theme('background-color', $chat-bg-color-input);\n\n // 缩小输入框内的图片,方便编辑\n img {\n max-width: 150px;\n max-height: 150px;\n object-fit: contain;\n }\n\n // 聊天区域和输入框的分界线\n .boundary {\n cursor: s-resize;\n margin: 0 auto;\n border-width: 1px 0px 0px 0px;\n border-color: rgba(0, 0, 0, 0.2);\n height: 5px;\n @include theme('background', $chat-bg-color-input);\n }\n\n // 输入框\n >.chatinput {\n position: relative;\n overflow-y: scroll;\n /* margin: 0px 3px 0px 3px; */\n width: calc(100% - 6px);\n margin: auto;\n /* width: 100%; */\n height: calc(100% - 75px);\n /* height: 100%; */\n border: none;\n outline: none;\n resize: none;\n font-size: 18px;\n @include theme('color', $chat-color-input);\n word-break: break-all;\n overflow-wrap: break-word;\n padding: 5px;\n outline: none;\n }\n\n // 发送按钮\n .send {\n float: right;\n padding: 4px 20px 4px 20px;\n\n margin: {\n right: 12px;\n top: -2px;\n }\n\n color: white;\n @include theme('background', $chat-message-bg-color-me);\n box-shadow: 5px 5px 15px 0 rgba(102, 102, 102, 0.1);\n border: none;\n border-radius: 4px;\n @include push-animate;\n }\n\n // 输入框上方的输入表情等功能按钮\n .tool-button {\n padding: 0px 3px 0px 3px;\n background: none;\n border: none;\n margin: 5px;\n margin-bottom: 0px;\n @include push-animate;\n\n path {\n fill: rgb(139, 135, 153);\n }\n\n svg {\n width: 18px;\n }\n }\n\n // end of.tool-button\n}\n\n/* 由功能按钮唤起的功能页面 */\n.lite-chatbox-tool {\n /* border: 5px solid red; */\n position: absolute;\n /* bottom: 20px; */\n margin-left: 3px;\n z-index: 3;\n}\n\n/* 部分功能页面需要用到的遮罩 */\n#toolMusk {\n /* border: 3px solid red; */\n position: absolute;\n width: 100vw;\n height: 100vh;\n top: 0;\n left: 0;\n z-index: 2;\n}\n\n.float-left {\n float: left;\n}\n\n.float-right {\n float: right;\n}\n","@mixin theme($key, $map_key) {\n $theme_colors: light,\n dark;\n\n @each $theme in $theme_colors {\n\n @if $theme ==light {\n // default light\n #{$key}: map-get($map: $map_key, $key: $theme);\n }\n\n @else {\n\n // 生成其他\n [litewebchat-theme=#{$theme}] & {\n #{$key}: map-get($map: $map_key, $key: $theme);\n }\n }\n }\n}\n","@use \"sass:selector\";\n\n@mixin unify-parent($child) {\n @at-root #{selector.unify(&, $child)} {\n @content;\n }\n}\n\n@mixin push-animate($time: .2, $scaleHover: 1.1, $scalePush: 0.9) {\n transition: all #{$time}s; // 让按下有呼吸感\n\n &:hover {\n transform: scale($scaleHover);\n opacity: .7;\n }\n\n &:active {\n transform: scale($scalePush);\n opacity: 1;\n }\n}\n"]}
--------------------------------------------------------------------------------
/src/main/resources/static/img/A.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/379685397/ChatWeb/65142fa199eaaaa6929b69b26fa60e3e61cec860/src/main/resources/static/img/A.jpg
--------------------------------------------------------------------------------
/src/main/resources/static/img/B.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/379685397/ChatWeb/65142fa199eaaaa6929b69b26fa60e3e61cec860/src/main/resources/static/img/B.jpg
--------------------------------------------------------------------------------
/src/main/resources/static/js/jquery.autocomplete.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Ajax Autocomplete for jQuery, version 1.4.10
3 | * (c) 2017 Tomas Kirda
4 | *
5 | * Ajax Autocomplete for jQuery is freely distributable under the terms of an MIT-style license.
6 | * For details, see the web site: https://github.com/devbridge/jQuery-Autocomplete
7 | */
8 | !function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("object"==typeof exports&&"function"==typeof require?require("jquery"):jQuery)}(function(a){"use strict";function b(c,d){var e=this;e.element=c,e.el=a(c),e.suggestions=[],e.badQueries=[],e.selectedIndex=-1,e.currentValue=e.element.value,e.timeoutId=null,e.cachedResponse={},e.onChangeTimeout=null,e.onChange=null,e.isLocal=!1,e.suggestionsContainer=null,e.noSuggestionsContainer=null,e.options=a.extend(!0,{},b.defaults,d),e.classes={selected:"autocomplete-selected",suggestion:"autocomplete-suggestion"},e.hint=null,e.hintValue="",e.selection=null,e.initialize(),e.setOptions(d)}function c(a,b,c){return a.value.toLowerCase().indexOf(c)!==-1}function d(b){return"string"==typeof b?a.parseJSON(b):b}function e(a,b){if(!b)return a.value;var c="("+g.escapeRegExChars(b)+")";return a.value.replace(new RegExp(c,"gi"),"$1 ").replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/<(\/?strong)>/g,"<$1>")}function f(a,b){return''+b+"
"}var g=function(){return{escapeRegExChars:function(a){return a.replace(/[|\\{}()[\]^$+*?.]/g,"\\$&")},createNode:function(a){var b=document.createElement("div");return b.className=a,b.style.position="absolute",b.style.display="none",b}}}(),h={ESC:27,TAB:9,RETURN:13,LEFT:37,UP:38,RIGHT:39,DOWN:40},i=a.noop;b.utils=g,a.Autocomplete=b,b.defaults={ajaxSettings:{},autoSelectFirst:!1,appendTo:"body",serviceUrl:null,lookup:null,onSelect:null,width:"auto",minChars:1,maxHeight:300,deferRequestBy:0,params:{},formatResult:e,formatGroup:f,delimiter:null,zIndex:9999,type:"GET",noCache:!1,onSearchStart:i,onSearchComplete:i,onSearchError:i,preserveInput:!1,containerClass:"autocomplete-suggestions",tabDisabled:!1,dataType:"text",currentRequest:null,triggerSelectOnValidInput:!0,preventBadQueries:!0,lookupFilter:c,paramName:"query",transformResult:d,showNoSuggestionNotice:!1,noSuggestionNotice:"No results",orientation:"bottom",forceFixPosition:!1},b.prototype={initialize:function(){var c,d=this,e="."+d.classes.suggestion,f=d.classes.selected,g=d.options;d.element.setAttribute("autocomplete","off"),d.noSuggestionsContainer=a('
').html(this.options.noSuggestionNotice).get(0),d.suggestionsContainer=b.utils.createNode(g.containerClass),c=a(d.suggestionsContainer),c.appendTo(g.appendTo||"body"),"auto"!==g.width&&c.css("width",g.width),c.on("mouseover.autocomplete",e,function(){d.activate(a(this).data("index"))}),c.on("mouseout.autocomplete",function(){d.selectedIndex=-1,c.children("."+f).removeClass(f)}),c.on("click.autocomplete",e,function(){d.select(a(this).data("index"))}),c.on("click.autocomplete",function(){clearTimeout(d.blurTimeoutId)}),d.fixPositionCapture=function(){d.visible&&d.fixPosition()},a(window).on("resize.autocomplete",d.fixPositionCapture),d.el.on("keydown.autocomplete",function(a){d.onKeyPress(a)}),d.el.on("keyup.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("blur.autocomplete",function(){d.onBlur()}),d.el.on("focus.autocomplete",function(){d.onFocus()}),d.el.on("change.autocomplete",function(a){d.onKeyUp(a)}),d.el.on("input.autocomplete",function(a){d.onKeyUp(a)})},onFocus:function(){var a=this;a.fixPosition(),a.el.val().length>=a.options.minChars&&a.onValueChange()},onBlur:function(){var b=this,c=b.options,d=b.el.val(),e=b.getQuery(d);b.blurTimeoutId=setTimeout(function(){b.hide(),b.selection&&b.currentValue!==e&&(c.onInvalidateSelection||a.noop).call(b.element)},200)},abortAjax:function(){var a=this;a.currentRequest&&(a.currentRequest.abort(),a.currentRequest=null)},setOptions:function(b){var c=this,d=a.extend({},c.options,b);c.isLocal=Array.isArray(d.lookup),c.isLocal&&(d.lookup=c.verifySuggestionsFormat(d.lookup)),d.orientation=c.validateOrientation(d.orientation,"bottom"),a(c.suggestionsContainer).css({"max-height":d.maxHeight+"px",width:d.width+"px","z-index":d.zIndex}),this.options=d},clearCache:function(){this.cachedResponse={},this.badQueries=[]},clear:function(){this.clearCache(),this.currentValue="",this.suggestions=[]},disable:function(){var a=this;a.disabled=!0,clearTimeout(a.onChangeTimeout),a.abortAjax()},enable:function(){this.disabled=!1},fixPosition:function(){var b=this,c=a(b.suggestionsContainer),d=c.parent().get(0);if(d===document.body||b.options.forceFixPosition){var e=b.options.orientation,f=c.outerHeight(),g=b.el.outerHeight(),h=b.el.offset(),i={top:h.top,left:h.left};if("auto"===e){var j=a(window).height(),k=a(window).scrollTop(),l=-k+h.top-f,m=k+j-(h.top+g+f);e=Math.max(l,m)===l?"top":"bottom"}if("top"===e?i.top+=-f:i.top+=g,d!==document.body){var n,o=c.css("opacity");b.visible||c.css("opacity",0).show(),n=c.offsetParent().offset(),i.top-=n.top,i.top+=d.scrollTop,i.left-=n.left,b.visible||c.css("opacity",o).hide()}"auto"===b.options.width&&(i.width=b.el.outerWidth()+"px"),c.css(i)}},isCursorAtEnd:function(){var a,b=this,c=b.el.val().length,d=b.element.selectionStart;return"number"==typeof d?d===c:!document.selection||(a=document.selection.createRange(),a.moveStart("character",-c),c===a.text.length)},onKeyPress:function(a){var b=this;if(!b.disabled&&!b.visible&&a.which===h.DOWN&&b.currentValue)return void b.suggest();if(!b.disabled&&b.visible){switch(a.which){case h.ESC:b.el.val(b.currentValue),b.hide();break;case h.RIGHT:if(b.hint&&b.options.onHint&&b.isCursorAtEnd()){b.selectHint();break}return;case h.TAB:if(b.hint&&b.options.onHint)return void b.selectHint();if(b.selectedIndex===-1)return void b.hide();if(b.select(b.selectedIndex),b.options.tabDisabled===!1)return;break;case h.RETURN:if(b.selectedIndex===-1)return void b.hide();b.select(b.selectedIndex);break;case h.UP:b.moveUp();break;case h.DOWN:b.moveDown();break;default:return}a.stopImmediatePropagation(),a.preventDefault()}},onKeyUp:function(a){var b=this;if(!b.disabled){switch(a.which){case h.UP:case h.DOWN:return}clearTimeout(b.onChangeTimeout),b.currentValue!==b.el.val()&&(b.findBestHint(),b.options.deferRequestBy>0?b.onChangeTimeout=setTimeout(function(){b.onValueChange()},b.options.deferRequestBy):b.onValueChange())}},onValueChange:function(){if(this.ignoreValueChange)return void(this.ignoreValueChange=!1);var b=this,c=b.options,d=b.el.val(),e=b.getQuery(d);return b.selection&&b.currentValue!==e&&(b.selection=null,(c.onInvalidateSelection||a.noop).call(b.element)),clearTimeout(b.onChangeTimeout),b.currentValue=d,b.selectedIndex=-1,c.triggerSelectOnValidInput&&b.isExactMatch(e)?void b.select(0):void(e.lengthh&&(c.suggestions=c.suggestions.slice(0,h)),c},getSuggestions:function(b){var c,d,e,f,g=this,h=g.options,i=h.serviceUrl;if(h.params[h.paramName]=b,h.onSearchStart.call(g.element,h.params)!==!1){if(d=h.ignoreParams?null:h.params,a.isFunction(h.lookup))return void h.lookup(b,function(a){g.suggestions=a.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,a.suggestions)});g.isLocal?c=g.getSuggestionsLocal(b):(a.isFunction(i)&&(i=i.call(g.element,b)),e=i+"?"+a.param(d||{}),c=g.cachedResponse[e]),c&&Array.isArray(c.suggestions)?(g.suggestions=c.suggestions,g.suggest(),h.onSearchComplete.call(g.element,b,c.suggestions)):g.isBadQuery(b)?h.onSearchComplete.call(g.element,b,[]):(g.abortAjax(),f={url:i,data:d,type:h.type,dataType:h.dataType},a.extend(f,h.ajaxSettings),g.currentRequest=a.ajax(f).done(function(a){var c;g.currentRequest=null,c=h.transformResult(a,b),g.processResponse(c,b,e),h.onSearchComplete.call(g.element,b,c.suggestions)}).fail(function(a,c,d){h.onSearchError.call(g.element,b,a,c,d)}))}},isBadQuery:function(a){if(!this.options.preventBadQueries)return!1;for(var b=this.badQueries,c=b.length;c--;)if(0===a.indexOf(b[c]))return!0;return!1},hide:function(){var b=this,c=a(b.suggestionsContainer);a.isFunction(b.options.onHide)&&b.visible&&b.options.onHide.call(b.element,c),b.visible=!1,b.selectedIndex=-1,clearTimeout(b.onChangeTimeout),a(b.suggestionsContainer).hide(),b.signalHint(null)},suggest:function(){if(!this.suggestions.length)return void(this.options.showNoSuggestionNotice?this.noSuggestions():this.hide());var b,c=this,d=c.options,e=d.groupBy,f=d.formatResult,g=c.getQuery(c.currentValue),h=c.classes.suggestion,i=c.classes.selected,j=a(c.suggestionsContainer),k=a(c.noSuggestionsContainer),l=d.beforeRender,m="",n=function(a,c){var f=a.data[e];return b===f?"":(b=f,d.formatGroup(a,b))};return d.triggerSelectOnValidInput&&c.isExactMatch(g)?void c.select(0):(a.each(c.suggestions,function(a,b){e&&(m+=n(b,g,a)),m+=''+f(b,g,a)+"
"}),this.adjustContainerWidth(),k.detach(),j.html(m),a.isFunction(l)&&l.call(c.element,j,c.suggestions),c.fixPosition(),j.show(),d.autoSelectFirst&&(c.selectedIndex=0,j.scrollTop(0),j.children("."+h).first().addClass(i)),c.visible=!0,void c.findBestHint())},noSuggestions:function(){var b=this,c=b.options.beforeRender,d=a(b.suggestionsContainer),e=a(b.noSuggestionsContainer);this.adjustContainerWidth(),e.detach(),d.empty(),d.append(e),a.isFunction(c)&&c.call(b.element,d,b.suggestions),b.fixPosition(),d.show(),b.visible=!0},adjustContainerWidth:function(){var b,c=this,d=c.options,e=a(c.suggestionsContainer);"auto"===d.width?(b=c.el.outerWidth(),e.css("width",b>0?b:300)):"flex"===d.width&&e.css("width","")},findBestHint:function(){var b=this,c=b.el.val().toLowerCase(),d=null;c&&(a.each(b.suggestions,function(a,b){var e=0===b.value.toLowerCase().indexOf(c);return e&&(d=b),!e}),b.signalHint(d))},signalHint:function(b){var c="",d=this;b&&(c=d.currentValue+b.value.substr(d.currentValue.length)),d.hintValue!==c&&(d.hintValue=c,d.hint=b,(this.options.onHint||a.noop)(c))},verifySuggestionsFormat:function(b){return b.length&&"string"==typeof b[0]?a.map(b,function(a){return{value:a,data:null}}):b},validateOrientation:function(b,c){return b=a.trim(b||"").toLowerCase(),a.inArray(b,["auto","bottom","top"])===-1&&(b=c),b},processResponse:function(a,b,c){var d=this,e=d.options;a.suggestions=d.verifySuggestionsFormat(a.suggestions),e.noCache||(d.cachedResponse[c]=a,e.preventBadQueries&&!a.suggestions.length&&d.badQueries.push(b)),b===d.getQuery(d.currentValue)&&(d.suggestions=a.suggestions,d.suggest())},activate:function(b){var c,d=this,e=d.classes.selected,f=a(d.suggestionsContainer),g=f.find("."+d.classes.suggestion);return f.find("."+e).removeClass(e),d.selectedIndex=b,d.selectedIndex!==-1&&g.length>d.selectedIndex?(c=g.get(d.selectedIndex),a(c).addClass(e),c):null},selectHint:function(){var b=this,c=a.inArray(b.hint,b.suggestions);b.select(c)},select:function(a){var b=this;b.hide(),b.onSelect(a)},moveUp:function(){var b=this;if(b.selectedIndex!==-1)return 0===b.selectedIndex?(a(b.suggestionsContainer).children("."+b.classes.suggestion).first().removeClass(b.classes.selected),b.selectedIndex=-1,b.ignoreValueChange=!1,b.el.val(b.currentValue),void b.findBestHint()):void b.adjustScroll(b.selectedIndex-1)},moveDown:function(){var a=this;a.selectedIndex!==a.suggestions.length-1&&a.adjustScroll(a.selectedIndex+1)},adjustScroll:function(b){var c=this,d=c.activate(b);if(d){var e,f,g,h=a(d).outerHeight();e=d.offsetTop,f=a(c.suggestionsContainer).scrollTop(),g=f+c.options.maxHeight-h,eg&&a(c.suggestionsContainer).scrollTop(e-c.options.maxHeight+h),c.options.preserveInput||(c.ignoreValueChange=!0,c.el.val(c.getValue(c.suggestions[b].value))),c.signalHint(null)}},onSelect:function(b){var c=this,d=c.options.onSelect,e=c.suggestions[b];c.currentValue=c.getValue(e.value),c.currentValue===c.el.val()||c.options.preserveInput||c.el.val(c.currentValue),c.signalHint(null),c.suggestions=[],c.selection=e,a.isFunction(d)&&d.call(c.element,e)},getValue:function(a){var b,c,d=this,e=d.options.delimiter;return e?(b=d.currentValue,c=b.split(e),1===c.length?a:b.substr(0,b.length-c[c.length-1].length)+a):a},dispose:function(){var b=this;b.el.off(".autocomplete").removeData("autocomplete"),a(window).off("resize.autocomplete",b.fixPositionCapture),a(b.suggestionsContainer).remove()}},a.fn.devbridgeAutocomplete=function(c,d){var e="autocomplete";return arguments.length?this.each(function(){var f=a(this),g=f.data(e);"string"==typeof c?g&&"function"==typeof g[c]&&g[c](d):(g&&g.dispose&&g.dispose(),g=new b(this,c),f.data(e,g))}):this.first().data(e)},a.fn.autocomplete||(a.fn.autocomplete=a.fn.devbridgeAutocomplete)});
--------------------------------------------------------------------------------
/src/main/resources/static/js/jquery.validate.min.js:
--------------------------------------------------------------------------------
1 | /*! jQuery Validation Plugin - v1.19.1 - 6/15/2019
2 | * https://jqueryvalidation.org/
3 | * Copyright (c) 2019 Jörn Zaefferer; Licensed MIT */
4 | !function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery")):a(jQuery)}(function(a){a.extend(a.fn,{validate:function(b){if(!this.length)return void(b&&b.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."));var c=a.data(this[0],"validator");return c?c:(this.attr("novalidate","novalidate"),c=new a.validator(b,this[0]),a.data(this[0],"validator",c),c.settings.onsubmit&&(this.on("click.validate",":submit",function(b){c.submitButton=b.currentTarget,a(this).hasClass("cancel")&&(c.cancelSubmit=!0),void 0!==a(this).attr("formnovalidate")&&(c.cancelSubmit=!0)}),this.on("submit.validate",function(b){function d(){var d,e;return c.submitButton&&(c.settings.submitHandler||c.formSubmitted)&&(d=a(" ").attr("name",c.submitButton.name).val(a(c.submitButton).val()).appendTo(c.currentForm)),!(c.settings.submitHandler&&!c.settings.debug)||(e=c.settings.submitHandler.call(c,c.currentForm,b),d&&d.remove(),void 0!==e&&e)}return c.settings.debug&&b.preventDefault(),c.cancelSubmit?(c.cancelSubmit=!1,d()):c.form()?c.pendingRequest?(c.formSubmitted=!0,!1):d():(c.focusInvalid(),!1)})),c)},valid:function(){var b,c,d;return a(this[0]).is("form")?b=this.validate().form():(d=[],b=!0,c=a(this[0].form).validate(),this.each(function(){b=c.element(this)&&b,b||(d=d.concat(c.errorList))}),c.errorList=d),b},rules:function(b,c){var d,e,f,g,h,i,j=this[0],k="undefined"!=typeof this.attr("contenteditable")&&"false"!==this.attr("contenteditable");if(null!=j&&(!j.form&&k&&(j.form=this.closest("form")[0],j.name=this.attr("name")),null!=j.form)){if(b)switch(d=a.data(j.form,"validator").settings,e=d.rules,f=a.validator.staticRules(j),b){case"add":a.extend(f,a.validator.normalizeRule(c)),delete f.messages,e[j.name]=f,c.messages&&(d.messages[j.name]=a.extend(d.messages[j.name],c.messages));break;case"remove":return c?(i={},a.each(c.split(/\s/),function(a,b){i[b]=f[b],delete f[b]}),i):(delete e[j.name],f)}return g=a.validator.normalizeRules(a.extend({},a.validator.classRules(j),a.validator.attributeRules(j),a.validator.dataRules(j),a.validator.staticRules(j)),j),g.required&&(h=g.required,delete g.required,g=a.extend({required:h},g)),g.remote&&(h=g.remote,delete g.remote,g=a.extend(g,{remote:h})),g}}}),a.extend(a.expr.pseudos||a.expr[":"],{blank:function(b){return!a.trim(""+a(b).val())},filled:function(b){var c=a(b).val();return null!==c&&!!a.trim(""+c)},unchecked:function(b){return!a(b).prop("checked")}}),a.validator=function(b,c){this.settings=a.extend(!0,{},a.validator.defaults,b),this.currentForm=c,this.init()},a.validator.format=function(b,c){return 1===arguments.length?function(){var c=a.makeArray(arguments);return c.unshift(b),a.validator.format.apply(this,c)}:void 0===c?b:(arguments.length>2&&c.constructor!==Array&&(c=a.makeArray(arguments).slice(1)),c.constructor!==Array&&(c=[c]),a.each(c,function(a,c){b=b.replace(new RegExp("\\{"+a+"\\}","g"),function(){return c})}),b)},a.extend(a.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",pendingClass:"pending",validClass:"valid",errorElement:"label",focusCleanup:!1,focusInvalid:!0,errorContainer:a([]),errorLabelContainer:a([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(a){this.lastActive=a,this.settings.focusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,a,this.settings.errorClass,this.settings.validClass),this.hideThese(this.errorsFor(a)))},onfocusout:function(a){this.checkable(a)||!(a.name in this.submitted)&&this.optional(a)||this.element(a)},onkeyup:function(b,c){var d=[16,17,18,20,35,36,37,38,39,40,45,144,225];9===c.which&&""===this.elementValue(b)||a.inArray(c.keyCode,d)!==-1||(b.name in this.submitted||b.name in this.invalid)&&this.element(b)},onclick:function(a){a.name in this.submitted?this.element(a):a.parentNode.name in this.submitted&&this.element(a.parentNode)},highlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).addClass(c).removeClass(d):a(b).addClass(c).removeClass(d)},unhighlight:function(b,c,d){"radio"===b.type?this.findByName(b.name).removeClass(c).addClass(d):a(b).removeClass(c).addClass(d)}},setDefaults:function(b){a.extend(a.validator.defaults,b)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",equalTo:"Please enter the same value again.",maxlength:a.validator.format("Please enter no more than {0} characters."),minlength:a.validator.format("Please enter at least {0} characters."),rangelength:a.validator.format("Please enter a value between {0} and {1} characters long."),range:a.validator.format("Please enter a value between {0} and {1}."),max:a.validator.format("Please enter a value less than or equal to {0}."),min:a.validator.format("Please enter a value greater than or equal to {0}."),step:a.validator.format("Please enter a multiple of {0}.")},autoCreateRanges:!1,prototype:{init:function(){function b(b){var c="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");if(!this.form&&c&&(this.form=a(this).closest("form")[0],this.name=a(this).attr("name")),d===this.form){var e=a.data(this.form,"validator"),f="on"+b.type.replace(/^validate/,""),g=e.settings;g[f]&&!a(this).is(g.ignore)&&g[f].call(e,this,b)}}this.labelContainer=a(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||a(this.currentForm),this.containers=a(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var c,d=this.currentForm,e=this.groups={};a.each(this.settings.groups,function(b,c){"string"==typeof c&&(c=c.split(/\s/)),a.each(c,function(a,c){e[c]=b})}),c=this.settings.rules,a.each(c,function(b,d){c[b]=a.validator.normalizeRule(d)}),a(this.currentForm).on("focusin.validate focusout.validate keyup.validate",":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'], [type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'], [type='radio'], [type='checkbox'], [contenteditable], [type='button']",b).on("click.validate","select, option, [type='radio'], [type='checkbox']",b),this.settings.invalidHandler&&a(this.currentForm).on("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),a.extend(this.submitted,this.errorMap),this.invalid=a.extend({},this.errorMap),this.valid()||a(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var a=0,b=this.currentElements=this.elements();b[a];a++)this.check(b[a]);return this.valid()},element:function(b){var c,d,e=this.clean(b),f=this.validationTargetFor(e),g=this,h=!0;return void 0===f?delete this.invalid[e.name]:(this.prepareElement(f),this.currentElements=a(f),d=this.groups[f.name],d&&a.each(this.groups,function(a,b){b===d&&a!==f.name&&(e=g.validationTargetFor(g.clean(g.findByName(a))),e&&e.name in g.invalid&&(g.currentElements.push(e),h=g.check(e)&&h))}),c=this.check(f)!==!1,h=h&&c,c?this.invalid[f.name]=!1:this.invalid[f.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),a(b).attr("aria-invalid",!c)),h},showErrors:function(b){if(b){var c=this;a.extend(this.errorMap,b),this.errorList=a.map(this.errorMap,function(a,b){return{message:a,element:c.findByName(b)[0]}}),this.successList=a.grep(this.successList,function(a){return!(a.name in b)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){a.fn.resetForm&&a(this.currentForm).resetForm(),this.invalid={},this.submitted={},this.prepareForm(),this.hideErrors();var b=this.elements().removeData("previousValue").removeAttr("aria-invalid");this.resetElements(b)},resetElements:function(a){var b;if(this.settings.unhighlight)for(b=0;a[b];b++)this.settings.unhighlight.call(this,a[b],this.settings.errorClass,""),this.findByName(a[b].name).removeClass(this.settings.validClass);else a.removeClass(this.settings.errorClass).removeClass(this.settings.validClass)},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(a){var b,c=0;for(b in a)void 0!==a[b]&&null!==a[b]&&a[b]!==!1&&c++;return c},hideErrors:function(){this.hideThese(this.toHide)},hideThese:function(a){a.not(this.containers).text(""),this.addWrapper(a).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{a(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").trigger("focus").trigger("focusin")}catch(b){}},findLastActive:function(){var b=this.lastActive;return b&&1===a.grep(this.errorList,function(a){return a.element.name===b.name}).length&&b},elements:function(){var b=this,c={};return a(this.currentForm).find("input, select, textarea, [contenteditable]").not(":submit, :reset, :image, :disabled").not(this.settings.ignore).filter(function(){var d=this.name||a(this).attr("name"),e="undefined"!=typeof a(this).attr("contenteditable")&&"false"!==a(this).attr("contenteditable");return!d&&b.settings.debug&&window.console&&console.error("%o has no name assigned",this),e&&(this.form=a(this).closest("form")[0],this.name=d),this.form===b.currentForm&&(!(d in c||!b.objectLength(a(this).rules()))&&(c[d]=!0,!0))})},clean:function(b){return a(b)[0]},errors:function(){var b=this.settings.errorClass.split(" ").join(".");return a(this.settings.errorElement+"."+b,this.errorContext)},resetInternals:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=a([]),this.toHide=a([])},reset:function(){this.resetInternals(),this.currentElements=a([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(a){this.reset(),this.toHide=this.errorsFor(a)},elementValue:function(b){var c,d,e=a(b),f=b.type,g="undefined"!=typeof e.attr("contenteditable")&&"false"!==e.attr("contenteditable");return"radio"===f||"checkbox"===f?this.findByName(b.name).filter(":checked").val():"number"===f&&"undefined"!=typeof b.validity?b.validity.badInput?"NaN":e.val():(c=g?e.text():e.val(),"file"===f?"C:\\fakepath\\"===c.substr(0,12)?c.substr(12):(d=c.lastIndexOf("/"),d>=0?c.substr(d+1):(d=c.lastIndexOf("\\"),d>=0?c.substr(d+1):c)):"string"==typeof c?c.replace(/\r/g,""):c)},check:function(b){b=this.validationTargetFor(this.clean(b));var c,d,e,f,g=a(b).rules(),h=a.map(g,function(a,b){return b}).length,i=!1,j=this.elementValue(b);"function"==typeof g.normalizer?f=g.normalizer:"function"==typeof this.settings.normalizer&&(f=this.settings.normalizer),f&&(j=f.call(b,j),delete g.normalizer);for(d in g){e={method:d,parameters:g[d]};try{if(c=a.validator.methods[d].call(this,j,b,e.parameters),"dependency-mismatch"===c&&1===h){i=!0;continue}if(i=!1,"pending"===c)return void(this.toHide=this.toHide.not(this.errorsFor(b)));if(!c)return this.formatAndAdd(b,e),!1}catch(k){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+b.id+", check the '"+e.method+"' method.",k),k instanceof TypeError&&(k.message+=". Exception occurred when checking element "+b.id+", check the '"+e.method+"' method."),k}}if(!i)return this.objectLength(g)&&this.successList.push(b),!0},customDataMessage:function(b,c){return a(b).data("msg"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase())||a(b).data("msg")},customMessage:function(a,b){var c=this.settings.messages[a];return c&&(c.constructor===String?c:c[b])},findDefined:function(){for(var a=0;aWarning: No message defined for "+b.name+""),e=/\$?\{(\d+)\}/g;return"function"==typeof d?d=d.call(this,c.parameters,b):e.test(d)&&(d=a.validator.format(d.replace(e,"{$1}"),c.parameters)),d},formatAndAdd:function(a,b){var c=this.defaultMessage(a,b);this.errorList.push({message:c,element:a,method:b.method}),this.errorMap[a.name]=c,this.submitted[a.name]=c},addWrapper:function(a){return this.settings.wrapper&&(a=a.add(a.parent(this.settings.wrapper))),a},defaultShowErrors:function(){var a,b,c;for(a=0;this.errorList[a];a++)c=this.errorList[a],this.settings.highlight&&this.settings.highlight.call(this,c.element,this.settings.errorClass,this.settings.validClass),this.showLabel(c.element,c.message);if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(a=0;this.successList[a];a++)this.showLabel(this.successList[a]);if(this.settings.unhighlight)for(a=0,b=this.validElements();b[a];a++)this.settings.unhighlight.call(this,b[a],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return a(this.errorList).map(function(){return this.element})},showLabel:function(b,c){var d,e,f,g,h=this.errorsFor(b),i=this.idOrName(b),j=a(b).attr("aria-describedby");h.length?(h.removeClass(this.settings.validClass).addClass(this.settings.errorClass),h.html(c)):(h=a("<"+this.settings.errorElement+">").attr("id",i+"-error").addClass(this.settings.errorClass).html(c||""),d=h,this.settings.wrapper&&(d=h.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.length?this.labelContainer.append(d):this.settings.errorPlacement?this.settings.errorPlacement.call(this,d,a(b)):d.insertAfter(b),h.is("label")?h.attr("for",i):0===h.parents("label[for='"+this.escapeCssMeta(i)+"']").length&&(f=h.attr("id"),j?j.match(new RegExp("\\b"+this.escapeCssMeta(f)+"\\b"))||(j+=" "+f):j=f,a(b).attr("aria-describedby",j),e=this.groups[b.name],e&&(g=this,a.each(g.groups,function(b,c){c===e&&a("[name='"+g.escapeCssMeta(b)+"']",g.currentForm).attr("aria-describedby",h.attr("id"))})))),!c&&this.settings.success&&(h.text(""),"string"==typeof this.settings.success?h.addClass(this.settings.success):this.settings.success(h,b)),this.toShow=this.toShow.add(h)},errorsFor:function(b){var c=this.escapeCssMeta(this.idOrName(b)),d=a(b).attr("aria-describedby"),e="label[for='"+c+"'], label[for='"+c+"'] *";return d&&(e=e+", #"+this.escapeCssMeta(d).replace(/\s+/g,", #")),this.errors().filter(e)},escapeCssMeta:function(a){return a.replace(/([\\!"#$%&'()*+,.\/:;<=>?@\[\]^`{|}~])/g,"\\$1")},idOrName:function(a){return this.groups[a.name]||(this.checkable(a)?a.name:a.id||a.name)},validationTargetFor:function(b){return this.checkable(b)&&(b=this.findByName(b.name)),a(b).not(this.settings.ignore)[0]},checkable:function(a){return/radio|checkbox/i.test(a.type)},findByName:function(b){return a(this.currentForm).find("[name='"+this.escapeCssMeta(b)+"']")},getLength:function(b,c){switch(c.nodeName.toLowerCase()){case"select":return a("option:selected",c).length;case"input":if(this.checkable(c))return this.findByName(c.name).filter(":checked").length}return b.length},depend:function(a,b){return!this.dependTypes[typeof a]||this.dependTypes[typeof a](a,b)},dependTypes:{"boolean":function(a){return a},string:function(b,c){return!!a(b,c.form).length},"function":function(a,b){return a(b)}},optional:function(b){var c=this.elementValue(b);return!a.validator.methods.required.call(this,c,b)&&"dependency-mismatch"},startRequest:function(b){this.pending[b.name]||(this.pendingRequest++,a(b).addClass(this.settings.pendingClass),this.pending[b.name]=!0)},stopRequest:function(b,c){this.pendingRequest--,this.pendingRequest<0&&(this.pendingRequest=0),delete this.pending[b.name],a(b).removeClass(this.settings.pendingClass),c&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(a(this.currentForm).submit(),this.submitButton&&a("input:hidden[name='"+this.submitButton.name+"']",this.currentForm).remove(),this.formSubmitted=!1):!c&&0===this.pendingRequest&&this.formSubmitted&&(a(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(b,c){return c="string"==typeof c&&c||"remote",a.data(b,"previousValue")||a.data(b,"previousValue",{old:null,valid:!0,message:this.defaultMessage(b,{method:c})})},destroy:function(){this.resetForm(),a(this.currentForm).off(".validate").removeData("validator").find(".validate-equalTo-blur").off(".validate-equalTo").removeClass("validate-equalTo-blur").find(".validate-lessThan-blur").off(".validate-lessThan").removeClass("validate-lessThan-blur").find(".validate-lessThanEqual-blur").off(".validate-lessThanEqual").removeClass("validate-lessThanEqual-blur").find(".validate-greaterThanEqual-blur").off(".validate-greaterThanEqual").removeClass("validate-greaterThanEqual-blur").find(".validate-greaterThan-blur").off(".validate-greaterThan").removeClass("validate-greaterThan-blur")}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(b,c){b.constructor===String?this.classRuleSettings[b]=c:a.extend(this.classRuleSettings,b)},classRules:function(b){var c={},d=a(b).attr("class");return d&&a.each(d.split(" "),function(){this in a.validator.classRuleSettings&&a.extend(c,a.validator.classRuleSettings[this])}),c},normalizeAttributeRule:function(a,b,c,d){/min|max|step/.test(c)&&(null===b||/number|range|text/.test(b))&&(d=Number(d),isNaN(d)&&(d=void 0)),d||0===d?a[c]=d:b===c&&"range"!==b&&(a[c]=!0)},attributeRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)"required"===c?(d=b.getAttribute(c),""===d&&(d=!0),d=!!d):d=f.attr(c),this.normalizeAttributeRule(e,g,c,d);return e.maxlength&&/-1|2147483647|524288/.test(e.maxlength)&&delete e.maxlength,e},dataRules:function(b){var c,d,e={},f=a(b),g=b.getAttribute("type");for(c in a.validator.methods)d=f.data("rule"+c.charAt(0).toUpperCase()+c.substring(1).toLowerCase()),""===d&&(d=!0),this.normalizeAttributeRule(e,g,c,d);return e},staticRules:function(b){var c={},d=a.data(b.form,"validator");return d.settings.rules&&(c=a.validator.normalizeRule(d.settings.rules[b.name])||{}),c},normalizeRules:function(b,c){return a.each(b,function(d,e){if(e===!1)return void delete b[d];if(e.param||e.depends){var f=!0;switch(typeof e.depends){case"string":f=!!a(e.depends,c.form).length;break;case"function":f=e.depends.call(c,c)}f?b[d]=void 0===e.param||e.param:(a.data(c.form,"validator").resetElements(a(c)),delete b[d])}}),a.each(b,function(d,e){b[d]=a.isFunction(e)&&"normalizer"!==d?e(c):e}),a.each(["minlength","maxlength"],function(){b[this]&&(b[this]=Number(b[this]))}),a.each(["rangelength","range"],function(){var c;b[this]&&(a.isArray(b[this])?b[this]=[Number(b[this][0]),Number(b[this][1])]:"string"==typeof b[this]&&(c=b[this].replace(/[\[\]]/g,"").split(/[\s,]+/),b[this]=[Number(c[0]),Number(c[1])]))}),a.validator.autoCreateRanges&&(null!=b.min&&null!=b.max&&(b.range=[b.min,b.max],delete b.min,delete b.max),null!=b.minlength&&null!=b.maxlength&&(b.rangelength=[b.minlength,b.maxlength],delete b.minlength,delete b.maxlength)),b},normalizeRule:function(b){if("string"==typeof b){var c={};a.each(b.split(/\s/),function(){c[this]=!0}),b=c}return b},addMethod:function(b,c,d){a.validator.methods[b]=c,a.validator.messages[b]=void 0!==d?d:a.validator.messages[b],c.length<3&&a.validator.addClassRules(b,a.validator.normalizeRule(b))},methods:{required:function(b,c,d){if(!this.depend(d,c))return"dependency-mismatch";if("select"===c.nodeName.toLowerCase()){var e=a(c).val();return e&&e.length>0}return this.checkable(c)?this.getLength(b,c)>0:void 0!==b&&null!==b&&b.length>0},email:function(a,b){return this.optional(b)||/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(a)},url:function(a,b){return this.optional(b)||/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[\/?#]\S*)?$/i.test(a)},date:function(){var a=!1;return function(b,c){return a||(a=!0,this.settings.debug&&window.console&&console.warn("The `date` method is deprecated and will be removed in version '2.0.0'.\nPlease don't use it, since it relies on the Date constructor, which\nbehaves very differently across browsers and locales. Use `dateISO`\ninstead or one of the locale specific methods in `localizations/`\nand `additional-methods.js`.")),this.optional(c)||!/Invalid|NaN/.test(new Date(b).toString())}}(),dateISO:function(a,b){return this.optional(b)||/^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(a)},number:function(a,b){return this.optional(b)||/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(a)},digits:function(a,b){return this.optional(b)||/^\d+$/.test(a)},minlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d},maxlength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e<=d},rangelength:function(b,c,d){var e=a.isArray(b)?b.length:this.getLength(b,c);return this.optional(c)||e>=d[0]&&e<=d[1]},min:function(a,b,c){return this.optional(b)||a>=c},max:function(a,b,c){return this.optional(b)||a<=c},range:function(a,b,c){return this.optional(b)||a>=c[0]&&a<=c[1]},step:function(b,c,d){var e,f=a(c).attr("type"),g="Step attribute on input type "+f+" is not supported.",h=["text","number","range"],i=new RegExp("\\b"+f+"\\b"),j=f&&!i.test(h.join()),k=function(a){var b=(""+a).match(/(?:\.(\d+))?$/);return b&&b[1]?b[1].length:0},l=function(a){return Math.round(a*Math.pow(10,e))},m=!0;if(j)throw new Error(g);return e=k(d),(k(b)>e||l(b)%l(d)!==0)&&(m=!1),this.optional(c)||m},equalTo:function(b,c,d){var e=a(d);return this.settings.onfocusout&&e.not(".validate-equalTo-blur").length&&e.addClass("validate-equalTo-blur").on("blur.validate-equalTo",function(){a(c).valid()}),b===e.val()},remote:function(b,c,d,e){if(this.optional(c))return"dependency-mismatch";e="string"==typeof e&&e||"remote";var f,g,h,i=this.previousValue(c,e);return this.settings.messages[c.name]||(this.settings.messages[c.name]={}),i.originalMessage=i.originalMessage||this.settings.messages[c.name][e],this.settings.messages[c.name][e]=i.message,d="string"==typeof d&&{url:d}||d,h=a.param(a.extend({data:b},d.data)),i.old===h?i.valid:(i.old=h,f=this,this.startRequest(c),g={},g[c.name]=b,a.ajax(a.extend(!0,{mode:"abort",port:"validate"+c.name,dataType:"json",data:g,context:f.currentForm,success:function(a){var d,g,h,j=a===!0||"true"===a;f.settings.messages[c.name][e]=i.originalMessage,j?(h=f.formSubmitted,f.resetInternals(),f.toHide=f.errorsFor(c),f.formSubmitted=h,f.successList.push(c),f.invalid[c.name]=!1,f.showErrors()):(d={},g=a||f.defaultMessage(c,{method:e,parameters:b}),d[c.name]=i.message=g,f.invalid[c.name]=!0,f.showErrors(d)),i.valid=j,f.stopRequest(c,j)}},d)),"pending")}}});var b,c={};return a.ajaxPrefilter?a.ajaxPrefilter(function(a,b,d){var e=a.port;"abort"===a.mode&&(c[e]&&c[e].abort(),c[e]=d)}):(b=a.ajax,a.ajax=function(d){var e=("mode"in d?d:a.ajaxSettings).mode,f=("port"in d?d:a.ajaxSettings).port;return"abort"===e?(c[f]&&c[f].abort(),c[f]=b.apply(this,arguments),c[f]):b.apply(this,arguments)}),a});
--------------------------------------------------------------------------------
/src/main/resources/static/js/litewebchat_input.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */
6 | "use strict";
7 |
8 |
9 | // --------------------------------
10 | // 上半部分的聊天区域
11 | var upperChild = document.querySelector('.lite-chatbox');
12 | // 分界线
13 | var oLine = document.querySelector('.lite-chatinput hr');
14 | // 下半部分的输入框区域
15 | var downChild = document.querySelector('.lite-chatinput');
16 | var downHeight = downChild.clientHeight;
17 | var upperHeight = upperChild.clientHeight;
18 |
19 | // 以下为输入框区域的按钮
20 | var emojiBtn = document.getElementById("emojiBtn"); // 表情按钮
21 | var imageBtn = document.getElementById("imageBtn"); // 图片按钮
22 | var fileBtn = document.getElementById("fileBtn"); // 文件按钮
23 | var editFullScreen = document.getElementById("editFullScreen"); // 全屏按钮
24 | var exitFullScreen = document.getElementById("exitFullScreen"); // 退出全屏按钮
25 | var emojiMart = document.getElementById("emojiMart"); // 表情面板
26 | var toolMusk = document.getElementById("toolMusk"); // 表情面板遮罩
27 | var sendBtn = document.getElementById("sendBtn"); // 发送按钮
28 | var chatInput = document.querySelector('.lite-chatinput>.chatinput'); // 输入框
29 | // --------------------------------
30 |
31 | // Emoji Mart(表情面板)设置及唤起
32 | var pickerOptions = {
33 | "locale": "zh",
34 | onEmojiSelect: function onEmojiSelect(e) {
35 | // console.log(e.native);
36 | emojiMart.style.display = "none";
37 | toolMusk.style.display = "none";
38 | insertAtCursor(chatInput, e.native);
39 | // insertEmoji(e.native);
40 | }
41 | };
42 |
43 | var picker = new EmojiMart.Picker(pickerOptions);
44 | emojiMart.appendChild(picker);
45 |
46 | // 负责在光标处插入文字的函数
47 | function insertAtCursor(myField, myValue) {
48 | var editor = myField;
49 | var html = myValue;
50 | editor.focus();
51 | if (window.getSelection) {
52 | var selection = window.getSelection();
53 | if (selection.getRangeAt && selection.rangeCount) {
54 | var range = selection.getRangeAt(0);
55 | range.deleteContents();
56 | var element = document.createElement('div');
57 | element.innerHTML = html;
58 | var node;
59 | var lastNode;
60 | var fragment = document.createDocumentFragment();
61 | while (node = element.firstChild) {
62 | lastNode = fragment.appendChild(node);
63 | }
64 | ;
65 | range.insertNode(fragment);
66 | if (lastNode) {
67 | range = range.cloneRange();
68 | range.setStartAfter(lastNode);
69 | range.collapse(true);
70 | selection.removeAllRanges();
71 | selection.addRange(range);
72 | }
73 | ;
74 | }
75 | } else if (document.selection && document.selection.type != 'Control') {
76 | editor.focus();
77 | var range = document.selection.createRange();
78 | range.pasteHTML(html);
79 | editor.focus();
80 | }
81 | }
82 |
83 | // 调整聊天区域和输入框区域比例的函数
84 | oLine.onmousedown = function (ev) {
85 | // 更改oLine颜色为蓝色,方便查看分界线
86 | var olineOriBgColor = oLine.style.backgroundColor;
87 | oLine.style.backgroundColor = "#1E90FF";
88 | var iEvent = ev || event;
89 | var dy = iEvent.clientY; //当你第一次单击的时候,存储y轴的坐标。//相对于浏览器窗口
90 | upperHeight = upperChild.offsetHeight;
91 | downHeight = downChild.offsetHeight;
92 | document.onmousemove = function (ev) {
93 | var iEvent = ev || event;
94 | var diff = iEvent.clientY - dy; //移动的距离(向上滑时为负数,下滑时为正数)
95 | if (100 < upperHeight + diff && 100 < downHeight - diff) {
96 | //两个div的最小高度均为100px
97 | upperChild.style.height = "calc(100% - ".concat(downHeight - diff, "px)");
98 | downChild.style.height = downHeight - diff + 'px';
99 | }
100 | };
101 | document.onmouseup = function () {
102 | // 更改oLine颜色为原色
103 | oLine.style.backgroundColor = olineOriBgColor;
104 | document.onmousedown = null;
105 | document.onmousemove = null;
106 | };
107 | return false;
108 | };
109 |
110 |
111 | // 全屏编辑文字
112 | editFullScreen.onclick = function () {
113 | downHeight = downChild.clientHeight;
114 | upperHeight = upperChild.clientHeight;
115 | downChild.style.height = "100%";
116 | upperChild.style.height = "0px";
117 | editFullScreen.style.display = "none";
118 | exitFullScreen.style.display = "block";
119 | oLine.style.display = "none";
120 | };
121 |
122 | // 退出全屏编辑文字
123 | exitFullScreen.onclick = function () {
124 | // 防呆不防傻,用于避免上部聊天窗口被压到没有高度后出现异常
125 | if (upperHeight != 0) {
126 | downChild.style.height = "".concat(downHeight, "px");
127 | upperChild.style.height = "calc(100% - ".concat(downHeight, "px)");
128 | } else {
129 | upperChild.style.height = "calc(100% - 150px)";
130 | downChild.style.height = "150px";
131 | }
132 | exitFullScreen.style.display = "none";
133 | editFullScreen.style.display = "block";
134 | oLine.style.display = "block";
135 | };
136 |
137 | // 隐藏musk和表情输入框
138 | toolMusk.onclick = function () {
139 | emojiMart.style.display = "none";
140 | toolMusk.style.display = "none";
141 | };
142 |
143 | // 将图片插入到输入框中
144 | function addImage(file) {
145 | new Promise(function (resolve, reject) {
146 | // console.log(file);
147 | // 获取file的src
148 | var reader = new FileReader();
149 | reader.onload = function (e) {
150 | var src = e.target.result;
151 | var img = new Image();
152 | img.src = src;
153 |
154 | // *这里的方法已经转移到了css里,暂时弃用
155 | // // 为了防止图片在输入框内显示过大不好编辑
156 | // img.style.width = "100px";
157 | // 将img从HEMLElement转化为字符串
158 | // 例如,转化结束后为' '
159 | var imgStr = img.outerHTML;
160 | // 将img字符串插入到输入框中
161 | insertAtCursor(chatInput, imgStr);
162 | };
163 | reader.readAsDataURL(file);
164 | });
165 | }
166 |
167 | // 上传图片、文件
168 | function inputFile(settings) {
169 | console.log(settings);
170 | // -----------------设置最大图片大小及数量-----------------
171 | if (settings.maxImageSize != undefined) {
172 | var maxImageSize = settings.maxImageSize;
173 | } else {
174 | var maxImageSize = -1;
175 | }
176 | if (settings.maxImageNumber != undefined) {
177 | var maxImageNumber = settings.maxImageNumber;
178 | } else {
179 | var maxImageNumber = -1;
180 | }
181 | if (settings.enable) {
182 | // -----------------上传图片的按钮-----------------
183 | imageBtn.onclick = function () {
184 | var imageInput = document.createElement('input');
185 | imageInput.type = 'file';
186 | imageInput.accept = 'image/*';
187 | imageInput.multiple = true;
188 | imageInput.style.display = 'none';
189 | imageInput.onchange = function () {
190 | // 获取输入框内图片数量
191 | // 获取文件
192 | var imgNum = chatInput.getElementsByTagName('img').length;
193 | for (var i = 0; i < this.files.length; i++) {
194 | if (maxImageNumber == -1 || imgNum < maxImageNumber) {
195 | // 如果大小超过限制,改用文件上传
196 | if (maxImageSize == -1 || this.files[i].size <= maxImageSize) {
197 | imgNum++;
198 | addImage(this.files[i]);
199 | } else {
200 | sendFile(this.files[i]);
201 | }
202 | }
203 | }
204 | };
205 | // 触发点击事件
206 | imageInput.click();
207 | };
208 | // -----------------上传文件的按钮-----------------
209 | var sendFile = settings.sendFileFunc;
210 | // 上传文件按钮
211 | fileBtn.onclick = function () {
212 | // 创建一个隐藏的上传文件的input,再借助点击这个input来上传文件
213 | var fileInput = document.createElement('input');
214 | fileInput.type = 'file';
215 | fileInput.multiple = true;
216 | fileInput.style.display = 'none';
217 | fileInput.onchange = function () {
218 | // 获取文件
219 | for (var i = 0; i < this.files.length; i++) {
220 | var file = this.files[i];
221 | sendFile(file);
222 | }
223 | };
224 | // 触发点击事件
225 | fileInput.click();
226 | };
227 |
228 | // -----------------拖拽上传-----------------
229 | if (settings.enableDrop) {
230 | // 当downChild有文件被拖入时,也调用上传文件的函数
231 | downChild.ondrop = function (e) {
232 | e.preventDefault();
233 | // 阻止火狐浏览器默认打开文件的行为
234 | e.stopPropagation();
235 | downChild.style.border = "none";
236 | // 获取被拖拽的文件并上传
237 | var imgNum = chatInput.getElementsByTagName('img').length;
238 | for (var i = 0; i < e.dataTransfer.files.length; i++) {
239 | var file = e.dataTransfer.files[i];
240 | // 如果是图片,直接插入到输入框中
241 | if (file.type.indexOf("image") == 0) {
242 | if (maxImageNumber == -1 || imgNum < maxImageNumber) {
243 | // 如果大小超过限制,改用文件上传
244 | if (maxImageSize == -1 || file.size <= maxImageSize) {
245 | addImage(file);
246 | imgNum++;
247 | } else {
248 | sendFile(file);
249 | }
250 | }
251 | } else {
252 | sendFile(file);
253 | }
254 | }
255 | };
256 |
257 | // 当downChild有文件被拖入时,改变downChild的边框颜色
258 | downChild.ondragover = function (e) {
259 | e.preventDefault();
260 | downChild.style.border = "3px solid #1E90FF";
261 | };
262 |
263 | // 当downChild有文件被拖入后离开时,改回downChild的边框颜色
264 | downChild.ondragleave = function (e) {
265 | e.preventDefault();
266 | downChild.style.border = "none";
267 | };
268 | }
269 | } else {
270 | // 如果不允许上传,那么删除事件
271 | imageBtn.onclick = null;
272 | fileBtn.onclick = null;
273 | // 删除拖拽事件
274 | downChild.ondrop = null;
275 | downChild.ondragover = null;
276 | downChild.ondragleave = null;
277 | }
278 | }
279 |
280 | // TODO:可能富文本输入框的粘贴部分需要对Chrome浏览器做部分额外适配,以优化体验
281 | // 无格式粘贴
282 | chatInput.addEventListener('paste', function (e) {
283 | onPaste(e);
284 | });
285 |
286 | //格式化粘贴文本方法
287 | function onPaste(event) {
288 | // 如果粘贴的是文本,就清除格式后粘贴
289 | if (event.clipboardData && event.clipboardData.getData) {
290 | var text = event.clipboardData.getData('text/plain');
291 | if (text) {
292 | event.preventDefault();
293 | document.execCommand('insertText', false, text);
294 | }
295 | }
296 | }
297 |
298 | window.addEventListener('DOMContentLoaded', function () {
299 | chatInput.focus();
300 | });
301 | //# sourceMappingURL=map/litewebchat_input.js.map
302 |
--------------------------------------------------------------------------------
/src/main/resources/static/js/litewebchat_input.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */"use strict";var upperChild=document.querySelector(".lite-chatbox"),oLine=document.querySelector(".lite-chatinput hr"),downChild=document.querySelector(".lite-chatinput"),downHeight=downChild.clientHeight,upperHeight=upperChild.clientHeight,emojiBtn=document.getElementById("emojiBtn"),imageBtn=document.getElementById("imageBtn"),fileBtn=document.getElementById("fileBtn"),editFullScreen=document.getElementById("editFullScreen"),exitFullScreen=document.getElementById("exitFullScreen"),emojiMart=document.getElementById("emojiMart"),toolMusk=document.getElementById("toolMusk"),sendBtn=document.getElementById("sendBtn"),chatInput=document.querySelector(".lite-chatinput>.chatinput"),pickerOptions={locale:"zh",onEmojiSelect:function(e){emojiMart.style.display="none",toolMusk.style.display="none",insertAtCursor(chatInput,e.native)}},picker=new EmojiMart.Picker(pickerOptions);function insertAtCursor(e,t){var n=e,o=t;if(n.focus(),window.getSelection){var i=window.getSelection();if(i.getRangeAt&&i.rangeCount){(r=i.getRangeAt(0)).deleteContents();var l,a,c=document.createElement("div");c.innerHTML=o;for(var d=document.createDocumentFragment();l=c.firstChild;)a=d.appendChild(l);r.insertNode(d),a&&((r=r.cloneRange()).setStartAfter(a),r.collapse(!0),i.removeAllRanges(),i.addRange(r))}}else if(document.selection&&"Control"!=document.selection.type){var r;n.focus(),(r=document.selection.createRange()).pasteHTML(o),n.focus()}}function addImage(e){new Promise((function(t,n){var o=new FileReader;o.onload=function(e){var t=e.target.result,n=new Image;n.src=t;var o=n.outerHTML;insertAtCursor(chatInput,o)},o.readAsDataURL(e)}))}function inputFile(e){if(console.log(e),null!=e.maxImageSize)var t=e.maxImageSize;else t=-1;if(null!=e.maxImageNumber)var n=e.maxImageNumber;else n=-1;if(e.enable){imageBtn.onclick=function(){var e=document.createElement("input");e.type="file",e.accept="image/*",e.multiple=!0,e.style.display="none",e.onchange=function(){for(var e=chatInput.getElementsByTagName("img").length,i=0;i chatBox.clientHeight) {
36 | chatBox.scrollTop = chatBox.scrollHeight;
37 | chatBox = '';
38 | htmlStr = '';
39 | }
40 | }, 300);
41 | }
42 | function renderMessageHtml(data) {
43 | return "\n
\n
\n ").concat(renderTitleHtml(data.htitle, TitleType[data.htitleType] || ''), "\n ").concat(escapeHtml(data.name) || ' ', " \n \n
").concat(data.messageType === 'raw' ? data.html : escapeHtml(data.html), " \n
");
44 | }
45 | function renderTitleHtml(content, css) {
46 | if (!content) return '';
47 | return "").concat(content, " ");
48 | }
49 | function renderTipHtml(content, css) {
50 | if (!content) return '';
51 | return "").concat(escapeHtml(content), "
");
52 | }
53 |
54 | // 转义 C0 Controls and Basic Latin 中非数字和字母,C1 Controls and Latin-1 Supplement 全部
55 | // https://www.w3schools.com/charsets/ref_html_utf8.asp
56 | function escapeHtml(unsafe) {
57 | return unsafe === null || unsafe === void 0 ? void 0 : unsafe.replace(/[\u0000-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u00FF]/g, function (c) {
58 | return '' + ('000' + c.charCodeAt(0)).slice(-4) + ';';
59 | });
60 | }
61 | //# sourceMappingURL=map/litewebchat_render.js.map
62 |
--------------------------------------------------------------------------------
/src/main/resources/static/js/litewebchat_render.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * LiteWebChat_Frame 2.2.1 (https://lab.morfans.cn/LiteWebChat_Frame)
3 | * MorFans Lab(c) 2017-2023
4 | * Licensed under LGPL
5 | */"use strict";var TipsType={tipsNormal:"tips",tipsPrimary:"tips-primary",tipsSuccess:"tips-success",tipsInfo:"tips-info",tipsWarning:"tips-warning",tipsDanger:"tips-danger"},TitleType={admin:"admin",owner:"owner"};function beforeRenderingHTML(e,n){for(var t="",s=document.querySelector(n),i=0;is.clientHeight&&(s.scrollTop=s.scrollHeight,s="",t="")}),300)}function renderMessageHtml(e){return'\n
\n
\n ').concat(renderTitleHtml(e.htitle,TitleType[e.htitleType]||""),"\n ").concat(escapeHtml(e.name)||" ",' \n \n
').concat("raw"===e.messageType?e.html:escapeHtml(e.html)," \n
")}function renderTitleHtml(e,n){return e?'').concat(e," "):""}function renderTipHtml(e,n){return e?'').concat(escapeHtml(e),"
"):""}function escapeHtml(e){return null==e?void 0:e.replace(/[\u0000-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u00FF]/g,(function(e){return""+("000"+e.charCodeAt(0)).slice(-4)+";"}))}
6 | //# sourceMappingURL=map/litewebchat_render.min.js.map
7 |
--------------------------------------------------------------------------------
/src/main/resources/static/js/map/litewebchat_input.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["input.js"],"names":["upperChild","document","querySelector","oLine","downChild","downHeight","clientHeight","upperHeight","emojiBtn","getElementById","imageBtn","fileBtn","editFullScreen","exitFullScreen","emojiMart","toolMusk","sendBtn","chatInput","pickerOptions","onEmojiSelect","e","style","display","insertAtCursor","native","picker","EmojiMart","Picker","appendChild","myField","myValue","editor","html","focus","window","getSelection","selection","getRangeAt","rangeCount","range","deleteContents","element","createElement","innerHTML","node","lastNode","fragment","createDocumentFragment","firstChild","insertNode","cloneRange","setStartAfter","collapse","removeAllRanges","addRange","type","createRange","pasteHTML","onmousedown","ev","olineOriBgColor","backgroundColor","iEvent","event","dy","clientY","offsetHeight","onmousemove","diff","height","onmouseup","onclick","emojiHeight","bottom","top","addImage","file","Promise","resolve","reject","reader","FileReader","onload","src","target","result","img","Image","imgStr","outerHTML","readAsDataURL","inputFile","settings","console","log","maxImageSize","undefined","maxImageNumber","enable","imageInput","accept","multiple","onchange","imgNum","getElementsByTagName","length","i","files","size","sendFile","click","sendFileFunc","fileInput","enableDrop","ondrop","preventDefault","stopPropagation","border","dataTransfer","indexOf","ondragover","ondragleave","addEventListener","onPaste","clipboardData","getData","text","execCommand"],"mappings":"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","file":"../litewebchat_input.js","sourcesContent":["// !参考资料来源:\n// !https://blog.csdn.net/weixin_40629244/article/details/104642683\n// !https://github.com/jrainlau/chat-input-box\n// !https://www.zhihu.com/question/20893119/answer/19452676\n// !致谢:感谢@jrainlau提供的思路和代码,我在他的富文本编辑器基础上进行了修改,使其能够在聊天输入框中使用\n// ————YubaC 2023.1.23\n\n// --------------------------------\n// 上半部分的聊天区域\nlet upperChild = document.querySelector('.lite-chatbox');\n// 分界线\nlet oLine = document.querySelector('.lite-chatinput hr');\n// 下半部分的输入框区域\nlet downChild = document.querySelector('.lite-chatinput');\n\nvar downHeight = downChild.clientHeight;\nvar upperHeight = upperChild.clientHeight;\n\n// 以下为输入框区域的按钮\nvar emojiBtn = document.getElementById(\"emojiBtn\"); // 表情按钮\nvar imageBtn = document.getElementById(\"imageBtn\"); // 图片按钮\nvar fileBtn = document.getElementById(\"fileBtn\"); // 文件按钮\nvar editFullScreen = document.getElementById(\"editFullScreen\"); // 全屏按钮\nvar exitFullScreen = document.getElementById(\"exitFullScreen\"); // 退出全屏按钮\nvar emojiMart = document.getElementById(\"emojiMart\"); // 表情面板\nvar toolMusk = document.getElementById(\"toolMusk\"); // 表情面板遮罩\nvar sendBtn = document.getElementById(\"sendBtn\"); // 发送按钮\nvar chatInput = document.querySelector('.lite-chatinput>.chatinput'); // 输入框\n// --------------------------------\n\n// Emoji Mart(表情面板)设置及唤起\nvar pickerOptions = {\n \"locale\": \"zh\",\n onEmojiSelect: function (e) {\n // console.log(e.native);\n emojiMart.style.display = \"none\";\n toolMusk.style.display = \"none\";\n insertAtCursor(chatInput, e.native);\n // insertEmoji(e.native);\n }\n}\nvar picker = new EmojiMart.Picker(pickerOptions);\nemojiMart.appendChild(picker);\n\n// 负责在光标处插入文字的函数\nfunction insertAtCursor(myField, myValue) {\n var editor = myField;\n var html = myValue;\n editor.focus();\n\n if (window.getSelection) {\n var selection = window.getSelection();\n if (selection.getRangeAt && selection.rangeCount) {\n var range = selection.getRangeAt(0);\n range.deleteContents();\n var element = document.createElement('div');\n element.innerHTML = html;\n\n var node;\n var lastNode;\n var fragment = document.createDocumentFragment();\n\n while ((node = element.firstChild)) {\n lastNode = fragment.appendChild(node);\n };\n\n range.insertNode(fragment);\n if (lastNode) {\n range = range.cloneRange();\n range.setStartAfter(lastNode);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n };\n }\n\n } else if (document.selection && document.selection.type != 'Control') {\n editor.focus();\n var range = document.selection.createRange();\n range.pasteHTML(html);\n editor.focus();\n }\n}\n\n// 调整聊天区域和输入框区域比例的函数\noLine.onmousedown = function (ev) {\n // 更改oLine颜色为蓝色,方便查看分界线\n const olineOriBgColor = oLine.style.backgroundColor;\n oLine.style.backgroundColor = \"#1E90FF\";\n var iEvent = ev || event;\n var dy = iEvent.clientY; //当你第一次单击的时候,存储y轴的坐标。//相对于浏览器窗口\n upperHeight = upperChild.offsetHeight;\n downHeight = downChild.offsetHeight;\n document.onmousemove = function (ev) {\n var iEvent = ev || event;\n var diff = iEvent.clientY - dy; //移动的距离(向上滑时为负数,下滑时为正数)\n if (100 < (upperHeight + diff) && 100 < (downHeight - diff)) {\n //两个div的最小高度均为100px\n upperChild.style.height = `calc(100% - ${downHeight - diff}px)`;\n downChild.style.height = (downHeight - diff) + 'px';\n }\n };\n document.onmouseup = function () {\n // 更改oLine颜色为原色\n oLine.style.backgroundColor = olineOriBgColor;\n document.onmousedown = null;\n document.onmousemove = null;\n };\n return false;\n}\n\n// 显示表情输入框\nemojiBtn.onclick = function () {\n emojiMart.style.display = \"block\";\n toolMusk.style.display = \"block\";\n\n let emojiHeight = emojiMart.offsetHeight;\n downHeight = downChild.clientHeight;\n upperHeight = upperChild.clientHeight;\n\n if (emojiHeight < upperHeight) {\n emojiMart.style.bottom = `${downHeight + 3}px`\n emojiMart.style.top = '';\n } else {\n emojiMart.style.bottom = ''\n emojiMart.style.top = '10px';\n }\n\n}\n\n// 全屏编辑文字\neditFullScreen.onclick = function () {\n downHeight = downChild.clientHeight;\n upperHeight = upperChild.clientHeight;\n downChild.style.height = `100%`;\n upperChild.style.height = \"0px\";\n editFullScreen.style.display = \"none\";\n exitFullScreen.style.display = \"block\";\n oLine.style.display = \"none\";\n}\n\n// 退出全屏编辑文字\nexitFullScreen.onclick = function () {\n // 防呆不防傻,用于避免上部聊天窗口被压到没有高度后出现异常\n if (upperHeight != 0) {\n downChild.style.height = `${downHeight}px`;\n upperChild.style.height = `calc(100% - ${downHeight}px)`;\n } else {\n upperChild.style.height = \"calc(100% - 150px)\";\n downChild.style.height = \"150px\";\n }\n\n exitFullScreen.style.display = \"none\";\n editFullScreen.style.display = \"block\";\n oLine.style.display = \"block\";\n}\n\n// 隐藏musk和表情输入框\ntoolMusk.onclick = function () {\n emojiMart.style.display = \"none\";\n toolMusk.style.display = \"none\";\n}\n\n// 将图片插入到输入框中\nfunction addImage(file) {\n new Promise((resolve, reject) => {\n // console.log(file);\n // 获取file的src\n var reader = new FileReader();\n reader.onload = function (e) {\n var src = e.target.result;\n var img = new Image();\n img.src = src;\n\n // *这里的方法已经转移到了css里,暂时弃用\n // // 为了防止图片在输入框内显示过大不好编辑\n // img.style.width = \"100px\";\n // 将img从HEMLElement转化为字符串\n // 例如,转化结束后为' '\n var imgStr = img.outerHTML;\n // 将img字符串插入到输入框中\n insertAtCursor(chatInput, imgStr);\n }\n reader.readAsDataURL(file);\n })\n}\n\n// 上传图片、文件\nfunction inputFile(settings) {\n console.log(settings);\n // -----------------设置最大图片大小及数量-----------------\n if (settings.maxImageSize != undefined) {\n var maxImageSize = settings.maxImageSize;\n } else {\n var maxImageSize = -1;\n }\n\n if (settings.maxImageNumber != undefined) {\n var maxImageNumber = settings.maxImageNumber;\n } else {\n var maxImageNumber = -1;\n }\n\n if (settings.enable) {\n // -----------------上传图片的按钮-----------------\n imageBtn.onclick = function () {\n var imageInput = document.createElement('input');\n imageInput.type = 'file';\n imageInput.accept = 'image/*';\n imageInput.multiple = true;\n imageInput.style.display = 'none';\n imageInput.onchange = function () {\n // 获取输入框内图片数量\n // 获取文件\n var imgNum = chatInput.getElementsByTagName('img').length;\n for (var i = 0; i < this.files.length; i++) {\n if (maxImageNumber == -1 || imgNum < maxImageNumber) {\n // 如果大小超过限制,改用文件上传\n if ((maxImageSize == -1 || this.files[i].size <= maxImageSize)) {\n imgNum++;\n addImage(this.files[i]);\n } else {\n sendFile(this.files[i]);\n }\n }\n }\n }\n // 触发点击事件\n imageInput.click();\n }\n // -----------------上传文件的按钮-----------------\n let sendFile = settings.sendFileFunc;\n // 上传文件按钮\n fileBtn.onclick = function () {\n // 创建一个隐藏的上传文件的input,再借助点击这个input来上传文件\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.multiple = true;\n fileInput.style.display = 'none';\n fileInput.onchange = function () {\n // 获取文件\n for (var i = 0; i < this.files.length; i++) {\n var file = this.files[i];\n sendFile(file);\n }\n }\n // 触发点击事件\n fileInput.click();\n }\n\n // -----------------拖拽上传-----------------\n if (settings.enableDrop) {\n // 当downChild有文件被拖入时,也调用上传文件的函数\n downChild.ondrop = function (e) {\n e.preventDefault();\n // 阻止火狐浏览器默认打开文件的行为\n e.stopPropagation();\n downChild.style.border = \"none\";\n // 获取被拖拽的文件并上传\n var imgNum = chatInput.getElementsByTagName('img').length;\n for (var i = 0; i < e.dataTransfer.files.length; i++) {\n var file = e.dataTransfer.files[i];\n // 如果是图片,直接插入到输入框中\n if (file.type.indexOf(\"image\") == 0) {\n if (maxImageNumber == -1 || imgNum < maxImageNumber) {\n // 如果大小超过限制,改用文件上传\n if ((maxImageSize == -1 || file.size <= maxImageSize)) {\n addImage(file);\n imgNum++;\n } else {\n sendFile(file);\n }\n }\n } else {\n sendFile(file);\n }\n }\n }\n\n // 当downChild有文件被拖入时,改变downChild的边框颜色\n downChild.ondragover = function (e) {\n e.preventDefault();\n downChild.style.border = \"3px solid #1E90FF\";\n }\n\n // 当downChild有文件被拖入后离开时,改回downChild的边框颜色\n downChild.ondragleave = function (e) {\n e.preventDefault();\n downChild.style.border = \"none\";\n }\n }\n } else {\n // 如果不允许上传,那么删除事件\n imageBtn.onclick = null;\n fileBtn.onclick = null;\n // 删除拖拽事件\n downChild.ondrop = null;\n downChild.ondragover = null;\n downChild.ondragleave = null;\n }\n}\n\n// TODO:可能富文本输入框的粘贴部分需要对Chrome浏览器做部分额外适配,以优化体验\n// 无格式粘贴\nchatInput.addEventListener('paste', function (e) {\n onPaste(e);\n})\n\n//格式化粘贴文本方法\nfunction onPaste(event) {\n // 如果粘贴的是文本,就清除格式后粘贴\n if (event.clipboardData && event.clipboardData.getData) {\n var text = event.clipboardData.getData('text/plain');\n if (text) {\n event.preventDefault();\n document.execCommand('insertText', false, text);\n }\n }\n}\n\nwindow.addEventListener('DOMContentLoaded', function () {\n chatInput.focus();\n});\n"]}
--------------------------------------------------------------------------------
/src/main/resources/static/js/map/litewebchat_input.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["input.js"],"names":["upperChild","document","querySelector","oLine","downChild","downHeight","clientHeight","upperHeight","emojiBtn","getElementById","imageBtn","fileBtn","editFullScreen","exitFullScreen","emojiMart","toolMusk","sendBtn","chatInput","pickerOptions","locale","onEmojiSelect","e","style","display","insertAtCursor","native","picker","EmojiMart","Picker","myField","myValue","editor","html","focus","window","getSelection","selection","getRangeAt","rangeCount","range","deleteContents","node","lastNode","element","createElement","innerHTML","fragment","createDocumentFragment","firstChild","appendChild","insertNode","cloneRange","setStartAfter","collapse","removeAllRanges","addRange","type","createRange","pasteHTML","addImage","file","Promise","resolve","reject","reader","FileReader","onload","src","target","result","img","Image","imgStr","outerHTML","readAsDataURL","inputFile","settings","console","log","undefined","maxImageSize","maxImageNumber","enable","onclick","imageInput","accept","multiple","onchange","imgNum","getElementsByTagName","length","i","this","files","size","sendFile","click","sendFileFunc","fileInput","enableDrop","ondrop","preventDefault","stopPropagation","border","dataTransfer","indexOf","ondragover","ondragleave","onPaste","event","clipboardData","getData","text","execCommand","onmousedown","ev","olineOriBgColor","backgroundColor","dy","clientY","offsetHeight","onmousemove","diff","height","concat","onmouseup","emojiHeight","bottom","top","addEventListener"],"mappings":"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","file":"../litewebchat_input.min.js","sourcesContent":["// !参考资料来源:\n// !https://blog.csdn.net/weixin_40629244/article/details/104642683\n// !https://github.com/jrainlau/chat-input-box\n// !https://www.zhihu.com/question/20893119/answer/19452676\n// !致谢:感谢@jrainlau提供的思路和代码,我在他的富文本编辑器基础上进行了修改,使其能够在聊天输入框中使用\n// ————YubaC 2023.1.23\n\n// --------------------------------\n// 上半部分的聊天区域\nlet upperChild = document.querySelector('.lite-chatbox');\n// 分界线\nlet oLine = document.querySelector('.lite-chatinput hr');\n// 下半部分的输入框区域\nlet downChild = document.querySelector('.lite-chatinput');\n\nvar downHeight = downChild.clientHeight;\nvar upperHeight = upperChild.clientHeight;\n\n// 以下为输入框区域的按钮\nvar emojiBtn = document.getElementById(\"emojiBtn\"); // 表情按钮\nvar imageBtn = document.getElementById(\"imageBtn\"); // 图片按钮\nvar fileBtn = document.getElementById(\"fileBtn\"); // 文件按钮\nvar editFullScreen = document.getElementById(\"editFullScreen\"); // 全屏按钮\nvar exitFullScreen = document.getElementById(\"exitFullScreen\"); // 退出全屏按钮\nvar emojiMart = document.getElementById(\"emojiMart\"); // 表情面板\nvar toolMusk = document.getElementById(\"toolMusk\"); // 表情面板遮罩\nvar sendBtn = document.getElementById(\"sendBtn\"); // 发送按钮\nvar chatInput = document.querySelector('.lite-chatinput>.chatinput'); // 输入框\n// --------------------------------\n\n// Emoji Mart(表情面板)设置及唤起\nvar pickerOptions = {\n \"locale\": \"zh\",\n onEmojiSelect: function (e) {\n // console.log(e.native);\n emojiMart.style.display = \"none\";\n toolMusk.style.display = \"none\";\n insertAtCursor(chatInput, e.native);\n // insertEmoji(e.native);\n }\n}\nvar picker = new EmojiMart.Picker(pickerOptions);\nemojiMart.appendChild(picker);\n\n// 负责在光标处插入文字的函数\nfunction insertAtCursor(myField, myValue) {\n var editor = myField;\n var html = myValue;\n editor.focus();\n\n if (window.getSelection) {\n var selection = window.getSelection();\n if (selection.getRangeAt && selection.rangeCount) {\n var range = selection.getRangeAt(0);\n range.deleteContents();\n var element = document.createElement('div');\n element.innerHTML = html;\n\n var node;\n var lastNode;\n var fragment = document.createDocumentFragment();\n\n while ((node = element.firstChild)) {\n lastNode = fragment.appendChild(node);\n };\n\n range.insertNode(fragment);\n if (lastNode) {\n range = range.cloneRange();\n range.setStartAfter(lastNode);\n range.collapse(true);\n selection.removeAllRanges();\n selection.addRange(range);\n };\n }\n\n } else if (document.selection && document.selection.type != 'Control') {\n editor.focus();\n var range = document.selection.createRange();\n range.pasteHTML(html);\n editor.focus();\n }\n}\n\n// 调整聊天区域和输入框区域比例的函数\noLine.onmousedown = function (ev) {\n // 更改oLine颜色为蓝色,方便查看分界线\n const olineOriBgColor = oLine.style.backgroundColor;\n oLine.style.backgroundColor = \"#1E90FF\";\n var iEvent = ev || event;\n var dy = iEvent.clientY; //当你第一次单击的时候,存储y轴的坐标。//相对于浏览器窗口\n upperHeight = upperChild.offsetHeight;\n downHeight = downChild.offsetHeight;\n document.onmousemove = function (ev) {\n var iEvent = ev || event;\n var diff = iEvent.clientY - dy; //移动的距离(向上滑时为负数,下滑时为正数)\n if (100 < (upperHeight + diff) && 100 < (downHeight - diff)) {\n //两个div的最小高度均为100px\n upperChild.style.height = `calc(100% - ${downHeight - diff}px)`;\n downChild.style.height = (downHeight - diff) + 'px';\n }\n };\n document.onmouseup = function () {\n // 更改oLine颜色为原色\n oLine.style.backgroundColor = olineOriBgColor;\n document.onmousedown = null;\n document.onmousemove = null;\n };\n return false;\n}\n\n// 显示表情输入框\nemojiBtn.onclick = function () {\n emojiMart.style.display = \"block\";\n toolMusk.style.display = \"block\";\n\n let emojiHeight = emojiMart.offsetHeight;\n downHeight = downChild.clientHeight;\n upperHeight = upperChild.clientHeight;\n\n if (emojiHeight < upperHeight) {\n emojiMart.style.bottom = `${downHeight + 3}px`\n emojiMart.style.top = '';\n } else {\n emojiMart.style.bottom = ''\n emojiMart.style.top = '10px';\n }\n\n}\n\n// 全屏编辑文字\neditFullScreen.onclick = function () {\n downHeight = downChild.clientHeight;\n upperHeight = upperChild.clientHeight;\n downChild.style.height = `100%`;\n upperChild.style.height = \"0px\";\n editFullScreen.style.display = \"none\";\n exitFullScreen.style.display = \"block\";\n oLine.style.display = \"none\";\n}\n\n// 退出全屏编辑文字\nexitFullScreen.onclick = function () {\n // 防呆不防傻,用于避免上部聊天窗口被压到没有高度后出现异常\n if (upperHeight != 0) {\n downChild.style.height = `${downHeight}px`;\n upperChild.style.height = `calc(100% - ${downHeight}px)`;\n } else {\n upperChild.style.height = \"calc(100% - 150px)\";\n downChild.style.height = \"150px\";\n }\n\n exitFullScreen.style.display = \"none\";\n editFullScreen.style.display = \"block\";\n oLine.style.display = \"block\";\n}\n\n// 隐藏musk和表情输入框\ntoolMusk.onclick = function () {\n emojiMart.style.display = \"none\";\n toolMusk.style.display = \"none\";\n}\n\n// 将图片插入到输入框中\nfunction addImage(file) {\n new Promise((resolve, reject) => {\n // console.log(file);\n // 获取file的src\n var reader = new FileReader();\n reader.onload = function (e) {\n var src = e.target.result;\n var img = new Image();\n img.src = src;\n\n // *这里的方法已经转移到了css里,暂时弃用\n // // 为了防止图片在输入框内显示过大不好编辑\n // img.style.width = \"100px\";\n // 将img从HEMLElement转化为字符串\n // 例如,转化结束后为' '\n var imgStr = img.outerHTML;\n // 将img字符串插入到输入框中\n insertAtCursor(chatInput, imgStr);\n }\n reader.readAsDataURL(file);\n })\n}\n\n// 上传图片、文件\nfunction inputFile(settings) {\n console.log(settings);\n // -----------------设置最大图片大小及数量-----------------\n if (settings.maxImageSize != undefined) {\n var maxImageSize = settings.maxImageSize;\n } else {\n var maxImageSize = -1;\n }\n\n if (settings.maxImageNumber != undefined) {\n var maxImageNumber = settings.maxImageNumber;\n } else {\n var maxImageNumber = -1;\n }\n\n if (settings.enable) {\n // -----------------上传图片的按钮-----------------\n imageBtn.onclick = function () {\n var imageInput = document.createElement('input');\n imageInput.type = 'file';\n imageInput.accept = 'image/*';\n imageInput.multiple = true;\n imageInput.style.display = 'none';\n imageInput.onchange = function () {\n // 获取输入框内图片数量\n // 获取文件\n var imgNum = chatInput.getElementsByTagName('img').length;\n for (var i = 0; i < this.files.length; i++) {\n if (maxImageNumber == -1 || imgNum < maxImageNumber) {\n // 如果大小超过限制,改用文件上传\n if ((maxImageSize == -1 || this.files[i].size <= maxImageSize)) {\n imgNum++;\n addImage(this.files[i]);\n } else {\n sendFile(this.files[i]);\n }\n }\n }\n }\n // 触发点击事件\n imageInput.click();\n }\n // -----------------上传文件的按钮-----------------\n let sendFile = settings.sendFileFunc;\n // 上传文件按钮\n fileBtn.onclick = function () {\n // 创建一个隐藏的上传文件的input,再借助点击这个input来上传文件\n var fileInput = document.createElement('input');\n fileInput.type = 'file';\n fileInput.multiple = true;\n fileInput.style.display = 'none';\n fileInput.onchange = function () {\n // 获取文件\n for (var i = 0; i < this.files.length; i++) {\n var file = this.files[i];\n sendFile(file);\n }\n }\n // 触发点击事件\n fileInput.click();\n }\n\n // -----------------拖拽上传-----------------\n if (settings.enableDrop) {\n // 当downChild有文件被拖入时,也调用上传文件的函数\n downChild.ondrop = function (e) {\n e.preventDefault();\n // 阻止火狐浏览器默认打开文件的行为\n e.stopPropagation();\n downChild.style.border = \"none\";\n // 获取被拖拽的文件并上传\n var imgNum = chatInput.getElementsByTagName('img').length;\n for (var i = 0; i < e.dataTransfer.files.length; i++) {\n var file = e.dataTransfer.files[i];\n // 如果是图片,直接插入到输入框中\n if (file.type.indexOf(\"image\") == 0) {\n if (maxImageNumber == -1 || imgNum < maxImageNumber) {\n // 如果大小超过限制,改用文件上传\n if ((maxImageSize == -1 || file.size <= maxImageSize)) {\n addImage(file);\n imgNum++;\n } else {\n sendFile(file);\n }\n }\n } else {\n sendFile(file);\n }\n }\n }\n\n // 当downChild有文件被拖入时,改变downChild的边框颜色\n downChild.ondragover = function (e) {\n e.preventDefault();\n downChild.style.border = \"3px solid #1E90FF\";\n }\n\n // 当downChild有文件被拖入后离开时,改回downChild的边框颜色\n downChild.ondragleave = function (e) {\n e.preventDefault();\n downChild.style.border = \"none\";\n }\n }\n } else {\n // 如果不允许上传,那么删除事件\n imageBtn.onclick = null;\n fileBtn.onclick = null;\n // 删除拖拽事件\n downChild.ondrop = null;\n downChild.ondragover = null;\n downChild.ondragleave = null;\n }\n}\n\n// TODO:可能富文本输入框的粘贴部分需要对Chrome浏览器做部分额外适配,以优化体验\n// 无格式粘贴\nchatInput.addEventListener('paste', function (e) {\n onPaste(e);\n})\n\n//格式化粘贴文本方法\nfunction onPaste(event) {\n // 如果粘贴的是文本,就清除格式后粘贴\n if (event.clipboardData && event.clipboardData.getData) {\n var text = event.clipboardData.getData('text/plain');\n if (text) {\n event.preventDefault();\n document.execCommand('insertText', false, text);\n }\n }\n}\n\nwindow.addEventListener('DOMContentLoaded', function () {\n chatInput.focus();\n});\n"]}
--------------------------------------------------------------------------------
/src/main/resources/static/js/map/litewebchat_render.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["render.js"],"names":["TipsType","tipsNormal","tipsPrimary","tipsSuccess","tipsInfo","tipsWarning","tipsDanger","TitleType","admin","owner","beforeRenderingHTML","data","chatboxClass","htmlStr","chatBox","document","querySelector","i","length","isRender","messageType","indexOf","renderTipHtml","html","renderMessageHtml","insertAdjacentHTML","setTimeout","scrollHeight","clientHeight","scrollTop","position","diamond","headIcon","renderTitleHtml","htitle","htitleType","escapeHtml","name","content","css","unsafe","replace","c","charCodeAt","slice"],"mappings":";;;;;;AAAA,IAAMA,QAAQ,GAAG;EACfC,UAAU,EAAE,MAAM;EAClBC,WAAW,EAAE,cAAc;EAC3BC,WAAW,EAAE,cAAc;EAC3BC,QAAQ,EAAE,WAAW;EACrBC,WAAW,EAAE,cAAc;EAC3BC,UAAU,EAAE;AACd,CAAC;AACD,IAAMC,SAAS,GAAG;EAChBC,KAAK,EAAE,OAAO;EACdC,KAAK,EAAE;AACT,CAAC;AAED,SAASC,mBAAmB,CAACC,IAAI,EAAEC,YAAY,EAAE;EAC/C,IAAIC,OAAO,GAAG,EAAE;EAChB,IAAIC,OAAO,GAAGC,QAAQ,CAACC,aAAa,CAACJ,YAAY,CAAC;EAClD,KAAK,IAAIK,CAAC,GAAG,CAAC,EAAEA,CAAC,GAAGN,IAAI,CAACO,MAAM,EAAED,CAAC,EAAE,EAAE;IACpC,IAAIN,IAAI,CAACM,CAAC,CAAC,CAACE,QAAQ,EAAE;MACpB;IACF;IACA,IAAIR,IAAI,CAACM,CAAC,CAAC,CAACG,WAAW,CAACC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;MAC9CR,OAAO,IAAIS,aAAa,CAACX,IAAI,CAACM,CAAC,CAAC,CAACM,IAAI,EAAEvB,QAAQ,CAACW,IAAI,CAACM,CAAC,CAAC,CAACG,WAAW,CAAC,IAAI,MAAM,CAAC;IACjF,CAAC,MAAM;MACLP,OAAO,IAAIW,iBAAiB,CAACb,IAAI,CAACM,CAAC,CAAC,CAAC;IACvC;IACAN,IAAI,CAACM,CAAC,CAAC,CAACE,QAAQ,GAAG,IAAI;EACzB;EAEAL,OAAO,CAACW,kBAAkB,CAAC,WAAW,EAACZ,OAAO,CAAC;EAC/Ca,UAAU,CAAC,YAAM;IACf,IAAIZ,OAAO,CAACa,YAAY,GAAGb,OAAO,CAACc,YAAY,EAAE;MAC/Cd,OAAO,CAACe,SAAS,GAAGf,OAAO,CAACa,YAAY;MACxCb,OAAO,GAAG,EAAE;MACZD,OAAO,GAAG,EAAE;IACd;EACF,CAAC,EAAE,GAAG,CAAC;AACT;AAEA,SAASW,iBAAiB,CAACb,IAAI,EAAE;EAC/B,+BAAuBA,IAAI,CAACmB,QAAQ,qDACPnB,IAAI,CAACoB,OAAO,GAAG,EAAE,GAAG,QAAQ,sBAAUpB,IAAI,CAACqB,QAAQ,4HAEpEC,eAAe,CAACtB,IAAI,CAACuB,MAAM,EAAE3B,SAAS,CAACI,IAAI,CAACwB,UAAU,CAAC,IAAI,EAAE,CAAC,iCACxDC,UAAU,CAACzB,IAAI,CAAC0B,IAAI,CAAC,IAAI,QAAQ,uEAErB1B,IAAI,CAACS,WAAW,KAAK,KAAK,GAAGT,IAAI,CAACY,IAAI,GAAGa,UAAU,CAACzB,IAAI,CAACY,IAAI,CAAC;AAE9F;AAEA,SAASU,eAAe,CAACK,OAAO,EAAEC,GAAG,EAAE;EACrC,IAAI,CAACD,OAAO,EAAE,OAAO,EAAE;EACvB,sCAA8BC,GAAG,6CAAgCD,OAAO;AAC1E;AAEA,SAAShB,aAAa,CAACgB,OAAO,EAAEC,GAAG,EAAE;EACnC,IAAI,CAACD,OAAO,EAAE,OAAO,EAAE;EACvB,mDAAyCC,GAAG,+CAAkCH,UAAU,CAACE,OAAO,CAAC;AACnG;;AAEA;AACA;AACA,SAASF,UAAU,CAACI,MAAM,EAAE;EAC1B,OAAOA,MAAM,aAANA,MAAM,uBAANA,MAAM,CAAEC,OAAO,CACpB,yDAAyD,EACzD,UAAAC,CAAC;IAAA,OAAI,IAAI,GAAG,CAAC,KAAK,GAAGA,CAAC,CAACC,UAAU,CAAC,CAAC,CAAC,EAAEC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG;EAAA,EACtD;AACH","file":"../litewebchat_render.js","sourcesContent":["const TipsType = {\n tipsNormal: 'tips',\n tipsPrimary: 'tips-primary',\n tipsSuccess: 'tips-success',\n tipsInfo: 'tips-info',\n tipsWarning: 'tips-warning',\n tipsDanger: 'tips-danger',\n};\nconst TitleType = {\n admin: 'admin',\n owner: 'owner',\n};\n\nfunction beforeRenderingHTML(data, chatboxClass) {\n let htmlStr = '';\n let chatBox = document.querySelector(chatboxClass);\n for (let i = 0; i < data.length; i++) {\n if (data[i].isRender) {\n continue;\n }\n if (data[i].messageType.indexOf('tips') !== -1) {\n htmlStr += renderTipHtml(data[i].html, TipsType[data[i].messageType] || 'tips');\n } else {\n htmlStr += renderMessageHtml(data[i]);\n }\n data[i].isRender = true;\n }\n\n chatBox.insertAdjacentHTML('beforeend',htmlStr);\n setTimeout(() => {\n if (chatBox.scrollHeight > chatBox.clientHeight) {\n chatBox.scrollTop = chatBox.scrollHeight;\n chatBox = '';\n htmlStr = '';\n }\n }, 300);\n}\n\nfunction renderMessageHtml(data) {\n return `\n
\n
\n ${renderTitleHtml(data.htitle, TitleType[data.htitleType] || '')}\n ${escapeHtml(data.name) || ' '} \n \n
${data.messageType === 'raw' ? data.html : escapeHtml(data.html)} \n
`;\n}\n\nfunction renderTitleHtml(content, css) {\n if (!content) return '';\n return `${content} `;\n}\n\nfunction renderTipHtml(content, css) {\n if (!content) return '';\n return `${escapeHtml(content)}
`;\n}\n\n// 转义 C0 Controls and Basic Latin 中非数字和字母,C1 Controls and Latin-1 Supplement 全部\n// https://www.w3schools.com/charsets/ref_html_utf8.asp\nfunction escapeHtml(unsafe) {\n return unsafe?.replace(\n /[\\u0000-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u00FF]/g,\n c => '' + ('000' + c.charCodeAt(0)).slice(-4) + ';'\n )\n}\n"]}
--------------------------------------------------------------------------------
/src/main/resources/static/js/map/litewebchat_render.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["render.js"],"names":["TipsType","tipsNormal","tipsPrimary","tipsSuccess","tipsInfo","tipsWarning","tipsDanger","TitleType","admin","owner","beforeRenderingHTML","data","chatboxClass","htmlStr","chatBox","document","querySelector","i","length","isRender","messageType","indexOf","renderTipHtml","html","renderMessageHtml","insertAdjacentHTML","setTimeout","scrollHeight","clientHeight","scrollTop","concat","position","diamond","headIcon","renderTitleHtml","htitle","htitleType","escapeHtml","name","content","css","unsafe","replace","c","charCodeAt","slice"],"mappings":";;;;GAAA,aAAA,IAAMA,SAAW,CACfC,WAAY,OACZC,YAAa,eACbC,YAAa,eACbC,SAAU,YACVC,YAAa,eACbC,WAAY,eAERC,UAAY,CAChBC,MAAO,QACPC,MAAO,SAGT,SAASC,oBAAoBC,EAAMC,GAGjC,IAFA,IAAIC,EAAU,GACVC,EAAUC,SAASC,cAAcJ,GAC5BK,EAAI,EAAGA,EAAIN,EAAKO,OAAQD,IAC3BN,EAAKM,GAAGE,YAGiC,IAAzCR,EAAKM,GAAGG,YAAYC,QAAQ,QAC9BR,GAAWS,cAAcX,EAAKM,GAAGM,KAAMvB,SAASW,EAAKM,GAAGG,cAAgB,QAExEP,GAAWW,kBAAkBb,EAAKM,IAEpCN,EAAKM,GAAGE,UAAW,GAGrBL,EAAQW,mBAAmB,YAAYZ,GACvCa,YAAW,WACLZ,EAAQa,aAAeb,EAAQc,eACjCd,EAAQe,UAAYf,EAAQa,aAC5Bb,EAAU,GACVD,EAAU,GAEd,GAAG,IACL,CAEA,SAASW,kBAAkBb,GACzB,MAAA,gBAAAmB,OAAuBnB,EAAKoB,SAAQ,0CAAAD,OACPnB,EAAKqB,QAAU,GAAK,SAAQ,WAAAF,OAAUnB,EAAKsB,SAAQ,4GAAAH,OAEpEI,gBAAgBvB,EAAKwB,OAAQ5B,UAAUI,EAAKyB,aAAe,IAAG,wBAAAN,OACxDO,WAAW1B,EAAK2B,OAAS,SAAQ,4DAAAR,OAEA,QAArBnB,EAAKS,YAAwBT,EAAKY,KAAOc,WAAW1B,EAAKY,MAAK,sBAE9F,CAEA,SAASW,gBAAgBK,EAASC,GAChC,OAAKD,EACL,uBAAAT,OAA8BU,EAAG,iCAAAV,OAAgCS,EAAO,WADnD,EAEvB,CAEA,SAASjB,cAAciB,EAASC,GAC9B,OAAKD,EACL,kCAAAT,OAAyCU,EAAG,mCAAAV,OAAkCO,WAAWE,GAAQ,iBAD5E,EAEvB,CAIA,SAASF,WAAWI,GAClB,OAAOA,aAAM,EAANA,EAAQC,QACb,2DACA,SAAAC,GAAC,MAAI,MAAQ,MAAQA,EAAEC,WAAW,IAAIC,OAAO,GAAK,GAAG,GAEzD","file":"../litewebchat_render.min.js","sourcesContent":["const TipsType = {\n tipsNormal: 'tips',\n tipsPrimary: 'tips-primary',\n tipsSuccess: 'tips-success',\n tipsInfo: 'tips-info',\n tipsWarning: 'tips-warning',\n tipsDanger: 'tips-danger',\n};\nconst TitleType = {\n admin: 'admin',\n owner: 'owner',\n};\n\nfunction beforeRenderingHTML(data, chatboxClass) {\n let htmlStr = '';\n let chatBox = document.querySelector(chatboxClass);\n for (let i = 0; i < data.length; i++) {\n if (data[i].isRender) {\n continue;\n }\n if (data[i].messageType.indexOf('tips') !== -1) {\n htmlStr += renderTipHtml(data[i].html, TipsType[data[i].messageType] || 'tips');\n } else {\n htmlStr += renderMessageHtml(data[i]);\n }\n data[i].isRender = true;\n }\n\n chatBox.insertAdjacentHTML('beforeend',htmlStr);\n setTimeout(() => {\n if (chatBox.scrollHeight > chatBox.clientHeight) {\n chatBox.scrollTop = chatBox.scrollHeight;\n chatBox = '';\n htmlStr = '';\n }\n }, 300);\n}\n\nfunction renderMessageHtml(data) {\n return `\n
\n
\n ${renderTitleHtml(data.htitle, TitleType[data.htitleType] || '')}\n ${escapeHtml(data.name) || ' '} \n \n
${data.messageType === 'raw' ? data.html : escapeHtml(data.html)} \n
`;\n}\n\nfunction renderTitleHtml(content, css) {\n if (!content) return '';\n return `${content} `;\n}\n\nfunction renderTipHtml(content, css) {\n if (!content) return '';\n return `${escapeHtml(content)}
`;\n}\n\n// 转义 C0 Controls and Basic Latin 中非数字和字母,C1 Controls and Latin-1 Supplement 全部\n// https://www.w3schools.com/charsets/ref_html_utf8.asp\nfunction escapeHtml(unsafe) {\n return unsafe?.replace(\n /[\\u0000-\\u002F\\u003A-\\u0040\\u005B-\\u0060\\u007B-\\u00FF]/g,\n c => '' + ('000' + c.charCodeAt(0)).slice(-4) + ';'\n )\n}\n"]}
--------------------------------------------------------------------------------
/src/main/resources/templates/chat.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | LiteChat_Frame
8 |
9 |
10 |
11 |
33 |
34 |
35 |
53 |
54 |
55 |
56 |
57 |
67 |
84 |
135 |
136 |
--------------------------------------------------------------------------------
/src/test/java/com/chatweb/WebtapApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.chatweb;
2 |
3 | import static org.assertj.core.api.Assertions.assertThat;
4 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
5 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
6 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
7 |
8 | import java.lang.management.ManagementFactory;
9 |
10 | import javax.management.ObjectName;
11 |
12 | import org.junit.Before;
13 | import org.junit.Test;
14 | import org.junit.runner.RunWith;
15 | import org.springframework.beans.factory.annotation.Autowired;
16 | import org.springframework.boot.test.context.SpringBootTest;
17 | import org.springframework.test.context.ActiveProfiles;
18 | import org.springframework.test.context.TestPropertySource;
19 | import org.springframework.test.context.junit4.SpringRunner;
20 | import org.springframework.test.web.servlet.MockMvc;
21 | import org.springframework.test.web.servlet.setup.MockMvcBuilders;
22 | import org.springframework.web.context.WebApplicationContext;
23 |
24 | @RunWith(SpringRunner.class)
25 | @SpringBootTest
26 | // Enable JMX so we can test the MBeans (you can't do this in a properties file)
27 | @TestPropertySource(properties = { "spring.jmx.enabled:true",
28 | "spring.datasource.jmx-enabled:true" })
29 | @ActiveProfiles("scratch")
30 | public class WebtapApplicationTests {
31 |
32 | @Autowired
33 | private WebApplicationContext context;
34 |
35 | private MockMvc mvc;
36 |
37 | @Before
38 | public void setUp() {
39 | this.mvc = MockMvcBuilders.webAppContextSetup(this.context).build();
40 | }
41 |
42 | @Test
43 | public void testHome() throws Exception {
44 |
45 | this.mvc.perform(get("/")).andExpect(status().isOk())
46 | .andExpect(content().string("Bath"));
47 | }
48 |
49 | @Test
50 | public void testJmx() throws Exception {
51 | assertThat(ManagementFactory.getPlatformMBeanServer()
52 | .queryMBeans(new ObjectName("jpa.sample:type=ConnectionPool,*"), null))
53 | .hasSize(1);
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/test/resources/application-scratch.properties:
--------------------------------------------------------------------------------
1 | spring.datasource.name=scratchdb
2 | spring.jmx.default-domain=jpa.sample
3 |
4 |
--------------------------------------------------------------------------------
/start.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | echo "--- begin start server ---"
4 |
5 | # start server
6 | nohup java -server -Xms512m -Xmx512m -Xss512K -jar chatweb-1.0.jar>/dev/null 2>&1&
7 |
--------------------------------------------------------------------------------
/stop.sh:
--------------------------------------------------------------------------------
1 | serviceName="chatweb-1.0.jar"
2 |
3 | ps -efww|grep -w "$serviceName"|grep -v grep|cut -c 9-15|xargs kill -9|| exit 0
4 |
--------------------------------------------------------------------------------