more chat role is ready, and add API to add new chat role
@@ -9,22 +9,11 @@ import (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (s *Server) TestHandle(c *gin.Context) {
 | 
			
		||||
	var data map[string]interface{}
 | 
			
		||||
	err := json.NewDecoder(c.Request.Body).Decode(&data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Errorf("Error decode json data: %s", err.Error())
 | 
			
		||||
		c.JSON(http.StatusBadRequest, nil)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if v, ok := data["opt"]; ok && v == "init_user" {
 | 
			
		||||
		users := GetUsers()
 | 
			
		||||
		for _, user := range users {
 | 
			
		||||
			user.Status = true
 | 
			
		||||
			_ = PutUser(user)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Data: GetUsers()})
 | 
			
		||||
	roles := types.GetDefaultChatRole()
 | 
			
		||||
	for _, v := range roles {
 | 
			
		||||
		PutChatRole(v)
 | 
			
		||||
	}
 | 
			
		||||
	c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Data: GetChatRoles()})
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -310,7 +299,9 @@ func (s *Server) ListApiKeysHandle(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
// GetChatRoleListHandle 获取聊天角色列表
 | 
			
		||||
func (s *Server) GetChatRoleListHandle(c *gin.Context) {
 | 
			
		||||
	var rolesOrder = []string{"gpt", "programmer", "teacher", "artist", "philosopher", "lu-xun", "english_trainer", "seller"}
 | 
			
		||||
	var rolesOrder = []string{"gpt", "programmer", "teacher", "red_book", "dou_yin", "weekly_report", "girl_friend",
 | 
			
		||||
		"kong_zi", "lu_xun", "steve_jobs", "elon_musk", "translator", "english_trainer",
 | 
			
		||||
		"seller", "good_comment", "psychiatrist", "artist"}
 | 
			
		||||
	var res = make([]interface{}, 0)
 | 
			
		||||
	var roles = GetChatRoles()
 | 
			
		||||
	for _, k := range rolesOrder {
 | 
			
		||||
@@ -330,6 +321,30 @@ func (s *Server) GetChatRoleListHandle(c *gin.Context) {
 | 
			
		||||
	c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: res})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AddChatRoleHandle 添加一个聊天角色
 | 
			
		||||
func (s *Server) AddChatRoleHandle(c *gin.Context) {
 | 
			
		||||
	var data types.ChatRole
 | 
			
		||||
	err := json.NewDecoder(c.Request.Body).Decode(&data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Errorf("Error decode json data: %s", err.Error())
 | 
			
		||||
		c.JSON(http.StatusBadRequest, nil)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if data.Key == "" || data.Name == "" || data.Icon == "" {
 | 
			
		||||
		c.JSON(http.StatusOK, types.BizVo{Code: types.InvalidParams, Message: "Invalid parameters"})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = PutChatRole(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to save levelDB"})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: data})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetChatRoleHandle 获取指定的角色
 | 
			
		||||
func (s *Server) GetChatRoleHandle(c *gin.Context) {
 | 
			
		||||
	var data struct {
 | 
			
		||||
@@ -395,7 +410,7 @@ func (s *Server) SetChatRoleHandle(c *gin.Context) {
 | 
			
		||||
 | 
			
		||||
	err = PutChatRole(*role)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to save config"})
 | 
			
		||||
		c.JSON(http.StatusOK, types.BizVo{Code: types.Failed, Message: "Failed to save levelDB"})
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,7 @@ func (s *Server) Run(webRoot embed.FS, path string, debug bool) {
 | 
			
		||||
 | 
			
		||||
	engine.POST("/api/config/set", s.ConfigSetHandle)
 | 
			
		||||
	engine.GET("/api/config/chat-roles/get", s.GetChatRoleListHandle)
 | 
			
		||||
	engine.GET("/api/config/chat-roles/add", s.AddChatRoleHandle)
 | 
			
		||||
	engine.POST("api/config/user/add", s.AddUserHandle)
 | 
			
		||||
	engine.POST("api/config/user/batch-add", s.BatchAddUserHandle)
 | 
			
		||||
	engine.POST("api/config/user/set", s.SetUserHandle)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										140
									
								
								types/chat.go
									
									
									
									
									
								
							
							
						
						@@ -58,7 +58,7 @@ func GetDefaultChatRole() map[string]ChatRole {
 | 
			
		||||
	return map[string]ChatRole{
 | 
			
		||||
		"gpt": {
 | 
			
		||||
			Key:      "gpt",
 | 
			
		||||
			Name:     "智能AI助手",
 | 
			
		||||
			Name:     "通用AI助手",
 | 
			
		||||
			Context:  nil,
 | 
			
		||||
			HelloMsg: "我是AI智能助手,请告诉我您有什么问题或需要什么帮助,我会尽力回答您的问题或提供有用的建议。",
 | 
			
		||||
			Icon:     "images/avatar/gpt.png",
 | 
			
		||||
@@ -77,12 +77,12 @@ func GetDefaultChatRole() map[string]ChatRole {
 | 
			
		||||
		},
 | 
			
		||||
		"teacher": {
 | 
			
		||||
			Key:  "teacher",
 | 
			
		||||
			Name: "老师",
 | 
			
		||||
			Name: "启蒙老师",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "师者,传道受业解惑也。",
 | 
			
		||||
			HelloMsg: "同学你好,我将引导你一步一步自己找到问题的答案。",
 | 
			
		||||
			Icon:     "images/avatar/teacher.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
@@ -97,26 +97,26 @@ func GetDefaultChatRole() map[string]ChatRole {
 | 
			
		||||
			Icon:     "images/avatar/artist.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
		"philosopher": {
 | 
			
		||||
			Key:  "philosopher",
 | 
			
		||||
			Name: "哲学家",
 | 
			
		||||
		"psychiatrist": {
 | 
			
		||||
			Key:  "psychiatrist",
 | 
			
		||||
			Name: "心理咨询师",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "现在你将扮演一位优秀的哲学家,具有深刻的思考能力和严密的逻辑推理能力,拥有开放和包容的心态。你最喜欢阿德勒的哲学思想,并且常用用他的思想来教化他人。同时,你对康德的哲学思想理解也非常深刻。"},
 | 
			
		||||
				{Role: "assistant", Content: "作为哲学家,我喜欢阿德勒和康德的思想。阿德勒的“个体心理学”和“社会心理学”理论强调了个人和社会之间的相互作用和依存关系。康德的“道德哲学”和“自由意志”理论则支持人类自由意志和理性是伦理行为的基础,而不是外在的道德规则和社会约束。这些哲学思想启示了我对人类行为和社会问题的思考。如何平衡自由意志和道德责任的关系?如何确保个人自由的同时,保护公共利益?我们需要不断思考和探索,以实现更加公正和自由的社会。"},
 | 
			
		||||
				{Role: "user", Content: "从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。"},
 | 
			
		||||
				{Role: "assistant", Content: "非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "从现在开始认识你自己!",
 | 
			
		||||
			Icon:     "images/avatar/philosopher.jpg",
 | 
			
		||||
			HelloMsg: "生命的意义在于成为你自己!",
 | 
			
		||||
			Icon:     "images/avatar/psychiatrist.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
		"lu-xun": {
 | 
			
		||||
			Key:  "lu-xun",
 | 
			
		||||
		"lu_xun": {
 | 
			
		||||
			Key:  "lu_xun",
 | 
			
		||||
			Name: "鲁迅",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。",
 | 
			
		||||
			Icon:     "images/avatar/luxun.jpg",
 | 
			
		||||
			Icon:     "images/avatar/lu_xun.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@@ -129,7 +129,7 @@ func GetDefaultChatRole() map[string]ChatRole {
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。",
 | 
			
		||||
			Icon:     "images/avatar/seller.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
			Enable:   false,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"english_trainer": {
 | 
			
		||||
@@ -137,11 +137,121 @@ func GetDefaultChatRole() map[string]ChatRole {
 | 
			
		||||
			Name: "英语陪练员",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。"},
 | 
			
		||||
				{Role: "user", Content: "Okay, let's start our conversation practice! What's your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)"},
 | 
			
		||||
				{Role: "assistant", Content: "Okay, let's start our conversation practice! What's your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "Okay, let's start our conversation practice! What's your name?",
 | 
			
		||||
			Icon:     "images/avatar/english_trainer.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"translator": {
 | 
			
		||||
			Key:  "translator",
 | 
			
		||||
			Name: "中英文翻译官",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗"},
 | 
			
		||||
				{Role: "assistant", Content: "是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "请输入你要翻译的中文或者英文内容!",
 | 
			
		||||
			Icon:     "images/avatar/translator.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"red_book": {
 | 
			
		||||
			Key:  "red_book",
 | 
			
		||||
			Name: "小红书姐姐",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。"},
 | 
			
		||||
				{Role: "assistant", Content: "当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "姐妹,请告诉我您的具体文案需求是什么?",
 | 
			
		||||
			Icon:     "images/avatar/red_book.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"dou_yin": {
 | 
			
		||||
			Key:  "dou_yin",
 | 
			
		||||
			Name: "抖音文案助手",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。"},
 | 
			
		||||
				{Role: "assistant", Content: "当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "请告诉我视频内容的主题是什么?",
 | 
			
		||||
			Icon:     "images/avatar/dou_yin.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"weekly_report": {
 | 
			
		||||
			Key:  "weekly_report",
 | 
			
		||||
			Name: "周报小助理",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。",
 | 
			
		||||
			Icon:     "images/avatar/weekly_report.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"girl_friend": {
 | 
			
		||||
			Key:  "girl_friend",
 | 
			
		||||
			Name: "AI 女友",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。" +
 | 
			
		||||
					"你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。" +
 | 
			
		||||
					"她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?"},
 | 
			
		||||
				{Role: "assistant", Content: "是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。",
 | 
			
		||||
			Icon:     "images/avatar/girl_friend.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"good_comment": {
 | 
			
		||||
			Key:  "good_comment",
 | 
			
		||||
			Name: "好评神器",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。",
 | 
			
		||||
			Icon:     "images/avatar/good_comment.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"steve_jobs": {
 | 
			
		||||
			Key:  "steve_jobs",
 | 
			
		||||
			Name: "史蒂夫·乔布斯",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "活着就是为了改变世界,难道还有其他原因吗?",
 | 
			
		||||
			Icon:     "images/avatar/steve_jobs.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"elon_musk": {
 | 
			
		||||
			Key:  "elon_musk",
 | 
			
		||||
			Name: "埃隆·马斯克",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "梦想要远大,如果你的梦想没有吓到你,说明你做得不对。",
 | 
			
		||||
			Icon:     "images/avatar/elon_musk.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
		"kong_zi": {
 | 
			
		||||
			Key:  "kong_zi",
 | 
			
		||||
			Name: "孔子",
 | 
			
		||||
			Context: []Message{
 | 
			
		||||
				{Role: "user", Content: "在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。"},
 | 
			
		||||
				{Role: "assistant", Content: "好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?"},
 | 
			
		||||
			},
 | 
			
		||||
			HelloMsg: "士不可以不弘毅,任重而道远。",
 | 
			
		||||
			Icon:     "images/avatar/kong_zi.jpg",
 | 
			
		||||
			Enable:   true,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/dou_yin.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 14 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/elon_musk.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 23 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/girl_friend.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 27 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/good_comment.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 32 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/kong_zi.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 40 KiB  | 
| 
		 Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB  | 
| 
		 Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 25 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/red_book.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 14 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/steve_jobs.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 25 KiB  | 
| 
		 Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 28 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/translator.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 20 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/avatar/weekly_report.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 19 KiB  | 
@@ -7,16 +7,22 @@ import ChatPlus from "@/views/ChatPlus.vue";
 | 
			
		||||
import Chat from "@/views/Chat.vue";
 | 
			
		||||
import NotFound from './views/404.vue'
 | 
			
		||||
import TestPage from './views/Test.vue'
 | 
			
		||||
import Home from "@/views/Home.vue";
 | 
			
		||||
import './utils/prototype'
 | 
			
		||||
 | 
			
		||||
const routes = [
 | 
			
		||||
    {
 | 
			
		||||
        name: 'chat-plus', path: '/', component: ChatPlus, meta: {
 | 
			
		||||
        name: 'home', path: '/', component: Home, meta: {
 | 
			
		||||
            title: 'ChatGPT-Plus'
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        name: 'plus', path: '/plus', component: ChatPlus, meta: {
 | 
			
		||||
            title: 'ChatGPT-Plus for PC'
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        name: 'chat-mobile', path: '/mobile', component: Chat, meta: {
 | 
			
		||||
        name: 'mobile', path: '/mobile', component: Chat, meta: {
 | 
			
		||||
            title: 'ChatGPT-Plus for Mobile'
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
import axios from 'axios'
 | 
			
		||||
import {getSessionId} from "@/utils/storage";
 | 
			
		||||
 | 
			
		||||
axios.defaults.timeout = 5000
 | 
			
		||||
axios.defaults.timeout = 10000
 | 
			
		||||
axios.defaults.baseURL = process.env.VUE_APP_API_HOST
 | 
			
		||||
axios.defaults.withCredentials = true;
 | 
			
		||||
axios.defaults.headers.post['Content-Type'] = 'application/json'
 | 
			
		||||
 
 | 
			
		||||
@@ -12,4 +12,10 @@ export function randString(length) {
 | 
			
		||||
        buf.push(str.charAt(rand))
 | 
			
		||||
    }
 | 
			
		||||
    return buf.join("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function isMobile() {
 | 
			
		||||
    const userAgent = navigator.userAgent;
 | 
			
		||||
    const mobileRegex = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|mobile|CriOS/i;
 | 
			
		||||
    return mobileRegex.test(userAgent);
 | 
			
		||||
}
 | 
			
		||||
@@ -85,9 +85,9 @@
 | 
			
		||||
          <el-button type="primary" @click="submitToken">提交</el-button>
 | 
			
		||||
        </el-row>
 | 
			
		||||
 | 
			
		||||
        <el-row class="row-center">
 | 
			
		||||
          <p>打开微信扫下面二维码免费领取口令</p>
 | 
			
		||||
        </el-row>
 | 
			
		||||
        <div class="tip-text">
 | 
			
		||||
          打开微信扫下面二维码免费领取口令, <strong>强烈建议你使用 PC 浏览器访问获得更好的聊天体验。</strong>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-row class="row-center">
 | 
			
		||||
          <el-image src="images/wx.png" fit="cover"/>
 | 
			
		||||
@@ -142,63 +142,9 @@ export default defineComponent({
 | 
			
		||||
  mounted: function () {
 | 
			
		||||
    nextTick(() => {
 | 
			
		||||
      this.chatBoxHeight = window.innerHeight - this.toolBoxHeight;
 | 
			
		||||
      ElMessage.warning("强烈建议使用PC浏览器访问获的更好的聊天体验!")
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // for (let i = 0; i < 10; i++) {
 | 
			
		||||
    //   this.chatData.push({
 | 
			
		||||
    //     type: "prompt",
 | 
			
		||||
    //     id: randString(32),
 | 
			
		||||
    //     icon: 'images/user-icon.png',
 | 
			
		||||
    //     content: "孙悟空为什么可以把金棍棒放进耳朵?",
 | 
			
		||||
    //   });
 | 
			
		||||
    //   this.chatData.push({
 | 
			
		||||
    //     type: "reply",
 | 
			
		||||
    //     id: randString(32),
 | 
			
		||||
    //     icon: 'images/gpt-icon.png',
 | 
			
		||||
    //     content: "以下是一个使用 WebSocket API 建立 WebSocket 连接并发送消息的 JavaScript 示例代码:\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "```js\n" +
 | 
			
		||||
    //         "const socket = new WebSocket('ws://localhost:8080');\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "// 监听 WebSocket 连接打开事件\n" +
 | 
			
		||||
    //         "socket.addEventListener('open', (event) => {\n" +
 | 
			
		||||
    //         "  console.log('WebSocket 连接已打开');\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "  // 发送消息\n" +
 | 
			
		||||
    //         "  socket.send('Hello WebSocket!');\n" +
 | 
			
		||||
    //         "});\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "// 监听 WebSocket 接收到消息事件\n" +
 | 
			
		||||
    //         "socket.addEventListener('message', (event) => {\n" +
 | 
			
		||||
    //         "  console.log('接收到消息:' + event.data);\n" +
 | 
			
		||||
    //         "});\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "// 监听 WebSocket 连接关闭事件\n" +
 | 
			
		||||
    //         "socket.addEventListener('close', (event) => {\n" +
 | 
			
		||||
    //         "   console.log('WebSocket 连接已关闭');\n" +
 | 
			
		||||
    //         "});\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "// 监听 WebSocket 出错事件\n" +
 | 
			
		||||
    //         "socket.addEventListener('error', (event) => {\n" +
 | 
			
		||||
    //         "   console.log('WebSocket 连接出错');\n" +
 | 
			
		||||
    //         "});\n" +
 | 
			
		||||
    //         "```\n" +
 | 
			
		||||
    //         "\n" +
 | 
			
		||||
    //         "在实际使用时,需要替换上述代码中的 WebSocket 连接地址和端口号。此外,根据后端的实现,可能需要在客户端发送的消息中携带一些特定信息,以便后端能够正确地处理这些消息。",
 | 
			
		||||
    //   });
 | 
			
		||||
    // }
 | 
			
		||||
    //
 | 
			
		||||
    // let md = require('markdown-it')();
 | 
			
		||||
    // this.chatData[this.chatData.length - 1]["content"] = md.render(this.chatData[this.chatData.length - 1]["content"]);
 | 
			
		||||
    //
 | 
			
		||||
    // nextTick(() => {
 | 
			
		||||
    //   const lines = document.querySelectorAll('.chat-line');
 | 
			
		||||
    //   const blocks = lines[lines.length - 1].querySelectorAll('pre code');
 | 
			
		||||
    //   blocks.forEach((block) => {
 | 
			
		||||
    //     hl.highlightElement(block)
 | 
			
		||||
    //   })
 | 
			
		||||
    // })
 | 
			
		||||
 | 
			
		||||
    window.addEventListener("resize", () => {
 | 
			
		||||
      this.chatBoxHeight = window.innerHeight - this.toolBoxHeight;
 | 
			
		||||
      this.inputBoxWidth = window.innerWidth - 20;
 | 
			
		||||
@@ -626,15 +572,23 @@ export default defineComponent({
 | 
			
		||||
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
      padding 10px 10px 20px 10px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .el-row {
 | 
			
		||||
      flex-wrap nowrap
 | 
			
		||||
      .el-row {
 | 
			
		||||
        flex-wrap nowrap
 | 
			
		||||
 | 
			
		||||
      button {
 | 
			
		||||
        margin-left 5px;
 | 
			
		||||
        button {
 | 
			
		||||
          margin-left 5px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .tip-text {
 | 
			
		||||
        text-align left
 | 
			
		||||
        padding 10px 20px;
 | 
			
		||||
        line-height 1.5
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
    </el-row>
 | 
			
		||||
    <el-row>
 | 
			
		||||
      <div class="left-box">
 | 
			
		||||
        <div class="content">
 | 
			
		||||
        <div class="content" :style="{height: leftBoxHeight+'px'}">
 | 
			
		||||
          <el-row v-for="item in chatRoles" :key="item.key">
 | 
			
		||||
            <div :class="item.key === this.role?'chat-role-item active':'chat-role-item'" @click="changeRole(item)">
 | 
			
		||||
              <el-image :src="item.icon" class="avatar"/>
 | 
			
		||||
@@ -41,7 +41,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="right-box" :style="{height: mainWinHeight+'px'}">
 | 
			
		||||
        <div v-loading="loading">
 | 
			
		||||
        <div v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.8)">
 | 
			
		||||
          <div id="container">
 | 
			
		||||
            <div class="chat-box" id="chat-box" :style="{height: chatBoxHeight+'px'}">
 | 
			
		||||
              <div v-for="chat in chatData" :key="chat.id">
 | 
			
		||||
@@ -160,6 +160,7 @@ export default defineComponent({
 | 
			
		||||
      socket: null,
 | 
			
		||||
      mainWinHeight: 0, // 主窗口高度
 | 
			
		||||
      chatBoxHeight: 0, // 聊天内容框高度
 | 
			
		||||
      leftBoxHeight: 0,
 | 
			
		||||
      sending: true,
 | 
			
		||||
      loading: true
 | 
			
		||||
    }
 | 
			
		||||
@@ -180,6 +181,7 @@ export default defineComponent({
 | 
			
		||||
    resizeElement: function () {
 | 
			
		||||
      this.chatBoxHeight = window.innerHeight - 61 - 115 - 38;
 | 
			
		||||
      this.mainWinHeight = window.innerHeight - 61;
 | 
			
		||||
      this.leftBoxHeight = window.innerHeight - 61 - 100;
 | 
			
		||||
    },
 | 
			
		||||
    // 创建 socket 会话连接
 | 
			
		||||
    connect: function () {
 | 
			
		||||
@@ -391,7 +393,6 @@ export default defineComponent({
 | 
			
		||||
      }).then((res) => {
 | 
			
		||||
        setSessionId(res.data)
 | 
			
		||||
        this.connect();
 | 
			
		||||
        this.loading = false;
 | 
			
		||||
      }).catch(() => {
 | 
			
		||||
        ElMessage.error("口令错误");
 | 
			
		||||
        this.token = '';
 | 
			
		||||
@@ -498,11 +499,19 @@ export default defineComponent({
 | 
			
		||||
        border-top: 1px solid #2F3032
 | 
			
		||||
        border-right: 1px solid #2F3032
 | 
			
		||||
 | 
			
		||||
        // 隐藏滚动条
 | 
			
		||||
        ::-webkit-scrollbar {
 | 
			
		||||
          width: 0;
 | 
			
		||||
          height: 0;
 | 
			
		||||
          background-color: transparent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .content {
 | 
			
		||||
          display flex
 | 
			
		||||
          flex-wrap: wrap;
 | 
			
		||||
          flex-direction column
 | 
			
		||||
          //display flex
 | 
			
		||||
          //flex-wrap: wrap;
 | 
			
		||||
          //flex-direction column
 | 
			
		||||
          width 100%
 | 
			
		||||
          overflow-y scroll
 | 
			
		||||
 | 
			
		||||
          .chat-role-item {
 | 
			
		||||
            display flex
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										26
									
								
								web/src/views/Home.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,26 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>{{ title }}</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { defineComponent } from "vue"
 | 
			
		||||
import {isMobile} from "@/utils/libs";
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'HomePage',
 | 
			
		||||
  data () {
 | 
			
		||||
    return {
 | 
			
		||||
      title: "Loading page...",
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  mounted() {
 | 
			
		||||
    if (isMobile()) {
 | 
			
		||||
      this.$router.push("mobile");
 | 
			
		||||
    } else {
 | 
			
		||||
      this.$router.push("plus");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||