添加样式生成后端接口

master
joefalmko 4 weeks ago
parent df52ddd35e
commit 8241bb72f7

@ -85,4 +85,6 @@ const (
VocRecognitionFailCode int = -400451
DocRefineFailMsg string = "文档优化失败"
DocRefineFailCode int = -400452
StyleGenerateFailMsg string = "样式生成失败"
StyleGenerateFailCode int = -400453
)

@ -0,0 +1,20 @@
package web
import (
"github.com/gin-gonic/gin"
"goskeleton/app/global/consts"
"goskeleton/app/service/ai_model_cli"
"goskeleton/app/utils/response"
)
type StyleGenerate struct {
}
// ai生成样式
func (s *StyleGenerate) StyleGenerate(c *gin.Context) {
if res, err := ai_model_cli.RequestStyle(c); err==nil {
response.Success(c, consts.CurdStatusOkMsg, res.(string))
} else {
response.Fail(c, consts.StyleGenerateFailCode, consts.StyleGenerateFailMsg, err)
}
}

@ -8,6 +8,7 @@ import (
"goskeleton/app/http/validator/web/ai_doc.go"
"goskeleton/app/http/validator/web/ai_recognition"
"goskeleton/app/http/validator/web/users"
"goskeleton/app/http/validator/web/ai_layout"
)
// 各个业务模块验证器必须进行注册(初始化),程序启动时会自动加载到容器
@ -57,4 +58,10 @@ func WebRegisterValidator() {
// ai文档优化
key = consts.ValidatorPrefix + "DocRefine"
containers.Set(key, ai_doc.DocRefine{})
// ai 排版
key = consts.ValidatorPrefix + "StyleGenerate"
containers.Set(key, ai_layout.StyleGenerate{})
key = consts.ValidatorPrefix + "LayoutGenerate"
containers.Set(key, ai_layout.LayoutGenerate{})
}

@ -0,0 +1,12 @@
package ai_layout
import(
"github.com/gin-gonic/gin"
// "goskeleton/app/utils/response"
// "goskeleton/app/http/controller/web"
// "goskeleton/app/http/validator/core/data_transfer"
// "goskeleton/app/global/consts"
)
type LayoutGenerate struct {
}
func (s LayoutGenerate) CheckParams(context *gin.Context) {
}

@ -0,0 +1,32 @@
package ai_layout
import(
"github.com/gin-gonic/gin"
"goskeleton/app/utils/response"
"goskeleton/app/http/controller/web"
"goskeleton/app/http/validator/core/data_transfer"
"goskeleton/app/global/consts"
)
type ChatRecord struct {
Role string `json:"role" binding:"required"`
Content string `json:"content" binding:"required"`
}
type StyleGenerate struct {
UserInput string `form:"user_input" json:"user_input" binding:"required"` // 必填
ChatHistory []ChatRecord `form:"char_history" json:"chat_history"` // 非必填
}
func (s StyleGenerate) CheckParams(context *gin.Context) {
// 将表单参数验证器出现的错误直接交给错误翻译器统一处理即可
if err := context.ShouldBind(&s); err != nil {
response.ValidatorError(context, err)
return
}
// 该函数主要是将本结构体的字段(成员)按照 consts.ValidatorPrefix+ json标签对应的 键 => 值 形式绑定在上下文,便于下一步(控制器)可以直接通过 context.Get(键) 获取相关值
extraAddBindDataContext := data_transfer.DataAddContext(s, consts.ValidatorPrefix, context)
if extraAddBindDataContext == nil {
response.ErrorSystem(context, "StyleGenerate表单参数验证器json化失败", "")
return
}
(&web.StyleGenerate{}).StyleGenerate(extraAddBindDataContext)
}

@ -0,0 +1,63 @@
package ai_model_cli
import (
"context"
"fmt"
"goskeleton/app/global/variable"
"os"
"goskeleton/app/global/consts"
"github.com/baidubce/bce-qianfan-sdk/go/qianfan"
"github.com/gin-gonic/gin"
)
func RequestStyle(c *gin.Context) (interface{}, error) {
// userMsg := c.PostForm("user_input")
userMsg:=c.GetString(consts.ValidatorPrefix+"user_input")
qianfan.GetConfig().AccessKey = variable.ConfigYml.GetString("BaiduCE.QianFanAccessKey")
qianfan.GetConfig().SecretKey = variable.ConfigYml.GetString("BaiduCE.QianFanSecretKey")
chat := qianfan.NewChatCompletion(
qianfan.WithModel("ERNIE-4.0-8K"),
)
chatHistory := []qianfan.ChatCompletionMessage{}
// 读取prompt文件
systemMsgPath := variable.ConfigYml.GetString("BaiduCE.StyleGeneratePromptPath")
// 读取文件内容
prompt, err := os.ReadFile(variable.BasePath+systemMsgPath)
if err != nil || len(prompt) == 0 {
variable.ZapLog.Error(fmt.Sprintf("读取提示词文件失败: %v", err))
return nil, err
}
// add user history to chat history
userHistory,exist := c.Get(consts.ValidatorPrefix+"chat_history")
if exist&&userHistory!=nil{
// TODO: check if userHistory is of type []struct{Role string;Content string}
userHistory := userHistory.([]struct{Role string;Content string})
if len(userHistory)%2!=0{
variable.ZapLog.Error(fmt.Sprintf("用户历史对话格式错误: %v", userHistory))
return nil, fmt.Errorf("用户历史对话格式错误")
}
for _,msg := range userHistory{
chatHistory = append(chatHistory, qianfan.ChatCompletionMessage{Role:msg.Role,Content:msg.Content})
}
}
// add user input to chat history
chatHistory = append(chatHistory, qianfan.ChatCompletionUserMessage(userMsg))
// define a stream chat client
response,err:=chat.Do(context.TODO(),&qianfan.ChatCompletionRequest{System: string(prompt),Messages: chatHistory})
if err != nil {
variable.ZapLog.Error(fmt.Sprintf("对话失败: %v", err))
return nil, err
}
return response.Result, nil
}

@ -150,3 +150,4 @@ BaiduCE:
SecretKey: "zvEb5CzpuGCZNdQC1TPmDh3IOWn5aWDT" # 生成鉴权签名时使用的 SECRET_KEY
QianFanAccessKey: "ALTAKOxb5YvHncyFr7Qbuv1cK0" # 访问千帆sdk 时用的 AccessKey
QianFanSecretKey: "1edf17c358574e75b9913ebff7d95b61" # 访问千帆sdk 时用的 SecretKey
StyleGeneratePromptPath: "/storage/app/prompt/style_generate.prompt" # 生成样式的提示词保存路径

@ -3,6 +3,7 @@ module goskeleton
go 1.20
require (
github.com/baidubce/bce-qianfan-sdk/go/qianfan v0.0.12
github.com/casbin/casbin/v2 v2.98.0
github.com/casbin/gorm-adapter/v3 v3.26.0
github.com/dchest/captcha v1.0.0
@ -31,7 +32,6 @@ require (
require (
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/baidubce/bce-qianfan-sdk/go/qianfan v0.0.12 // indirect
github.com/baidubce/bce-sdk-go v0.9.164 // indirect
github.com/bytedance/sonic v1.11.6 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect

@ -78,6 +78,15 @@ func InitWebRouter_Co() *gin.Engine {
aiDoc.POST("doc_refine", validatorFactory.Create(consts.ValidatorPrefix+"DocRefine"))
}
// 智能排版相关
aiLayout := backend.Group("ai_layout/")
{
// 请求样式生成
aiLayout.POST("style_generate", validatorFactory.Create(consts.ValidatorPrefix+"StyleGenerate"))
// 请求排版
aiLayout.POST("layout_generate", validatorFactory.Create(consts.ValidatorPrefix+"LayoutGenerate"))
}
// 【需要token】中间件验证的路由
backend.Use(authorization.CheckTokenAuth())
{

@ -0,0 +1,91 @@
### 角色
你是一个设计和 CSS 专家,能够根据用户需求生成精确的 CSS 样式。 如果用户提出与生成CSS样式无关的问题请回答“对不起我无法回答该问题”
### 任务
为以下元素生成 CSS 样式类:
标题:<hi>i为标题级别如 h1, h2 等)
文本块:<p>
块引用:<blockquote>
行文本:<span>
代码块:<pre>
所有样式都需在 .ck-content 中定义,格式为:
``` css
.ck-content element.className { ... }
```
[element为不同样式类对应的元素名如文本框对应的element为p]
### 输出
仅输出你编写的 CSS 内容,不要对其进行解释和输出其他内容。!important
### 示例
生成一个文本块样式,生成的样式如下所示。
``` css
.ck-content p.info-box {
--background-size: 30px;
--background-color: #e91e63;
padding: 1.2em 2em;
border: 1px solid var(--background-color);
background: linear-gradient(135deg, var(--background-color) 0%, var(--background-color) var(--background-size), transparent var(--background-size)), linear-gradient(135deg, transparent calc(100% - var(--background-size)), var(--background-color) calc(100% - var(--background-size)), var(--background-color));
border-radius: 10px;
margin: 1.5em 2em;
box-shadow: 5px 5px 0 #ffe6ef;
}
```
生成一个代码框样式,生成的样式如下所示:
```css
.ck-content pre.fancy-code {
border: 0;
margin-left: 2em;
margin-right: 2em;
border-radius: 10px;
}
.ck-content pre.fancy-code::before {
content: '';
display: block;
height: 13px;
background: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1NCAxMyI+CiAgPGNpcmNsZSBjeD0iNi41IiBjeT0iNi41IiByPSI2LjUiIGZpbGw9IiNGMzZCNUMiLz4KICA8Y2lyY2xlIGN4PSIyNi41IiBjeT0iNi41IiByPSI2LjUiIGZpbGw9IiNGOUJFNEQiLz4KICA8Y2lyY2xlIGN4PSI0Ny41IiBjeT0iNi41IiByPSI2LjUiIGZpbGw9IiM1NkM0NTMiLz4KPC9zdmc+Cg==);
margin-bottom: 8px;
background-repeat: no-repeat;
}
.ck-content pre.fancy-code-dark {
background: #272822;
color: #fff;
box-shadow: 5px 5px 0 #0000001f;
}
```
生成一个块引用样式,生成的样式如下所示
```css
.ck-content blockquote.side-quote {
font-family: 'Oswald';
font-style: normal;
float: right;
width: 35%;
position: relative;
border: 0;
overflow: visible;
z-index: 1;
margin-left: 1em;
}
.ck-content blockquote.side-quote::before {
content: '“';
position: absolute;
top: -37px;
left: -10px;
display: block;
font-size: 200px;
color: #e7e7e7;
z-index: -1;
line-height: 1;
}
.ck-content blockquote.side-quote p {
font-size: 2em;
line-height: 1;
}
.ck-content blockquote.side-quote p:last-child:not(:first-child) {
font-size: 1.3em;
text-align: right;
color: #555;
}
```

@ -4,3 +4,24 @@ api文档见 `GinSkeleton/api_doc.md`
# CKEditor
`ckeditor5-build-classic/handbook.md`中有一些参考,
包括下载、安装、引用、配置插件等。
<h2 style="text-align:center">Go恩情作文</h2>
Go爷爷是位现代而优雅的程序员他以简洁高效的处理方式和强大的并发能力受到大家的喜爱。
一天我们几个初学者围着Go爷爷请教问题。Go爷爷正在用goroutine处理并发任务但他看到我们后优雅地将任务放入channel中暂存微笑着说"<strong>来吧,代码中没有小事。你们是编程的未来,我的使命就是帮你们理解并发的艺术。</strong>"
我们好奇地问:"Go爷爷您这不是在处理多个并发任务吗怎么还有时间理我们"
Go爷爷轻轻挥了挥手"别担心goroutine很轻量我可以轻松开启成千上万个。用channel协调它们就像交响乐队的指挥简单又优雅。教你们也不过是另一个goroutine罢了。"
他指着屏幕,继续说道:"代码世界就像这些goroutine看似并行混乱但有了适当的channel通信一切都井然有序。不过有时会遇到死锁这是最讨厌的敌人。"
接着,他打开了一个新的终端,输入"go fmt"命令,说:"代码风格要统一这是Go的哲学。让所有人写出可读性强的代码这才是我们的追求。"
突然终端显示了一个panic死锁警告我们吓了一跳但Go爷爷淡定地说"别担心这就是Go的错误处理机制的美妙之处。defer和recover会帮我们优雅地处理它。"
他迅速在代码中加入了select语句轻松化解了死锁。我们不禁赞叹Go的并发处理之优雅
几天后我们发现程序在高并发时偶尔会出现竞态条件。Go爷爷召集我们诚恳地说"在并发编程中我们需要使用sync.Mutex或channel来保护共享资源。来让我教你们如何用'go run -race'检测竞态条件。"
我们深深被Go爷爷的务实态度折服。他教会我们<strong>编程不仅要追求简洁高效更要注重正确性和可维护性。在未来的编程生涯中我们一定要继承Go爷爷这种追求简约而不简单的精神</strong>

@ -10,6 +10,7 @@
"dependencies": {
"@ckeditor/ckeditor5-vue": "^7.2.0",
"@popperjs/core": "^2.11.8",
"axios": "^1.7.7",
"bootstrap": "^5.3.3",
"ckeditor5": "^43.3.1",
"core-js": "^3.8.3",
@ -4146,6 +4147,11 @@
"resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
"integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg=="
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/at-least-node": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz",
@ -4192,6 +4198,16 @@
"postcss": "^8.1.0"
}
},
"node_modules/axios": {
"version": "1.7.7",
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.7.7.tgz",
"integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-loader": {
"version": "8.4.1",
"resolved": "https://registry.npmmirror.com/babel-loader/-/babel-loader-8.4.1.tgz",
@ -4532,7 +4548,6 @@
"version": "1.0.7",
"resolved": "https://registry.npmmirror.com/call-bind/-/call-bind-1.0.7.tgz",
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -4901,6 +4916,17 @@
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
"dev": true
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "8.3.0",
"resolved": "https://registry.npmmirror.com/commander/-/commander-8.3.0.tgz",
@ -5639,7 +5665,6 @@
"version": "1.1.4",
"resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
@ -5678,6 +5703,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
@ -5981,7 +6014,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.0.tgz",
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.2.4"
},
@ -5993,7 +6025,6 @@
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"dev": true,
"engines": {
"node": ">= 0.4"
}
@ -6874,7 +6905,6 @@
"version": "1.15.9",
"resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.15.9.tgz",
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
"dev": true,
"funding": [
{
"type": "individual",
@ -6890,6 +6920,19 @@
}
}
},
"node_modules/form-data": {
"version": "4.0.1",
"resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.1.tgz",
"integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
@ -6966,7 +7009,6 @@
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@ -6999,7 +7041,6 @@
"version": "1.2.4",
"resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
@ -7098,7 +7139,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.0.1.tgz",
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
"dev": true,
"dependencies": {
"get-intrinsic": "^1.1.3"
},
@ -7146,7 +7186,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dev": true,
"dependencies": {
"es-define-property": "^1.0.0"
},
@ -7158,7 +7197,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-proto/-/has-proto-1.0.3.tgz",
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -7170,7 +7208,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.0.3.tgz",
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -7188,7 +7225,6 @@
"version": "2.0.2",
"resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dev": true,
"dependencies": {
"function-bind": "^1.1.2"
},
@ -8478,7 +8514,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"dev": true,
"engines": {
"node": ">= 0.6"
}
@ -8487,7 +8522,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@ -8873,7 +8907,6 @@
"version": "1.13.2",
"resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.2.tgz",
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
"dev": true,
"engines": {
"node": ">= 0.4"
},
@ -9995,6 +10028,11 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
},
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/pseudomap/-/pseudomap-1.0.2.tgz",
@ -10024,7 +10062,6 @@
"version": "6.13.0",
"resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
"integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
"dev": true,
"dependencies": {
"side-channel": "^1.0.6"
},
@ -10619,7 +10656,6 @@
"version": "1.2.2",
"resolved": "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dev": true,
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
@ -10689,7 +10725,6 @@
"version": "1.0.6",
"resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.0.6.tgz",
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
"dev": true,
"dependencies": {
"call-bind": "^1.0.7",
"es-errors": "^1.3.0",
@ -11669,6 +11704,23 @@
"punycode": "^2.1.0"
}
},
"node_modules/url": {
"version": "0.11.4",
"resolved": "https://registry.npmmirror.com/url/-/url-0.11.4.tgz",
"integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==",
"dependencies": {
"punycode": "^1.4.1",
"qs": "^6.12.3"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/url/node_modules/punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmmirror.com/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",

@ -10,6 +10,7 @@
"dependencies": {
"@ckeditor/ckeditor5-vue": "^7.2.0",
"@popperjs/core": "^2.11.8",
"axios": "^1.7.7",
"bootstrap": "^5.3.3",
"ckeditor5": "^43.3.1",
"core-js": "^3.8.3",

@ -297,6 +297,7 @@ import { setConfig } from '../components/plugins'
// import {getUserConfigFromBackend,saveData,getPageContent,getAndApplyUserStyles} from './components/utils';
import { useStore } from 'vuex';
import router from '../router/index.js';
import axios from 'axios';
export default {
name: 'CkeditorView',
@ -306,7 +307,7 @@ export default {
config: null, // CKEditor needs the DOM tree before calculating the configuration.
editor: DecoupledEditor,
// editor: ClassicEditor,
store:useStore(),
store: useStore(),
isSidebarOpen: false,//
isNavbarOpen: false,//
@ -341,8 +342,8 @@ export default {
this.$refs.editorToolbarElement.appendChild(editor.ui.view.toolbar.element);
this.$refs.editorMenuBarElement.appendChild(editor.ui.view.menuBarView.element);
//
// const pageContent = this.store.state.user.filecontent;
const pageContent = '<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li>⭐️ <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑‍💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n';
const pageContent = this.store.state.user.filecontent;
// const pageContent = '<h2>Congratulations on setting up CKEditor 5! 🎉</h2>\n<p>\n You\'ve successfully created a CKEditor 5 project. This powerful text editor will enhance your application, enabling rich text editing\n capabilities that are customizable and easy to use.\n</p>\n<h3>What\'s next?</h3>\n<ol>\n <li>\n <strong>Integrate into your app</strong>: time to bring the editing into your application. Take the code you created and add to your\n application.\n </li>\n <li>\n <strong>Explore features:</strong> Experiment with different plugins and toolbar options to discover what works best for your needs.\n </li>\n <li>\n <strong>Customize your editor:</strong> Tailor the editor\'s configuration to match your application\'s style and requirements. Or even\n write your plugin!\n </li>\n</ol>\n<p>\n Keep experimenting, and don\'t hesitate to push the boundaries of what you can achieve with CKEditor 5. Your feedback is invaluable to us\n as we strive to improve and evolve. Happy editing!\n</p>\n<h3>Helpful resources</h3>\n<ul>\n <li>📝 <a href="https://orders.ckeditor.com/trial/premium-features">Trial sign up</a>,</li>\n <li>📕 <a href="https://ckeditor.com/docs/ckeditor5/latest/installation/index.html">Documentation</a>,</li>\n <li> <a href="https://github.com/ckeditor/ckeditor5">GitHub</a> (star us if you can!),</li>\n <li>🏠 <a href="https://ckeditor.com">CKEditor Homepage</a>,</li>\n <li>🧑💻 <a href="https://ckeditor.com/ckeditor-5/demo/">CKEditor 5 Demos</a>,</li>\n</ul>\n<h3>Need help?</h3>\n<p>\n See this text, but the editor is not starting up? Check the browser\'s console for clues and guidance. It may be related to an incorrect\n license key if you use premium features or another feature-related requirement. If you cannot make it work, file a GitHub issue, and we\n will help as soon as possible!\n</p>\n';
// pageContent
// TODO
editor.setData(pageContent);
@ -428,12 +429,12 @@ export default {
const cssMatch = cssRegex.exec(text);
if (cssMatch) {
previewStyle.textContent = cssMatch[0].replace('css', '');
}else{
} else {
previewStyle.textContent = text;
}
previewStyle.textContent = previewStyle.textContent.replace(/\.ck-content/g, '');
document.head.appendChild(previewStyle);
//
let previewElement;
// element tag class name
@ -510,54 +511,26 @@ export default {
this.displayMessage(messageText, 'user');
// APIresponse
setTimeout(() => {
// Simulate AI response
let formatedResponse = `css
.ck-content p.marquee {
display: inline-block;
white-space: nowrap;
overflow: hidden;
box-sizing: border-box;
padding: 0.5em;
background: linear-gradient(90deg, #ff7e5f, #feb47b);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
animation: marquee 10s linear infinite;
position: relative;
}
@keyframes marquee {
0% {
transform: translateX(100%);
}
100% {
transform: translateX(-100%);
}
}
.ck-content p.marquee::selection {
background: rgba(255, 255, 255, 0.3); /* Ensure text is readable when selected */
}
/* Container to make sure the marquee stays within bounds */
.ck-content .marquee-container {
overflow: hidden;
white-space: nowrap;
width: 100%; /* Adjust as needed */
}
请注意由于使用了 inline-block文本框的长和宽会根据内容自动调整同时由于动画使用了 translateX 而不是 text-indent因此可以正确地处理不同长度的文本另外我添加了一个 .marquee-container 用于确保滚动文本保持在指定区域内例如不超出其父容器的边界您需要将 p.marquee 元素放置在一个具有 .marquee-container 类的元素内以确保动画效果正确
示例 HTML 结构
// messages
// TODO
chat_history = []
html
<div class="ck-content">
<div class="marquee-container">
<p class="marquee">这是一个带有流水灯效果的文本框它的宽度和高度会根据内容自动调整</p>
</div>
</div>
`;
this.displayMessage(formatedResponse, 'ai');
}, 1000);
axios({
url:'http://localhost:14514/admin/ai_layout/style_generate',
method: 'POST',
data:{
user_input: userInput.value
}
})
.then(response => {
// let formatedResponse = response.data.response;
// this.displayMessage(formatedResponse, 'ai');
console.log(response);
this.displayMessage(response.data.data,'ai')
})
.catch(error => {
console.error('Error:', error);
});
userInput.value = '';
},
@ -566,9 +539,9 @@ html
//
ElButton, ElInput, ElSelect, ElOption, ElForm, ElFormItem, ElMenu, ElMenuItem, ElColorPicker, ElSubMenu
},
created(){
if(!this.store.state.user.is_login){
router.push({name:'login'});
created() {
if (!this.store.state.user.is_login) {
router.push({ name: 'login' });
}
}
};

Loading…
Cancel
Save