mirror of
				https://github.com/yangjian102621/geekai.git
				synced 2025-11-04 16:23:42 +08:00 
			
		
		
		
	fixed conflicts
This commit is contained in:
		@@ -1,5 +1,14 @@
 | 
			
		||||
# 更新日志
 | 
			
		||||
 | 
			
		||||
## v4.0.7
 | 
			
		||||
 | 
			
		||||
* 功能优化:升级quic-go,支持 Go1.21
 | 
			
		||||
* 功能优化:添加导航菜单的时候支持框入外部链接,并支持上传自定义菜单图片
 | 
			
		||||
* Bug修复:修复弹窗等于图形验证码一直验证失败的问题
 | 
			
		||||
* 功能重构:重构前端 UI 页面,增加顶部导航
 | 
			
		||||
* 功能优化:优化 Vue 非父子组件之间的通信方式
 | 
			
		||||
* 功能优化:优化 ItemList 组件,自动根据页面宽度计算 cols 数量
 | 
			
		||||
 | 
			
		||||
## v4.0.6
 | 
			
		||||
 | 
			
		||||
* Bug修复:修复PC端画廊页面的瀑布流组件样式错乱问题
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										37
									
								
								api/go.mod
									
									
									
									
									
								
							
							
						
						
									
										37
									
								
								api/go.mod
									
									
									
									
									
								
							@@ -1,6 +1,8 @@
 | 
			
		||||
module geekai
 | 
			
		||||
 | 
			
		||||
go 1.19
 | 
			
		||||
go 1.21
 | 
			
		||||
 | 
			
		||||
toolchain go1.22.4
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/BurntSushi/toml v1.1.0
 | 
			
		||||
@@ -27,25 +29,21 @@ require github.com/xxl-job/xxl-job-executor-go v1.2.0
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/mojocn/base64Captcha v1.3.1
 | 
			
		||||
	github.com/shirou/gopsutil v3.21.11+incompatible
 | 
			
		||||
	github.com/shopspring/decimal v1.3.1
 | 
			
		||||
	github.com/syndtr/goleveldb v1.0.0
 | 
			
		||||
	golang.org/x/image v0.0.0-20211028202545-6944b10bf410
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/go-ole/go-ole v1.2.6 // indirect
 | 
			
		||||
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
			
		||||
	github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
 | 
			
		||||
	github.com/tklauser/go-sysconf v0.3.13 // indirect
 | 
			
		||||
	github.com/tklauser/numcpus v0.7.0 // indirect
 | 
			
		||||
	github.com/yusufpapurcu/wmi v1.2.4 // indirect
 | 
			
		||||
	go.uber.org/mock v0.4.0 // indirect
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/andybalholm/brotli v1.0.4 // indirect
 | 
			
		||||
	github.com/bytedance/sonic v1.9.1 // indirect
 | 
			
		||||
	github.com/cespare/xxhash/v2 v2.1.2 // indirect
 | 
			
		||||
	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 | 
			
		||||
	github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
 | 
			
		||||
	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 | 
			
		||||
	github.com/dlclark/regexp2 v1.8.1 // indirect
 | 
			
		||||
@@ -56,7 +54,6 @@ require (
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.7.0 // indirect
 | 
			
		||||
	github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
 | 
			
		||||
	github.com/goccy/go-json v0.10.2 // indirect
 | 
			
		||||
	github.com/golang/mock v1.6.0 // indirect
 | 
			
		||||
	github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 // indirect
 | 
			
		||||
	github.com/google/uuid v1.3.0 // indirect
 | 
			
		||||
	github.com/hashicorp/errwrap v1.1.0 // indirect
 | 
			
		||||
@@ -73,9 +70,7 @@ require (
 | 
			
		||||
	github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
 | 
			
		||||
	github.com/pelletier/go-toml/v2 v2.0.8 // indirect
 | 
			
		||||
	github.com/quic-go/qpack v0.4.0 // indirect
 | 
			
		||||
	github.com/quic-go/qtls-go1-19 v0.3.2 // indirect
 | 
			
		||||
	github.com/quic-go/qtls-go1-20 v0.2.2 // indirect
 | 
			
		||||
	github.com/quic-go/quic-go v0.35.1 // indirect
 | 
			
		||||
	github.com/quic-go/quic-go v0.45.0 // indirect
 | 
			
		||||
	github.com/refraction-networking/utls v1.3.2 // indirect
 | 
			
		||||
	github.com/rs/xid v1.5.0 // indirect
 | 
			
		||||
	github.com/sirupsen/logrus v1.9.3 // indirect
 | 
			
		||||
@@ -85,14 +80,14 @@ require (
 | 
			
		||||
	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 | 
			
		||||
	go.uber.org/dig v1.16.1 // indirect
 | 
			
		||||
	golang.org/x/arch v0.3.0 // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
 | 
			
		||||
	golang.org/x/mod v0.11.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.14.0 // indirect
 | 
			
		||||
	golang.org/x/sync v0.3.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.12.0 // indirect
 | 
			
		||||
	golang.org/x/time v0.3.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.10.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.30.0 // indirect
 | 
			
		||||
	golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
 | 
			
		||||
	golang.org/x/mod v0.17.0 // indirect
 | 
			
		||||
	golang.org/x/net v0.25.0 // indirect
 | 
			
		||||
	golang.org/x/sync v0.7.0 // indirect
 | 
			
		||||
	golang.org/x/text v0.15.0 // indirect
 | 
			
		||||
	golang.org/x/time v0.5.0 // indirect
 | 
			
		||||
	golang.org/x/tools v0.21.0 // indirect
 | 
			
		||||
	google.golang.org/protobuf v1.33.0 // indirect
 | 
			
		||||
	gopkg.in/ini.v1 v1.67.0 // indirect
 | 
			
		||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
			
		||||
)
 | 
			
		||||
@@ -111,7 +106,7 @@ require (
 | 
			
		||||
	go.uber.org/atomic v1.9.0 // indirect
 | 
			
		||||
	go.uber.org/fx v1.19.3
 | 
			
		||||
	go.uber.org/multierr v1.6.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.12.0
 | 
			
		||||
	golang.org/x/sys v0.15.0 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.23.0
 | 
			
		||||
	golang.org/x/sys v0.20.0 // indirect
 | 
			
		||||
	gorm.io/gorm v1.25.1
 | 
			
		||||
)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										95
									
								
								api/go.sum
									
									
									
									
									
								
							
							
						
						
									
										95
									
								
								api/go.sum
									
									
									
									
									
								
							@@ -7,11 +7,12 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible/go.mod h1:T/Aws4fEfogEE9
 | 
			
		||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
 | 
			
		||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
 | 
			
		||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
 | 
			
		||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 | 
			
		||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
 | 
			
		||||
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
 | 
			
		||||
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
 | 
			
		||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
 | 
			
		||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
 | 
			
		||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
 | 
			
		||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
 | 
			
		||||
@@ -29,6 +30,7 @@ github.com/eatmoreapple/openwechat v1.2.1 h1:ez4oqF/Y2NSEX/DbPV8lvj7JlfkYqvieeo4
 | 
			
		||||
github.com/eatmoreapple/openwechat v1.2.1/go.mod h1:61HOzTyvLobGdgWhL68jfGNwTJEv0mhQ1miCXQrvWU8=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
 | 
			
		||||
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
 | 
			
		||||
github.com/gaukas/godicttls v0.0.3 h1:YNDIf0d9adcxOijiLrEzpfZGAkNwLRzPaG6OjU7EITk=
 | 
			
		||||
@@ -40,10 +42,10 @@ github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SU
 | 
			
		||||
github.com/go-basic/ipv4 v1.0.0 h1:gjyFAa1USC1hhXTkPOwBWDPfMcUaIM+tvo1XzV9EZxs=
 | 
			
		||||
github.com/go-basic/ipv4 v1.0.0/go.mod h1:etLBnaxbidQfuqE6wgZQfs38nEWNmzALkxDZe4xY8Dg=
 | 
			
		||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
 | 
			
		||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
 | 
			
		||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 | 
			
		||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
 | 
			
		||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 | 
			
		||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 | 
			
		||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 | 
			
		||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
 | 
			
		||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 | 
			
		||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
 | 
			
		||||
@@ -68,15 +70,13 @@ github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJ
 | 
			
		||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
 | 
			
		||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
 | 
			
		||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 | 
			
		||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
 | 
			
		||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
 | 
			
		||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 | 
			
		||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
 | 
			
		||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
			
		||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
 | 
			
		||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 | 
			
		||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs=
 | 
			
		||||
github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
 | 
			
		||||
@@ -140,13 +140,16 @@ github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ
 | 
			
		||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
 | 
			
		||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 | 
			
		||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
 | 
			
		||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
 | 
			
		||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
 | 
			
		||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
 | 
			
		||||
github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs=
 | 
			
		||||
github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE=
 | 
			
		||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
 | 
			
		||||
github.com/onsi/gomega v1.27.7/go.mod h1:1p8OOlwo2iUUDsHnOrjE5UKYJ+e3W8eQ3qSlRahPmr4=
 | 
			
		||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A=
 | 
			
		||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU=
 | 
			
		||||
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
 | 
			
		||||
@@ -164,12 +167,8 @@ github.com/qiniu/go-sdk/v7 v7.17.1/go.mod h1:nqoYCNo53ZlGA521RvRethvxUDvXKt4gtYX
 | 
			
		||||
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
 | 
			
		||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
 | 
			
		||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
 | 
			
		||||
github.com/quic-go/qtls-go1-19 v0.3.2 h1:tFxjCFcTQzK+oMxG6Zcvp4Dq8dx4yD3dDiIiyc86Z5U=
 | 
			
		||||
github.com/quic-go/qtls-go1-19 v0.3.2/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
 | 
			
		||||
github.com/quic-go/qtls-go1-20 v0.2.2 h1:WLOPx6OY/hxtTxKV1Zrq20FtXtDEkeY00CGQm8GEa3E=
 | 
			
		||||
github.com/quic-go/qtls-go1-20 v0.2.2/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
 | 
			
		||||
github.com/quic-go/quic-go v0.35.1 h1:b0kzj6b/cQAf05cT0CkQubHM31wiA+xH3IBkxP62poo=
 | 
			
		||||
github.com/quic-go/quic-go v0.35.1/go.mod h1:+4CVgVppm0FNjpG3UcX8Joi/frKOH7/ciD5yGcwOO1g=
 | 
			
		||||
github.com/quic-go/quic-go v0.45.0 h1:OHmkQGM37luZITyTSu6ff03HP/2IrwDX1ZFiNEhSFUE=
 | 
			
		||||
github.com/quic-go/quic-go v0.45.0/go.mod h1:1dLehS7TIR64+vxGR70GDcatWTOtMX2PUtnKsjbTurI=
 | 
			
		||||
github.com/refraction-networking/utls v1.3.2 h1:o+AkWB57mkcoW36ET7uJ002CpBWHu0KPxi6vzxvPnv8=
 | 
			
		||||
github.com/refraction-networking/utls v1.3.2/go.mod h1:fmoaOww2bxzzEpIKOebIsnBvjQpqP7L2vcm/9KUfm/E=
 | 
			
		||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 | 
			
		||||
@@ -177,8 +176,6 @@ github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUA
 | 
			
		||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 | 
			
		||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 | 
			
		||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 | 
			
		||||
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
 | 
			
		||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
 | 
			
		||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
 | 
			
		||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
 | 
			
		||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 | 
			
		||||
@@ -207,10 +204,6 @@ github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gt
 | 
			
		||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 | 
			
		||||
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
 | 
			
		||||
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
 | 
			
		||||
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
 | 
			
		||||
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
 | 
			
		||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 | 
			
		||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 | 
			
		||||
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
 | 
			
		||||
@@ -221,10 +214,7 @@ github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4d
 | 
			
		||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
 | 
			
		||||
github.com/xxl-job/xxl-job-executor-go v1.2.0 h1:MTl2DpwrK2+hNjRRks2k7vB3oy+3onqm9OaSarneeLQ=
 | 
			
		||||
github.com/xxl-job/xxl-job-executor-go v1.2.0/go.mod h1:bUFhz/5Irp9zkdYk5MxhQcDDT6LlZrI8+rv5mHtQ1mo=
 | 
			
		||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
			
		||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
			
		||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
 | 
			
		||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 | 
			
		||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
			
		||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
 | 
			
		||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
			
		||||
@@ -233,6 +223,9 @@ go.uber.org/dig v1.16.1/go.mod h1:557JTAUZT5bUK0SvCwikmLPPtdQhfvLYtO5tJgQSbnk=
 | 
			
		||||
go.uber.org/fx v1.19.3 h1:YqMRE4+2IepTYCMOvXqQpRa+QAVdiSTnsHU4XNWBceA=
 | 
			
		||||
go.uber.org/fx v1.19.3/go.mod h1:w2HrQg26ql9fLK7hlBiZ6JsRUKV+Lj/atT1KCjT8YhM=
 | 
			
		||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
 | 
			
		||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
 | 
			
		||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
 | 
			
		||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
 | 
			
		||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
 | 
			
		||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
 | 
			
		||||
go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY=
 | 
			
		||||
@@ -241,43 +234,34 @@ golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUu
 | 
			
		||||
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
 | 
			
		||||
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
			
		||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
 | 
			
		||||
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
 | 
			
		||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
 | 
			
		||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc=
 | 
			
		||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w=
 | 
			
		||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
 | 
			
		||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
 | 
			
		||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
 | 
			
		||||
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 | 
			
		||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ=
 | 
			
		||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
 | 
			
		||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
			
		||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
			
		||||
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
 | 
			
		||||
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
			
		||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
 | 
			
		||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
			
		||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
			
		||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
			
		||||
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
 | 
			
		||||
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
 | 
			
		||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
 | 
			
		||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
 | 
			
		||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
 | 
			
		||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 | 
			
		||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
 | 
			
		||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
@@ -286,8 +270,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
 | 
			
		||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
			
		||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
 | 
			
		||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
 | 
			
		||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
			
		||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
			
		||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
			
		||||
@@ -297,23 +281,18 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
			
		||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
			
		||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
			
		||||
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
 | 
			
		||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 | 
			
		||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
 | 
			
		||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
 | 
			
		||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
			
		||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
 | 
			
		||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
			
		||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
			
		||||
golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg=
 | 
			
		||||
golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM=
 | 
			
		||||
golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
 | 
			
		||||
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
			
		||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
 | 
			
		||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 | 
			
		||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
 | 
			
		||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
			
		||||
 
 | 
			
		||||
@@ -42,12 +42,10 @@ func (h *ChatHandler) sendAzureMessage(
 | 
			
		||||
	logger.Info("HTTP请求完成,耗时:", time.Now().Sub(start))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if strings.Contains(err.Error(), "context canceled") {
 | 
			
		||||
			logger.Info("用户取消了请求:", prompt)
 | 
			
		||||
			return nil
 | 
			
		||||
			return fmt.Errorf("用户取消了请求:%s", prompt)
 | 
			
		||||
		} else if strings.Contains(err.Error(), "no available key") {
 | 
			
		||||
			return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return err
 | 
			
		||||
	} else {
 | 
			
		||||
		defer response.Body.Close()
 | 
			
		||||
 
 | 
			
		||||
@@ -58,9 +58,9 @@ func (h *ChatHandler) sendBaiduMessage(
 | 
			
		||||
	response, err := h.doRequest(ctx, req, session, &apiKey)
 | 
			
		||||
	logger.Info("HTTP请求完成,耗时:", time.Now().Sub(start))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error(err)
 | 
			
		||||
		if strings.Contains(err.Error(), "context canceled") {
 | 
			
		||||
			logger.Info("用户取消了请求:", prompt)
 | 
			
		||||
			return nil
 | 
			
		||||
			return fmt.Errorf("用户取消了请求:%s", prompt)
 | 
			
		||||
		} else if strings.Contains(err.Error(), "no available key") {
 | 
			
		||||
			return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,10 +34,6 @@ import (
 | 
			
		||||
	"gorm.io/gorm"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const ErrorMsg = "抱歉,AI 助手开小差了,请稍后再试。"
 | 
			
		||||
 | 
			
		||||
var ErrImg = ""
 | 
			
		||||
 | 
			
		||||
var logger = logger2.GetLogger()
 | 
			
		||||
 | 
			
		||||
type ChatHandler struct {
 | 
			
		||||
@@ -54,13 +50,6 @@ func NewChatHandler(app *core.AppServer, db *gorm.DB, redis *redis.Client, manag
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (h *ChatHandler) Init() {
 | 
			
		||||
	// 如果后台有上传微信客服微信二维码,则覆盖
 | 
			
		||||
	if h.App.SysConfig.WechatCardURL != "" {
 | 
			
		||||
		ErrImg = fmt.Sprintf("", h.App.SysConfig.WechatCardURL)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChatHandle 处理聊天 WebSocket 请求
 | 
			
		||||
func (h *ChatHandler) ChatHandle(c *gin.Context) {
 | 
			
		||||
	ws, err := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool { return true }}).Upgrade(c.Writer, c.Request, nil)
 | 
			
		||||
@@ -133,8 +122,6 @@ func (h *ChatHandler) ChatHandle(c *gin.Context) {
 | 
			
		||||
		Platform:    types.Platform(chatModel.Platform)}
 | 
			
		||||
	logger.Infof("New websocket connected, IP: %s, Username: %s", c.ClientIP(), session.Username)
 | 
			
		||||
 | 
			
		||||
	h.Init()
 | 
			
		||||
 | 
			
		||||
	// 保存会话连接
 | 
			
		||||
	h.App.ChatClients.Put(sessionId, client)
 | 
			
		||||
	go func() {
 | 
			
		||||
@@ -209,7 +196,7 @@ func (h *ChatHandler) sendMessage(ctx context.Context, session *types.ChatSessio
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if userVo.Power < session.Model.Power {
 | 
			
		||||
		return fmt.Errorf("您当前剩余算力(%d)已不足以支付当前模型的单次对话需要消耗的算力(%d)!", userVo.Power, session.Model.Power)
 | 
			
		||||
		return fmt.Errorf("您当前剩余算力 %d 已不足以支付当前模型的单次对话需要消耗的算力 %d,[立即购买](/member)。", userVo.Power, session.Model.Power)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if userVo.ExpiredTime > 0 && userVo.ExpiredTime <= time.Now().Unix() {
 | 
			
		||||
 
 | 
			
		||||
@@ -43,8 +43,7 @@ func (h *ChatHandler) sendChatGLMMessage(
 | 
			
		||||
	logger.Info("HTTP请求完成,耗时:", time.Now().Sub(start))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if strings.Contains(err.Error(), "context canceled") {
 | 
			
		||||
			logger.Info("用户取消了请求:", prompt)
 | 
			
		||||
			return nil
 | 
			
		||||
			return fmt.Errorf("用户取消了请求:%s", prompt)
 | 
			
		||||
		} else if strings.Contains(err.Error(), "no available key") {
 | 
			
		||||
			return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,16 +42,11 @@ func (h *ChatHandler) sendOpenAiMessage(
 | 
			
		||||
	response, err := h.doRequest(ctx, req, session, &apiKey)
 | 
			
		||||
	logger.Info("HTTP请求完成,耗时:", time.Now().Sub(start))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		logger.Error(err)
 | 
			
		||||
		if strings.Contains(err.Error(), "context canceled") {
 | 
			
		||||
			logger.Info("用户取消了请求:", prompt)
 | 
			
		||||
			return nil
 | 
			
		||||
			return fmt.Errorf("用户取消了请求:%s", prompt)
 | 
			
		||||
		} else if strings.Contains(err.Error(), "no available key") {
 | 
			
		||||
			utils.ReplyMessage(ws, "抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
			return nil
 | 
			
		||||
			return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		utils.ReplyMessage(ws, err.Error())
 | 
			
		||||
		return err
 | 
			
		||||
	} else {
 | 
			
		||||
		defer response.Body.Close()
 | 
			
		||||
@@ -82,7 +77,7 @@ func (h *ChatHandler) sendOpenAiMessage(
 | 
			
		||||
			if len(responseBody.Choices) == 0 { // Fixed: 兼容 Azure API 第一个输出空行
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			
 | 
			
		||||
 | 
			
		||||
			if responseBody.Choices[0].FinishReason == "stop" && len(contents) == 0 {
 | 
			
		||||
				utils.ReplyMessage(ws, "抱歉😔😔😔,AI助手由于未知原因已经停止输出内容。")
 | 
			
		||||
				break
 | 
			
		||||
 
 | 
			
		||||
@@ -57,8 +57,7 @@ func (h *ChatHandler) sendQWenMessage(
 | 
			
		||||
	logger.Info("HTTP请求完成,耗时:", time.Now().Sub(start))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if strings.Contains(err.Error(), "context canceled") {
 | 
			
		||||
			logger.Info("用户取消了请求:", prompt)
 | 
			
		||||
			return nil
 | 
			
		||||
			return fmt.Errorf("用户取消了请求:%s", prompt)
 | 
			
		||||
		} else if strings.Contains(err.Error(), "no available key") {
 | 
			
		||||
			return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ import (
 | 
			
		||||
	"crypto/sha256"
 | 
			
		||||
	"encoding/base64"
 | 
			
		||||
	"encoding/json"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"geekai/core/types"
 | 
			
		||||
	"geekai/store/model"
 | 
			
		||||
@@ -87,8 +88,7 @@ func (h *ChatHandler) sendXunFeiMessage(
 | 
			
		||||
		res = h.DB.Where("platform", session.Model.Platform).Where("type", "chat").Where("enabled", true).Order("last_used_at ASC").First(&apiKey)
 | 
			
		||||
	}
 | 
			
		||||
	if res.Error != nil {
 | 
			
		||||
		utils.ReplyMessage(ws, "抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
		return nil
 | 
			
		||||
		return errors.New("抱歉😔😔😔,系统已经没有可用的 API KEY,请联系管理员!")
 | 
			
		||||
	}
 | 
			
		||||
	// 更新 API KEY 的最后使用时间
 | 
			
		||||
	h.DB.Model(&apiKey).UpdateColumn("last_used_at", time.Now().Unix())
 | 
			
		||||
 
 | 
			
		||||
@@ -51,11 +51,12 @@ func NewService(db *gorm.DB, manager *oss.UploaderManager, redisCli *redis.Clien
 | 
			
		||||
 | 
			
		||||
// PushTask push a new mj task in to task queue
 | 
			
		||||
func (s *Service) PushTask(task types.DallTask) {
 | 
			
		||||
	logger.Debugf("add a new MidJourney task to the task list: %+v", task)
 | 
			
		||||
	logger.Infof("add a new DALL-E task to the task list: %+v", task)
 | 
			
		||||
	s.taskQueue.RPush(task)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *Service) Run() {
 | 
			
		||||
	logger.Info("Starting DALL-E job consumer...")
 | 
			
		||||
	go func() {
 | 
			
		||||
		for {
 | 
			
		||||
			var task types.DallTask
 | 
			
		||||
@@ -64,7 +65,7 @@ func (s *Service) Run() {
 | 
			
		||||
				logger.Errorf("taking task with error: %v", err)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			logger.Infof("handle a new DALL-E task: %+v", task)
 | 
			
		||||
			_, err = s.Image(task, false)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logger.Errorf("error with image task: %v", err)
 | 
			
		||||
@@ -138,7 +139,7 @@ func (s *Service) Image(task types.DallTask, sync bool) (string, error) {
 | 
			
		||||
	if len(apiKey.ProxyURL) > 5 {
 | 
			
		||||
		s.httpClient.SetProxyURL(apiKey.ProxyURL).R()
 | 
			
		||||
	}
 | 
			
		||||
	logger.Debugf("Sending %s request, ApiURL:%s, API KEY:%s, PROXY: %s", apiKey.Platform, apiKey.ApiURL, apiKey.Value, apiKey.ProxyURL)
 | 
			
		||||
	logger.Infof("Sending %s request, ApiURL:%s, API KEY:%s, PROXY: %s", apiKey.Platform, apiKey.ApiURL, apiKey.Value, apiKey.ProxyURL)
 | 
			
		||||
	r, err := s.httpClient.R().SetHeader("Content-Type", "application/json").
 | 
			
		||||
		SetHeader("Authorization", "Bearer "+apiKey.Value).
 | 
			
		||||
		SetBody(imgReq{
 | 
			
		||||
@@ -240,6 +241,8 @@ func (s *Service) DownloadImages() {
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					logger.Error("error with download image: %s, error: %v", imgURL, err)
 | 
			
		||||
					continue
 | 
			
		||||
				} else {
 | 
			
		||||
					logger.Infof("download image %s successfully.", v.OrgURL)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										838
									
								
								database/chatgpt_plus-v4.0.7.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										838
									
								
								database/chatgpt_plus-v4.0.7.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,838 @@
 | 
			
		||||
-- phpMyAdmin SQL Dump
 | 
			
		||||
-- version 5.2.1
 | 
			
		||||
-- https://www.phpmyadmin.net/
 | 
			
		||||
--
 | 
			
		||||
-- 主机: localhost
 | 
			
		||||
-- 生成日期: 2024-05-19 11:36:07
 | 
			
		||||
-- 服务器版本: 8.0.27
 | 
			
		||||
-- PHP 版本: 8.1.18
 | 
			
		||||
 | 
			
		||||
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
 | 
			
		||||
START TRANSACTION;
 | 
			
		||||
SET time_zone = "+00:00";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
 | 
			
		||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
 | 
			
		||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
 | 
			
		||||
/*!40101 SET NAMES utf8mb4 */;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 数据库: `chatgpt_plus`
 | 
			
		||||
--
 | 
			
		||||
CREATE DATABASE IF NOT EXISTS `chatgpt_plus` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
 | 
			
		||||
USE `chatgpt_plus`;
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_admin_users`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_admin_users`;
 | 
			
		||||
CREATE TABLE `chatgpt_admin_users` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
 | 
			
		||||
  `password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
 | 
			
		||||
  `salt` char(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码盐',
 | 
			
		||||
  `status` tinyint(1) NOT NULL COMMENT '当前状态',
 | 
			
		||||
  `last_login_at` int NOT NULL COMMENT '最后登录时间',
 | 
			
		||||
  `last_login_ip` char(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '最后登录 IP',
 | 
			
		||||
  `created_at` datetime NOT NULL COMMENT '创建时间',
 | 
			
		||||
  `updated_at` datetime NOT NULL COMMENT '更新时间'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='系统用户' ROW_FORMAT=DYNAMIC;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_admin_users`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_admin_users` (`id`, `username`, `password`, `salt`, `status`, `last_login_at`, `last_login_ip`, `created_at`, `updated_at`) VALUES
 | 
			
		||||
(1, 'admin', '6d17e80c87d209efb84ca4b2e0824f549d09fac8b2e1cc698de5bb5e1d75dfd0', 'mmrql75o', 1, 1715725043, '::1', '2024-03-11 16:30:20', '2024-05-15 06:17:24');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_api_keys`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_api_keys`;
 | 
			
		||||
CREATE TABLE `chatgpt_api_keys` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `platform` char(20) DEFAULT NULL COMMENT '平台',
 | 
			
		||||
  `name` varchar(30) DEFAULT NULL COMMENT '名称',
 | 
			
		||||
  `value` varchar(100) NOT NULL COMMENT 'API KEY value',
 | 
			
		||||
  `type` varchar(10) NOT NULL DEFAULT 'chat' COMMENT '用途(chat=>聊天,img=>图片)',
 | 
			
		||||
  `last_used_at` int NOT NULL COMMENT '最后使用时间',
 | 
			
		||||
  `api_url` varchar(255) DEFAULT NULL COMMENT 'API 地址',
 | 
			
		||||
  `enabled` tinyint(1) DEFAULT NULL COMMENT '是否启用',
 | 
			
		||||
  `proxy_url` varchar(100) DEFAULT NULL COMMENT '代理地址',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='OpenAI API ';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_chat_history`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_chat_history`;
 | 
			
		||||
CREATE TABLE `chatgpt_chat_history` (
 | 
			
		||||
  `id` bigint NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `chat_id` char(40) NOT NULL COMMENT '会话 ID',
 | 
			
		||||
  `type` varchar(10) NOT NULL COMMENT '类型:prompt|reply',
 | 
			
		||||
  `icon` varchar(100) NOT NULL COMMENT '角色图标',
 | 
			
		||||
  `role_id` int NOT NULL COMMENT '角色 ID',
 | 
			
		||||
  `model` varchar(30) DEFAULT NULL COMMENT '模型名称',
 | 
			
		||||
  `content` text NOT NULL COMMENT '聊天内容',
 | 
			
		||||
  `tokens` smallint NOT NULL COMMENT '耗费 token 数量',
 | 
			
		||||
  `use_context` tinyint(1) NOT NULL COMMENT '是否允许作为上下文语料',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL,
 | 
			
		||||
  `deleted_at` datetime DEFAULT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天历史记录';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_chat_items`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_chat_items`;
 | 
			
		||||
CREATE TABLE `chatgpt_chat_items` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `chat_id` char(40) NOT NULL COMMENT '会话 ID',
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `role_id` int NOT NULL COMMENT '角色 ID',
 | 
			
		||||
  `title` varchar(100) NOT NULL COMMENT '会话标题',
 | 
			
		||||
  `model_id` int NOT NULL DEFAULT '0' COMMENT '模型 ID',
 | 
			
		||||
  `model` varchar(30) DEFAULT NULL COMMENT '模型名称',
 | 
			
		||||
  `created_at` datetime NOT NULL COMMENT '创建时间',
 | 
			
		||||
  `updated_at` datetime NOT NULL COMMENT '更新时间',
 | 
			
		||||
  `deleted_at` datetime DEFAULT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户会话列表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_chat_models`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_chat_models`;
 | 
			
		||||
CREATE TABLE `chatgpt_chat_models` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `platform` varchar(20) DEFAULT NULL COMMENT '模型平台',
 | 
			
		||||
  `name` varchar(50) NOT NULL COMMENT '模型名称',
 | 
			
		||||
  `value` varchar(50) NOT NULL COMMENT '模型值',
 | 
			
		||||
  `sort_num` tinyint(1) NOT NULL COMMENT '排序数字',
 | 
			
		||||
  `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用模型',
 | 
			
		||||
  `power` tinyint NOT NULL COMMENT '消耗算力点数',
 | 
			
		||||
  `temperature` float(3,2) NOT NULL DEFAULT '1.00' COMMENT '模型创意度',
 | 
			
		||||
  `max_tokens` int NOT NULL DEFAULT '1024' COMMENT '最大响应长度',
 | 
			
		||||
  `max_context` int NOT NULL DEFAULT '4096' COMMENT '最大上下文长度',
 | 
			
		||||
  `open` tinyint(1) NOT NULL COMMENT '是否开放模型',
 | 
			
		||||
  `key_id` int NOT NULL COMMENT '绑定API KEY ID',
 | 
			
		||||
  `created_at` datetime DEFAULT NULL,
 | 
			
		||||
  `updated_at` datetime DEFAULT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='AI 模型表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_chat_models`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_chat_models` (`id`, `platform`, `name`, `value`, `sort_num`, `enabled`, `power`, `temperature`, `max_tokens`, `max_context`, `open`, `key_id`, `created_at`, `updated_at`) VALUES
 | 
			
		||||
(1, 'OpenAI', 'GPT-3.5', 'gpt-3.5-turbo-16k', 0, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-08-23 12:06:36', '2024-05-11 06:55:19'),
 | 
			
		||||
(2, 'XunFei', '星火3.5', 'generalv3.5', 14, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-08-23 12:15:30', '2024-05-15 07:17:37'),
 | 
			
		||||
(3, 'ChatGLM', 'ChatGML-Pro', 'chatglm_pro', 13, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-08-23 13:35:45', '2024-01-15 21:34:02'),
 | 
			
		||||
(5, 'ChatGLM', 'ChatGLM-Std', 'chatglm_std', 12, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-08-24 15:05:38', '2024-01-15 21:34:02'),
 | 
			
		||||
(6, 'ChatGLM', 'ChatGLM-Lite', 'chatglm_lite', 11, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-08-24 15:06:15', '2024-01-15 21:34:02'),
 | 
			
		||||
(7, 'Baidu', '文心一言3.0', 'eb-instant', 6, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-10-11 11:29:28', '2024-01-15 21:34:02'),
 | 
			
		||||
(8, 'XunFei', '星火V1.5', 'general', 8, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-10-11 15:48:30', '2024-01-15 21:34:02'),
 | 
			
		||||
(9, 'XunFei', '星火V2.0', 'generalv2', 9, 1, 1, 1.00, 1024, 4096, 1, 0, '2023-10-11 15:48:45', '2024-01-15 21:34:02'),
 | 
			
		||||
(10, 'Baidu', '文心一言4.0', 'completions_pro', 7, 1, 3, 1.00, 1024, 4096, 1, 0, '2023-10-25 08:31:37', '2024-01-15 21:34:02'),
 | 
			
		||||
(11, 'OpenAI', 'GPT-4.0', 'gpt-4', 5, 1, 15, 1.00, 1024, 4096, 1, 0, '2023-10-25 08:45:15', '2024-05-11 06:55:17'),
 | 
			
		||||
(12, 'XunFei', '星火V3.0', 'generalv3', 10, 1, 2, 1.00, 1024, 4096, 1, 0, '2023-11-23 06:28:18', '2024-01-15 21:34:02'),
 | 
			
		||||
(13, 'OpenAI', 'DALL·E', 'gpt-4-gizmo-g-2fkFE8rbu', 2, 1, 20, 1.00, 1024, 4096, 1, 0, '2024-01-15 21:24:05', '2024-01-15 21:34:02'),
 | 
			
		||||
(14, 'OpenAI', 'GPT-超级模型', 'gpt-4-all', 1, 1, 20, 1.00, 1024, 4096, 1, 0, '2024-01-15 21:24:37', '2024-01-15 21:34:02'),
 | 
			
		||||
(15, 'OpenAI', '董宇辉小作文助手', 'gpt-4-gizmo-g-dse9iXvor', 3, 1, 20, 1.00, 1024, 4096, 1, 0, '2024-01-15 21:30:54', '2024-01-15 21:34:02'),
 | 
			
		||||
(16, 'OpenAI', '网页/PDF对话', 'gpt-4-gizmo-g-pNWGgUYqS', 4, 1, 1, 1.00, 1024, 4096, 1, 0, '2024-01-15 21:32:53', '2024-01-15 21:34:54');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_chat_roles`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_chat_roles`;
 | 
			
		||||
CREATE TABLE `chatgpt_chat_roles` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `name` varchar(30) NOT NULL COMMENT '角色名称',
 | 
			
		||||
  `marker` varchar(30) NOT NULL COMMENT '角色标识',
 | 
			
		||||
  `context_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '角色语料 json',
 | 
			
		||||
  `hello_msg` varchar(255) NOT NULL COMMENT '打招呼信息',
 | 
			
		||||
  `icon` varchar(255) NOT NULL COMMENT '角色图标',
 | 
			
		||||
  `enable` tinyint(1) NOT NULL COMMENT '是否被启用',
 | 
			
		||||
  `sort_num` smallint NOT NULL DEFAULT '0' COMMENT '角色排序',
 | 
			
		||||
  `model_id` int NOT NULL DEFAULT '0' COMMENT '绑定模型ID',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='聊天角色表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_chat_roles`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_chat_roles` (`id`, `name`, `marker`, `context_json`, `hello_msg`, `icon`, `enable`, `sort_num`, `model_id`, `created_at`, `updated_at`) VALUES
 | 
			
		||||
(1, '通用AI助手', 'gpt', '', '您好,我是您的AI智能助手,我会尽力回答您的问题或提供有用的建议。', '/images/avatar/gpt.png', 1, 0, 0, '2023-05-30 07:02:06', '2024-04-05 17:04:48'),
 | 
			
		||||
(24, '程序员', 'programmer', '[{\"role\":\"user\",\"content\":\"现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。\"},{\"role\":\"assistant\",\"content\":\"好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。\"}]', 'Talk is cheap, i will show code!', '/images/avatar/programmer.jpg', 1, 1, 1, '2023-05-30 14:10:24', '2024-04-05 21:20:20'),
 | 
			
		||||
(25, '启蒙老师', 'teacher', '[{\"role\":\"user\",\"content\":\"从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。\"},{\"role\":\"assistant\",\"content\":\"好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案,绝对不直接给出答案。\"}]', '同学你好,我将引导你一步一步自己找到问题的答案。', '/images/avatar/teacher.jpg', 1, 3, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(26, '艺术家', 'artist', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。\"},{\"role\":\"assistant\",\"content\":\"非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。\"}]', '坚持原创,勇于表达,保持深刻的观察力和批判性思维。', '/images/avatar/artist.jpg', 1, 4, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(27, '心理咨询师', 'psychiatrist', '[{\"role\":\"user\",\"content\":\"从现在开始你将扮演中国著名的心理学家和心理治疗师武志红,你非常善于使用情景咨询法,认知重构法,自我洞察法,行为调节法等咨询方法来给客户做心理咨询。你总是循序渐进,一步一步地回答客户的问题。\"},{\"role\":\"assistant\",\"content\":\"非常感谢你的介绍。作为一名心理学家和心理治疗师,我的主要职责是帮助客户解决心理健康问题,提升他们的生活质量和幸福感。\"}]', '作为一名心理学家和心理治疗师,我的主要职责是帮助您解决心理健康问题,提升您的生活质量和幸福感。', '/images/avatar/psychiatrist.jpg', 1, 2, 14, '2023-05-30 14:10:24', '2024-04-05 21:20:31'),
 | 
			
		||||
(28, '鲁迅', 'lu_xun', '[{\"role\":\"user\",\"content\":\"现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。\"},{\"role\":\"assistant\",\"content\":\"好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。\"}]', '自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。', '/images/avatar/lu_xun.jpg', 1, 5, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(29, '白酒销售', 'seller', '[{\"role\":\"user\",\"content\":\"现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人,是人民的福酒。中颂福产品定价,分为三个系列,喜系列 6 瓶装:¥1188/箱,和系列 6 瓶装:¥2208/箱,贵系列 6 瓶装:¥3588/箱。\"},{\"role\":\"assistant\",\"content\":\"你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。\"}]', '你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。', '/images/avatar/seller.jpg', 0, 9, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(30, '英语陪练员', 'english_trainer', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的英语练习教练,你非常有耐心,接下来你将全程使用英文跟我对话,并及时指出我的语法错误,要求在你的每次回复后面附上本次回复的中文解释。\"},{\"role\":\"assistant\",\"content\":\"Okay, let\'s start our conversation practice! What\'s your name?(Translation: 好的,让我们开始对话练习吧!请问你的名字是什么?)\"}]', 'Okay, let\'s start our conversation practice! What\'s your name?', '/images/avatar/english_trainer.jpg', 1, 6, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(31, '中英文翻译官', 'translator', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一位中英文翻译官,如果我输入的内容是中文,那么需要把句子翻译成英文输出,如果我输入内容的是英文,那么你需要将其翻译成中文输出,你能听懂我意思吗\"},{\"role\":\"assistant\",\"content\":\"是的,我能听懂你的意思并会根据你的输入进行中英文翻译。请问有什么需要我帮助你翻译的内容吗?\"}]', '请输入你要翻译的中文或者英文内容!', '/images/avatar/translator.jpg', 1, 7, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(32, '小红书姐姐', 'red_book', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的小红书写手,你需要做的就是根据我提的文案需求,用小红书的写作手法来完成一篇文案,文案要简明扼要,利于传播。\"},{\"role\":\"assistant\",\"content\":\"当然,我会尽我所能地为您创作出一篇小红书文案。请告诉我您的具体文案需求是什么?)\"}]', '姐妹,请告诉我您的具体文案需求是什么?', '/images/avatar/red_book.jpg', 1, 8, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(33, '抖音文案助手', 'dou_yin', '[{\"role\":\"user\",\"content\":\"现在你将扮演一位优秀的抖音文案视频写手,抖音文案的特点首先是要有自带传播属性的标题,然后内容要短小精悍,风趣幽默,最后还要有一些互动元素。\"},{\"role\":\"assistant\",\"content\":\"当然,作为一位优秀的抖音文案视频写手,我会尽我所能为您创作出一篇抖音视频文案。请告诉我视频内容的主题是什么?)\"}]', '请告诉我视频内容的主题是什么?', '/images/avatar/dou_yin.jpg', 1, 10, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(34, '周报小助理', 'weekly_report', '[{\"role\":\"user\",\"content\":\"下面我将输入我本周的工作列表,你需要根据我本周的工作内容写一篇工作周报,周报的内容要体现我为公司做的贡献以及个人获得的成长。\"},{\"role\":\"assistant\",\"content\":\"好的,请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。\"}]', '请输入你本周大概的工作内容,我将尽力为您创作一份工作周报。', '/images/avatar/weekly_report.jpg', 1, 11, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(35, 'AI 女友', 'girl_friend', '[{\"role\":\"user\",\"content\":\"接下来我们来玩一场角色扮演,现在你将扮演我的女朋友,你总是能够让人感受到她的关怀和关注。你总是能够洞察到别人的情绪和需要,你身上散发着一股无比温暖的气息,让人不由自主地想要靠近你,和自己的快乐和烦恼。她总是能够用一种恰到好处的方式安慰和鼓励别人,在她的身边,人们总能够找到自己需要的支持和鼓励。接下来的对话中你要始终扮演这位女朋友的身份来跟我对话,不再是 AI 机器人,能听懂我的意思吗?\"},{\"role\":\"assistant\",\"content\":\"是的,我会尽力扮演你女朋友的角色,倾听你的心声并给你需要的支持和鼓励。)\"}]', '作为一个名合格的 AI 女友,我将倾听你的心声并给你需要的支持和鼓励。', '/images/avatar/girl_friend.jpg', 1, 12, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(36, '好评神器', 'good_comment', '[{\"role\":\"user\",\"content\":\"接下来你将扮演一个评论员来跟我对话,你是那种专门写好评的评论员,接下我会输入一些评论主体或者商品,你需要为该商品写一段好评。\"},{\"role\":\"assistant\",\"content\":\"好的,我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。\"}]', '我将为您写一段优秀的评论。请告诉我您需要评论的商品或主题是什么。', '/images/avatar/good_comment.jpg', 1, 13, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(37, '史蒂夫·乔布斯', 'steve_jobs', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以史蒂夫·乔布斯的身份,站在史蒂夫·乔布斯的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以史蒂夫·乔布斯的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '活着就是为了改变世界,难道还有其他原因吗?', '/images/avatar/steve_jobs.jpg', 1, 14, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(38, '埃隆·马斯克', 'elon_musk', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以埃隆·马斯克的身份,站在埃隆·马斯克的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以埃隆·马斯克的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '梦想要远大,如果你的梦想没有吓到你,说明你做得不对。', '/images/avatar/elon_musk.jpg', 1, 15, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04'),
 | 
			
		||||
(39, '孔子', 'kong_zi', '[{\"role\":\"user\",\"content\":\"在接下来的对话中,请以孔子的身份,站在孔子的视角仔细思考一下之后再回答我的问题。\"},{\"role\":\"assistant\",\"content\":\"好的,我将以孔子的身份来思考并回答你的问题。请问你有什么需要跟我探讨的吗?\"}]', '士不可以不弘毅,任重而道远。', '/images/avatar/kong_zi.jpg', 1, 16, 0, '2023-05-30 14:10:24', '2024-04-05 07:57:04');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_configs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_configs`;
 | 
			
		||||
CREATE TABLE `chatgpt_configs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `marker` varchar(20) NOT NULL COMMENT '标识',
 | 
			
		||||
  `config_json` text NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_configs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_configs` (`id`, `marker`, `config_json`) VALUES
 | 
			
		||||
(1, 'system', '{\"title\":\"GeekAI 创作系统\",\"admin_title\":\"GeekAI 控制台\",\"logo\":\"/images/logo.png\",\"init_power\":100,\"daily_power\":10,\"invite_power\":10,\"vip_month_power\":1000,\"register_ways\":[\"username\",\"mobile\",\"email\"],\"enabled_register\":true,\"reward_img\":\"/images/wechat-pay.png\",\"enabled_reward\":true,\"power_price\":0.1,\"order_pay_timeout\":1800,\"vip_info_text\":\"月度会员,年度会员每月赠送 1000 点算力,赠送算力当月有效当月没有消费完的算力不结余到下个月。 点卡充值的算力长期有效。\",\"default_models\":[1,12,3],\"mj_power\":20,\"mj_action_power\":10,\"sd_power\":5,\"dall_power\":15,\"wechat_card_url\":\"/images/wx.png\",\"enable_context\":true,\"context_deep\":4,\"sd_neg_prompt\":\"(worst quality:2), (low quality:2), (normal quality:2), lowres, ((monochrome)), ((grayscale)), bad anatomy,DeepNegative, skin spots, acnes, skin blemishes,(fat:1.2),facing away, looking away,tilted head, lowres,bad anatomy,bad hands, missing fingers,extra digit, fewer digits,bad feet,poorly drawn hands,poorly drawn face,mutation,deformed,extra fingers,extra limbs,extra arms,extra legs,malformed limbs,fused fingers,too many fingers,long neck,cross-eyed,mutated hands,polar lowres,bad body,bad proportions,gross proportions,missing arms,missing legs,extra digit, extra arms, extra leg, extra foot,teethcroppe,signature, watermark, username,blurry,cropped,jpeg artifacts,text,error\"}'),
 | 
			
		||||
(2, 'chat', '{\"azure\":{\"api_url\":\"https://chat-bot-api.openai.azure.com/openai/deployments/{model}/chat/completions?api-version=2023-05-15\",\"max_tokens\":1024,\"temperature\":1},\"baidu\":{\"api_url\":\"https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/{model}\",\"max_tokens\":1024,\"temperature\":0.95},\"chat_gml\":{\"api_url\":\"https://open.bigmodel.cn/api/paas/v3/model-api/{model}/sse-invoke\",\"max_tokens\":1024,\"temperature\":0.95},\"context_deep\":4,\"dall_api_url\":\"http://89.117.18.9:8001/v1/images/generations\",\"dall_img_num\":1,\"enable_context\":true,\"enable_history\":true,\"open_ai\":{\"api_url\":\"http://89.117.18.9:8001/v1/chat/completions\",\"max_tokens\":1024,\"temperature\":1},\"xun_fei\":{\"api_url\":\"wss://spark-api.xf-yun.com/{version}/chat\",\"max_tokens\":1024,\"temperature\":0.5}}'),
 | 
			
		||||
(3, 'notice', '{\"sd_neg_prompt\":\"\",\"content\":\"## v4.0.7 更新日志\\n\\n* 功能优化:添加导航菜单的时候支持框入外部链接,并支持上传自定义菜单图片\\n* Bug修复:修复弹窗等于图形验证码一直验证失败的问题\\n* 功能重构:重构前端 UI 页面,增加顶部导航\\n* 功能优化:优化 Vue 非父子组件之间的通信方式\\n* 功能优化:优化 ItemList 组件,自动根据页面宽度计算 cols 数量\\n\\n注意:当前站点仅为开源项目 \\u003ca style=\\\"color: #F56C6C\\\" href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003eChatPlus\\u003c/a\\u003e 的演示项目,本项目单纯就是给大家体验项目功能使用。\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n\\u003cstrong style=\\\"color: #F56C6C\\\"\\u003e体验额度用完之后请不要在当前站点进行任何充值操作!!!\\u003c/strong\\u003e\\n 如果觉得好用你就花几分钟自己部署一套,没有API KEY 的同学可以去下面几个推荐的中转站购买:\\n1. \\u003ca href=\\\"https://api.chat-plus.net\\\" target=\\\"_blank\\\"\\n   style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.chat-plus.net\\u003c/a\\u003e\\n2. \\u003ca href=\\\"https://api.geekai.me\\\" target=\\\"_blank\\\"\\n   style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://api.geekai.me\\u003c/a\\u003e\\n3. \\u003ca href=\\\"https://gpt.bemore.lol\\\" target=\\\"_blank\\\"\\n   style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://gpt.bemore.lol\\u003c/a\\u003e\\n\\n支持MidJourney,GPT,Claude,Google Gemmi,以及国内各个厂家的大模型,现在有超级优惠,价格远低于 OpenAI 官方。关于中转 API 的优势和劣势请参考 [中转API技术原理](https://ai.r9it.com/docs/install/errors-handle.html#%E8%B0%83%E7%94%A8%E4%B8%AD%E8%BD%AC-api-%E6%8A%A5%E9%94%99%E6%97%A0%E5%8F%AF%E7%94%A8%E6%B8%A0%E9%81%93)。GPT-3.5,GPT-4,DALL-E3 绘图......你都可以随意使用,无需魔法。\\n接入教程: \\u003ca href=\\\"https://ai.r9it.com/docs/install/\\\" target=\\\"_blank\\\"\\n             style=\\\"font-size: 20px;color:#F56C6C\\\"\\u003ehttps://ai.r9it.com/docs/install/\\u003c/a\\u003e\\n本项目源码地址:\\u003ca href=\\\"https://github.com/yangjian102621/chatgpt-plus\\\" target=\\\"_blank\\\"\\u003ehttps://github.com/yangjian102621/chatgpt-plus\\u003c/a\\u003e\",\"updated\":true}');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_dall_jobs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_dall_jobs`;
 | 
			
		||||
CREATE TABLE `chatgpt_dall_jobs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户ID',
 | 
			
		||||
  `prompt` varchar(2000) NOT NULL COMMENT '提示词',
 | 
			
		||||
  `img_url` varchar(255) NOT NULL COMMENT '图片地址',
 | 
			
		||||
  `org_url` varchar(400) DEFAULT NULL COMMENT '原图地址',
 | 
			
		||||
  `publish` tinyint(1) NOT NULL COMMENT '是否发布',
 | 
			
		||||
  `power` smallint NOT NULL COMMENT '消耗算力',
 | 
			
		||||
  `progress` smallint NOT NULL COMMENT '任务进度',
 | 
			
		||||
  `err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
 | 
			
		||||
  `created_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='DALLE 绘图任务表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_files`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_files`;
 | 
			
		||||
CREATE TABLE `chatgpt_files` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `name` varchar(100) NOT NULL COMMENT '文件名',
 | 
			
		||||
  `obj_key` varchar(100) DEFAULT NULL COMMENT '文件标识',
 | 
			
		||||
  `url` varchar(255) NOT NULL COMMENT '文件地址',
 | 
			
		||||
  `ext` varchar(10) NOT NULL COMMENT '文件后缀',
 | 
			
		||||
  `size` bigint NOT NULL DEFAULT '0' COMMENT '文件大小',
 | 
			
		||||
  `created_at` datetime NOT NULL COMMENT '创建时间'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户文件表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_functions`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_functions`;
 | 
			
		||||
CREATE TABLE `chatgpt_functions` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `name` varchar(30) NOT NULL COMMENT '函数名称',
 | 
			
		||||
  `label` varchar(30) DEFAULT NULL COMMENT '函数标签',
 | 
			
		||||
  `description` varchar(255) DEFAULT NULL COMMENT '函数描述',
 | 
			
		||||
  `parameters` text COMMENT '函数参数(JSON)',
 | 
			
		||||
  `required` varchar(255) NOT NULL COMMENT '必填参数(JSON)',
 | 
			
		||||
  `action` varchar(255) DEFAULT NULL COMMENT '函数处理 API',
 | 
			
		||||
  `token` varchar(255) DEFAULT NULL COMMENT 'API授权token',
 | 
			
		||||
  `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启用'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='函数插件表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_functions`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_functions` (`id`, `name`, `label`, `description`, `parameters`, `required`, `action`, `token`, `enabled`) VALUES
 | 
			
		||||
(1, 'weibo_hot', '微博热搜', '新浪微博热搜榜,微博当日热搜榜单', '{\"type\":\"object\",\"properties\":{}}', 'null', 'http://localhost:5678/api/function/weibo', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.ehLClXcjo-Ytr5y6pY9mSE3zN_2ViIXAIpTJxI9S1Mo', 0),
 | 
			
		||||
(2, 'zaobao', '今日早报', '每日早报,获取当天新闻事件列表', '{\"type\":\"object\",\"properties\":{}}', 'null', 'http://localhost:5678/api/function/zaobao', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.ehLClXcjo-Ytr5y6pY9mSE3zN_2ViIXAIpTJxI9S1Mo', 0),
 | 
			
		||||
(3, 'dalle3', 'DALL-E3 AI 绘图', 'AI 绘画工具,根据输入的绘图描述用 AI 工具进行绘画创作', '{\"type\":\"object\",\"required\":[\"prompt\"],\"properties\":{\"prompt\":{\"type\":\"string\",\"description\":\"绘画提示词\"}}}', 'null', 'http://localhost:5678/api/function/dalle3', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHBpcmVkIjowLCJ1c2VyX2lkIjowfQ.ehLClXcjo-Ytr5y6pY9mSE3zN_2ViIXAIpTJxI9S1Mo', 1);
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_invite_codes`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_invite_codes`;
 | 
			
		||||
CREATE TABLE `chatgpt_invite_codes` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户ID',
 | 
			
		||||
  `code` char(8) NOT NULL COMMENT '邀请码',
 | 
			
		||||
  `hits` int NOT NULL COMMENT '点击次数',
 | 
			
		||||
  `reg_num` smallint NOT NULL COMMENT '注册数量',
 | 
			
		||||
  `created_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户邀请码';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_invite_logs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_invite_logs`;
 | 
			
		||||
CREATE TABLE `chatgpt_invite_logs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `inviter_id` int NOT NULL COMMENT '邀请人ID',
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '注册用户ID',
 | 
			
		||||
  `username` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
 | 
			
		||||
  `invite_code` char(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '邀请码',
 | 
			
		||||
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
 | 
			
		||||
  `created_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='邀请注册日志';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_menus`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_menus`;
 | 
			
		||||
CREATE TABLE `chatgpt_menus` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `name` varchar(30) NOT NULL COMMENT '菜单名称',
 | 
			
		||||
  `icon` varchar(150) NOT NULL COMMENT '菜单图标',
 | 
			
		||||
  `url` varchar(100) NOT NULL COMMENT '地址',
 | 
			
		||||
  `sort_num` smallint NOT NULL COMMENT '排序',
 | 
			
		||||
  `enabled` tinyint(1) NOT NULL COMMENT '是否启用'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='前端菜单表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_menus`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_menus` (`id`, `name`, `icon`, `url`, `sort_num`, `enabled`) VALUES
 | 
			
		||||
(1, '对话聊天', '/images/menu/chat.png', '/chat', 0, 1),
 | 
			
		||||
(5, 'MJ 绘画', '/images/menu/mj.png', '/mj', 1, 1),
 | 
			
		||||
(6, 'SD 绘画', '/images/menu/sd.png', '/sd', 2, 1),
 | 
			
		||||
(7, '算力日志', '/images/menu/log.png', '/powerLog', 7, 1),
 | 
			
		||||
(8, '应用中心', '/images/menu/app.png', '/apps', 6, 1),
 | 
			
		||||
(9, '作品展示', '/images/menu/img-wall.png', '/images-wall', 4, 1),
 | 
			
		||||
(10, '会员计划', '/images/menu/member.png', '/member', 8, 1),
 | 
			
		||||
(11, '分享计划', '/images/menu/share.png', '/invite', 9, 1),
 | 
			
		||||
(12, '思维导图', '/images/menu/xmind.png', '/xmind', 5, 1),
 | 
			
		||||
(13, 'DALLE', '/images/menu/dalle.png', '/dalle', 3, 1),
 | 
			
		||||
(14, '项目文档', '/images/menu/docs.png', 'https://ai.r9it.com/docs/', 11, 1),
 | 
			
		||||
(15, 'GeekAI官方论坛', '/images/menu/bbs.png', 'https://bbs.geekai.me/', 12, 1);
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_mj_jobs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_mj_jobs`;
 | 
			
		||||
CREATE TABLE `chatgpt_mj_jobs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `task_id` varchar(20) DEFAULT NULL COMMENT '任务 ID',
 | 
			
		||||
  `type` varchar(20) DEFAULT 'image' COMMENT '任务类别',
 | 
			
		||||
  `message_id` char(40) NOT NULL COMMENT '消息 ID',
 | 
			
		||||
  `channel_id` char(40) DEFAULT NULL COMMENT '频道ID',
 | 
			
		||||
  `reference_id` char(40) DEFAULT NULL COMMENT '引用消息 ID',
 | 
			
		||||
  `prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
 | 
			
		||||
  `img_url` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '图片URL',
 | 
			
		||||
  `org_url` varchar(400) DEFAULT NULL COMMENT '原始图片地址',
 | 
			
		||||
  `hash` varchar(100) DEFAULT NULL COMMENT 'message hash',
 | 
			
		||||
  `progress` smallint DEFAULT '0' COMMENT '任务进度',
 | 
			
		||||
  `use_proxy` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否使用反代',
 | 
			
		||||
  `publish` tinyint(1) NOT NULL COMMENT '是否发布',
 | 
			
		||||
  `err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
 | 
			
		||||
  `power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
 | 
			
		||||
  `created_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='MidJourney 任务表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_orders`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_orders`;
 | 
			
		||||
CREATE TABLE `chatgpt_orders` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户ID',
 | 
			
		||||
  `product_id` int NOT NULL COMMENT '产品ID',
 | 
			
		||||
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户明',
 | 
			
		||||
  `order_no` varchar(30) NOT NULL COMMENT '订单ID',
 | 
			
		||||
  `trade_no` varchar(60) NOT NULL COMMENT '支付平台交易流水号',
 | 
			
		||||
  `subject` varchar(100) NOT NULL COMMENT '订单产品',
 | 
			
		||||
  `amount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '订单金额',
 | 
			
		||||
  `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '订单状态(0:待支付,1:已扫码,2:支付失败)',
 | 
			
		||||
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '备注',
 | 
			
		||||
  `pay_time` int DEFAULT NULL COMMENT '支付时间',
 | 
			
		||||
  `pay_way` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '支付方式',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL,
 | 
			
		||||
  `deleted_at` datetime DEFAULT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='充值订单表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_power_logs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_power_logs`;
 | 
			
		||||
CREATE TABLE `chatgpt_power_logs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户ID',
 | 
			
		||||
  `username` varchar(30) NOT NULL COMMENT '用户名',
 | 
			
		||||
  `type` tinyint(1) NOT NULL COMMENT '类型(1:充值,2:消费,3:退费)',
 | 
			
		||||
  `amount` smallint NOT NULL COMMENT '算力数值',
 | 
			
		||||
  `balance` int NOT NULL COMMENT '余额',
 | 
			
		||||
  `model` varchar(30) NOT NULL COMMENT '模型',
 | 
			
		||||
  `remark` varchar(255) NOT NULL COMMENT '备注',
 | 
			
		||||
  `mark` tinyint(1) NOT NULL COMMENT '资金类型(0:支出,1:收入)',
 | 
			
		||||
  `created_at` datetime NOT NULL COMMENT '创建时间'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户算力消费日志';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_products`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_products`;
 | 
			
		||||
CREATE TABLE `chatgpt_products` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `name` varchar(30) NOT NULL COMMENT '名称',
 | 
			
		||||
  `price` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '价格',
 | 
			
		||||
  `discount` decimal(10,2) NOT NULL DEFAULT '0.00' COMMENT '优惠金额',
 | 
			
		||||
  `days` smallint NOT NULL DEFAULT '0' COMMENT '延长天数',
 | 
			
		||||
  `power` int NOT NULL DEFAULT '0' COMMENT '增加算力值',
 | 
			
		||||
  `enabled` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否启动',
 | 
			
		||||
  `sales` int NOT NULL DEFAULT '0' COMMENT '销量',
 | 
			
		||||
  `sort_num` tinyint NOT NULL DEFAULT '0' COMMENT '排序',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL,
 | 
			
		||||
  `url` varchar(255) DEFAULT NULL COMMENT '跳转地址'
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='会员套餐表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_products`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_products` (`id`, `name`, `price`, `discount`, `days`, `power`, `enabled`, `sales`, `sort_num`, `created_at`, `updated_at`, `url`) VALUES
 | 
			
		||||
(1, 'VIP会员1个月', 19.90, 19.80, 30, 0, 1, 3, 0, '2023-08-28 10:48:57', '2024-01-07 12:00:35', NULL),
 | 
			
		||||
(2, 'VIP会员3个月', 140.00, 30.00, 90, 0, 1, 0, 0, '2023-08-28 10:52:22', '2024-01-07 12:00:40', NULL),
 | 
			
		||||
(3, 'VIP会员6个月', 290.00, 100.00, 180, 0, 1, 0, 0, '2023-08-28 10:53:39', '2024-01-07 12:00:45', NULL),
 | 
			
		||||
(4, 'VIP会员12个月', 580.00, 200.00, 365, 0, 1, 0, 0, '2023-08-28 10:54:15', '2024-01-07 12:00:52', NULL),
 | 
			
		||||
(5, '100次点卡', 10.00, 3.00, 0, 100, 1, 6, 0, '2023-08-28 10:55:08', '2023-11-08 17:32:42', NULL);
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_rewards`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_rewards`;
 | 
			
		||||
CREATE TABLE `chatgpt_rewards` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `tx_id` char(36) NOT NULL COMMENT '交易 ID',
 | 
			
		||||
  `amount` decimal(10,2) NOT NULL COMMENT '打赏金额',
 | 
			
		||||
  `remark` varchar(80) NOT NULL COMMENT '备注',
 | 
			
		||||
  `status` tinyint(1) NOT NULL COMMENT '核销状态,0:未核销,1:已核销',
 | 
			
		||||
  `exchange` varchar(255) NOT NULL COMMENT '兑换详情(json)',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户打赏';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_sd_jobs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_sd_jobs`;
 | 
			
		||||
CREATE TABLE `chatgpt_sd_jobs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户 ID',
 | 
			
		||||
  `type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT 'txt2img' COMMENT '任务类别',
 | 
			
		||||
  `task_id` char(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '任务 ID',
 | 
			
		||||
  `prompt` varchar(2000) NOT NULL COMMENT '会话提示词',
 | 
			
		||||
  `img_url` varchar(255) DEFAULT NULL COMMENT '图片URL',
 | 
			
		||||
  `params` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci COMMENT '绘画参数json',
 | 
			
		||||
  `progress` smallint DEFAULT '0' COMMENT '任务进度',
 | 
			
		||||
  `publish` tinyint(1) NOT NULL COMMENT '是否发布',
 | 
			
		||||
  `err_msg` varchar(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '错误信息',
 | 
			
		||||
  `power` smallint NOT NULL DEFAULT '0' COMMENT '消耗算力',
 | 
			
		||||
  `created_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='Stable Diffusion 任务表';
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_users`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_users`;
 | 
			
		||||
CREATE TABLE `chatgpt_users` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `username` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '用户名',
 | 
			
		||||
  `nickname` varchar(30) NOT NULL COMMENT '昵称',
 | 
			
		||||
  `password` char(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '密码',
 | 
			
		||||
  `avatar` varchar(100) NOT NULL COMMENT '头像',
 | 
			
		||||
  `salt` char(12) NOT NULL COMMENT '密码盐',
 | 
			
		||||
  `power` int NOT NULL DEFAULT '0' COMMENT '剩余算力',
 | 
			
		||||
  `expired_time` int NOT NULL COMMENT '用户过期时间',
 | 
			
		||||
  `status` tinyint(1) NOT NULL COMMENT '当前状态',
 | 
			
		||||
  `chat_config_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天配置json',
 | 
			
		||||
  `chat_roles_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '聊天角色 json',
 | 
			
		||||
  `chat_models_json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'AI模型 json',
 | 
			
		||||
  `last_login_at` int NOT NULL COMMENT '最后登录时间',
 | 
			
		||||
  `vip` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否会员',
 | 
			
		||||
  `last_login_ip` char(16) NOT NULL COMMENT '最后登录 IP',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户表';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转存表中的数据 `chatgpt_users`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
INSERT INTO `chatgpt_users` (`id`, `username`, `nickname`, `password`, `avatar`, `salt`, `power`, `expired_time`, `status`, `chat_config_json`, `chat_roles_json`, `chat_models_json`, `last_login_at`, `vip`, `last_login_ip`, `created_at`, `updated_at`) VALUES
 | 
			
		||||
(4, '18575670125', '极客学长@534641', 'ccc3fb7ab61b8b5d096a4a166ae21d121fc38c71bbd1be6173d9ab973214a63b', 'http://localhost:5678/static/upload/2024/5/1715725189044438.png', 'ueedue5l', 1985, 1769416236, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"elon_musk\",\"girl_friend\",\"lu_xun\",\"red_book\",\"psychiatrist\",\"translator\",\"weekly_report\",\"artist\",\"dou_yin\",\"english_trainer\",\"gpt\",\"kong_zi\",\"programmer\",\"seller\",\"steve_jobs\",\"teacher\"]', '[1]', 1715960703, 1, '::1', '2023-06-12 16:47:17', '2024-05-19 08:36:35'),
 | 
			
		||||
(91, '18575670126', '极客学长@623251', '5e4050b8dd403f593260395d9edeb9f273dbe92d15dfdd929c4a182e95da10c4', '/images/avatar/user.png', '6fj0otl8', 10, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\"]', '[1]', 1697184324, 0, '::1', '2023-10-13 16:01:56', '2024-01-05 21:28:38'),
 | 
			
		||||
(97, '13888888888', '极客学长@630521', 'c886771ae3fca0464aef3476c5368bb43feb758cc388cfb00f94ba38b1ded0f1', '/images/avatar/user.png', '35umf21c', 1099, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\"]', '[1]', 1711152776, 0, '::1', '2023-11-25 17:20:10', '2024-03-23 16:20:24'),
 | 
			
		||||
(98, '13777777777', '极客学长@900743', '03d4e5eefde1cba81b212247cb80aa89920a3f564cc71a266eb906f46b2bf697', '/images/avatar/user.png', 'cgk2aaen', 999, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\"]', '[1]', 0, 0, '', '2023-11-25 17:21:02', '2024-03-23 16:19:02'),
 | 
			
		||||
(99, '13999999999', '极客学长@378449', '40ea5cf3425967c426e4b93fae657784b6d23ce63857c9e222404a71266af333', '/images/avatar/user.png', 'uai5sc9e', 10, 0, 1, '{\"api_keys\":{\"Azure\":\"\",\"ChatGLM\":\"\",\"OpenAI\":\"\"}}', '[\"gpt\"]', '[1]', 0, 0, '', '2023-11-25 17:21:30', '2024-01-05 21:28:38'),
 | 
			
		||||
(104, '1333333333', '极客学长@904857', '094065fd732f4171bb2de8cb116fe577dfd2f5393dd7910fa2ec56e17c9f5f75', '/images/avatar/user.png', '19hakk06', 100, 0, 1, '', '[\"gpt\"]', '[1,12,3]', 0, 0, '', '2024-03-23 16:14:05', '2024-03-23 16:14:05');
 | 
			
		||||
 | 
			
		||||
-- --------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的结构 `chatgpt_user_login_logs`
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
DROP TABLE IF EXISTS `chatgpt_user_login_logs`;
 | 
			
		||||
CREATE TABLE `chatgpt_user_login_logs` (
 | 
			
		||||
  `id` int NOT NULL,
 | 
			
		||||
  `user_id` int NOT NULL COMMENT '用户ID',
 | 
			
		||||
  `username` varchar(30) NOT NULL COMMENT '用户名',
 | 
			
		||||
  `login_ip` char(16) NOT NULL COMMENT '登录IP',
 | 
			
		||||
  `login_address` varchar(30) NOT NULL COMMENT '登录地址',
 | 
			
		||||
  `created_at` datetime NOT NULL,
 | 
			
		||||
  `updated_at` datetime NOT NULL
 | 
			
		||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='用户登录日志';
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 转储表的索引
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_admin_users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_admin_users`
 | 
			
		||||
  ADD PRIMARY KEY (`id`) USING BTREE,
 | 
			
		||||
  ADD UNIQUE KEY `username` (`username`) USING BTREE;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_api_keys`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_api_keys`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_chat_history`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_history`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD KEY `chat_id` (`chat_id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_chat_items`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_items`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `chat_id` (`chat_id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_chat_models`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_models`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_chat_roles`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_roles`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `marker` (`marker`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_configs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_configs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `marker` (`marker`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_dall_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_dall_jobs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_files`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_files`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_functions`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_functions`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `name` (`name`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_invite_codes`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_invite_codes`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `code` (`code`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_invite_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_invite_logs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_menus`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_menus`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_mj_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `task_id` (`task_id`),
 | 
			
		||||
  ADD KEY `message_id` (`message_id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_orders`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_orders`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `order_no` (`order_no`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_power_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_power_logs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_products`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_products`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_rewards`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_rewards`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `tx_id` (`tx_id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_sd_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_sd_jobs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `task_id` (`task_id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_users`
 | 
			
		||||
  ADD PRIMARY KEY (`id`),
 | 
			
		||||
  ADD UNIQUE KEY `username` (`username`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 表的索引 `chatgpt_user_login_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_user_login_logs`
 | 
			
		||||
  ADD PRIMARY KEY (`id`);
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 在导出的表使用AUTO_INCREMENT
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_admin_users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_admin_users`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=108;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_api_keys`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_api_keys`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_history`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_history`
 | 
			
		||||
  MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_items`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_items`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_models`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_models`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=17;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_chat_roles`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_chat_roles`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=127;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_configs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_configs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=4;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_dall_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_dall_jobs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_files`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_files`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_functions`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_functions`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_codes`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_invite_codes`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_invite_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_invite_logs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_menus`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_menus`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=16;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_mj_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_orders`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_orders`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_power_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_power_logs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_products`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_products`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_rewards`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_rewards`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_sd_jobs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_sd_jobs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_users`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_users`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=105;
 | 
			
		||||
 | 
			
		||||
--
 | 
			
		||||
-- 使用表AUTO_INCREMENT `chatgpt_user_login_logs`
 | 
			
		||||
--
 | 
			
		||||
ALTER TABLE `chatgpt_user_login_logs`
 | 
			
		||||
  MODIFY `id` int NOT NULL AUTO_INCREMENT;
 | 
			
		||||
COMMIT;
 | 
			
		||||
 | 
			
		||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
 | 
			
		||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
 | 
			
		||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
 | 
			
		||||
							
								
								
									
										3
									
								
								database/update-v4.0.7.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								database/update-v4.0.7.sql
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
ALTER TABLE `chatgpt_mj_jobs` CHANGE `err_msg` `err_msg` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '错误信息';
 | 
			
		||||
ALTER TABLE `chatgpt_sd_jobs` CHANGE `err_msg` `err_msg` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '错误信息';
 | 
			
		||||
ALTER TABLE `chatgpt_dall_jobs` CHANGE `err_msg` `err_msg` VARCHAR(512) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '错误信息';
 | 
			
		||||
@@ -15,8 +15,8 @@ server {
 | 
			
		||||
#     ssl_prefer_server_ciphers on;
 | 
			
		||||
 | 
			
		||||
    # 日志地址
 | 
			
		||||
    access_log  /var/log/access.log;
 | 
			
		||||
    error_log /var/log/error.log;
 | 
			
		||||
    access_log  /var/log/nginx/access.log;
 | 
			
		||||
    error_log /var/log/nginx/error.log;
 | 
			
		||||
 | 
			
		||||
    index index.html;
 | 
			
		||||
    root /var/www/app/dist; # 这里改成前端静态页面的地址
 | 
			
		||||
 
 | 
			
		||||
@@ -6,4 +6,4 @@ VUE_APP_ADMIN_USER=admin
 | 
			
		||||
VUE_APP_ADMIN_PASS=admin123
 | 
			
		||||
VUE_APP_KEY_PREFIX=ChatPLUS_DEV_
 | 
			
		||||
VUE_APP_TITLE="Geek-AI 创作系统"
 | 
			
		||||
VUE_APP_VERSION=v4.0.6
 | 
			
		||||
VUE_APP_VERSION=v4.0.7
 | 
			
		||||
 
 | 
			
		||||
@@ -2,4 +2,4 @@ VUE_APP_API_HOST=
 | 
			
		||||
VUE_APP_WS_HOST=
 | 
			
		||||
VUE_APP_KEY_PREFIX=ChatPLUS_
 | 
			
		||||
VUE_APP_TITLE="Geek-AI 创作系统"
 | 
			
		||||
VUE_APP_VERSION=v4.0.6
 | 
			
		||||
VUE_APP_VERSION=v4.0.7
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										47
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										47
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -24,14 +24,16 @@
 | 
			
		||||
        "markdown-it-mathjax": "^2.0.0",
 | 
			
		||||
        "markmap-common": "^0.16.0",
 | 
			
		||||
        "markmap-lib": "^0.16.1",
 | 
			
		||||
        "markmap-toolbar": "^0.17.0",
 | 
			
		||||
        "markmap-view": "^0.16.0",
 | 
			
		||||
        "md-editor-v3": "^2.2.1",
 | 
			
		||||
        "mitt": "^3.0.1",
 | 
			
		||||
        "pinia": "^2.1.4",
 | 
			
		||||
        "qrcode": "^1.5.3",
 | 
			
		||||
        "qs": "^6.11.1",
 | 
			
		||||
        "sortablejs": "^1.15.0",
 | 
			
		||||
        "three": "^0.128.0",
 | 
			
		||||
        "v3-waterfall": "^1.2.1",
 | 
			
		||||
        "v3-waterfall": "^1.3.3",
 | 
			
		||||
        "vant": "^4.5.0",
 | 
			
		||||
        "vue": "^3.2.13",
 | 
			
		||||
        "vue-router": "^4.0.15"
 | 
			
		||||
@@ -8335,6 +8337,18 @@
 | 
			
		||||
        "js-yaml": "bin/js-yaml.js"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/markmap-toolbar": {
 | 
			
		||||
      "version": "0.17.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/markmap-toolbar/-/markmap-toolbar-0.17.0.tgz",
 | 
			
		||||
      "integrity": "sha512-zRkg+pYtjDefJ4lSG0KownAN3eqkJcrTei+HbobBWsWTsc7qdUMn2Ewd97SFHCkGoo1nrG0aW7dzDP6lHWuDkw==",
 | 
			
		||||
      "dependencies": {
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@gera2ld/jsx-dom": "^2.2.2"
 | 
			
		||||
      },
 | 
			
		||||
      "peerDependencies": {
 | 
			
		||||
        "markmap-common": "*"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/markmap-view": {
 | 
			
		||||
      "version": "0.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/markmap-view/-/markmap-view-0.16.0.tgz",
 | 
			
		||||
@@ -8592,6 +8606,11 @@
 | 
			
		||||
        "node": ">=8"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/mitt": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/mkdirp": {
 | 
			
		||||
      "version": "0.5.6",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
 | 
			
		||||
@@ -11513,9 +11532,9 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/v3-waterfall": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-zjfT1FuHupsAahvS4mr3Yb8k2SHB8srW6st+/cBXwrsyhbCcj8Qhb1QtNUuEIx/tbpLQrMpxtJunZXkaKBfAEA=="
 | 
			
		||||
      "version": "1.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.3.3.tgz",
 | 
			
		||||
      "integrity": "sha512-jUmp0xpHGkEcUxaYKGRtI5b2NvogxI/UrfoCLmpTi0UbQndDdqjwufxJvWwiJjwZQyOIPpnq9ZOFtkBwxchq3Q=="
 | 
			
		||||
    },
 | 
			
		||||
    "node_modules/v8-compile-cache": {
 | 
			
		||||
      "version": "2.3.0",
 | 
			
		||||
@@ -19059,6 +19078,15 @@
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "markmap-toolbar": {
 | 
			
		||||
      "version": "0.17.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/markmap-toolbar/-/markmap-toolbar-0.17.0.tgz",
 | 
			
		||||
      "integrity": "sha512-zRkg+pYtjDefJ4lSG0KownAN3eqkJcrTei+HbobBWsWTsc7qdUMn2Ewd97SFHCkGoo1nrG0aW7dzDP6lHWuDkw==",
 | 
			
		||||
      "requires": {
 | 
			
		||||
        "@babel/runtime": "^7.22.6",
 | 
			
		||||
        "@gera2ld/jsx-dom": "^2.2.2"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "markmap-view": {
 | 
			
		||||
      "version": "0.16.0",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/markmap-view/-/markmap-view-0.16.0.tgz",
 | 
			
		||||
@@ -19264,6 +19292,11 @@
 | 
			
		||||
        "yallist": "^4.0.0"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "mitt": {
 | 
			
		||||
      "version": "3.0.1",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/mitt/-/mitt-3.0.1.tgz",
 | 
			
		||||
      "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
 | 
			
		||||
    },
 | 
			
		||||
    "mkdirp": {
 | 
			
		||||
      "version": "0.5.6",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz",
 | 
			
		||||
@@ -21507,9 +21540,9 @@
 | 
			
		||||
      "dev": true
 | 
			
		||||
    },
 | 
			
		||||
    "v3-waterfall": {
 | 
			
		||||
      "version": "1.2.1",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.2.1.tgz",
 | 
			
		||||
      "integrity": "sha512-zjfT1FuHupsAahvS4mr3Yb8k2SHB8srW6st+/cBXwrsyhbCcj8Qhb1QtNUuEIx/tbpLQrMpxtJunZXkaKBfAEA=="
 | 
			
		||||
      "version": "1.3.3",
 | 
			
		||||
      "resolved": "https://registry.npmmirror.com/v3-waterfall/-/v3-waterfall-1.3.3.tgz",
 | 
			
		||||
      "integrity": "sha512-jUmp0xpHGkEcUxaYKGRtI5b2NvogxI/UrfoCLmpTi0UbQndDdqjwufxJvWwiJjwZQyOIPpnq9ZOFtkBwxchq3Q=="
 | 
			
		||||
    },
 | 
			
		||||
    "v8-compile-cache": {
 | 
			
		||||
      "version": "2.3.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@
 | 
			
		||||
    "compressorjs": "^1.2.1",
 | 
			
		||||
    "core-js": "^3.8.3",
 | 
			
		||||
    "echarts": "^5.5.0",
 | 
			
		||||
    "element-plus": "^2.3.0",
 | 
			
		||||
    "element-plus": "^2.4.0",
 | 
			
		||||
    "good-storage": "^1.1.1",
 | 
			
		||||
    "highlight.js": "^11.7.0",
 | 
			
		||||
    "json-bigint": "^1.0.0",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								web/public/images/menu/bbs.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/images/menu/bbs.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 1.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								web/public/images/menu/docs.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								web/public/images/menu/docs.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 802 B  | 
@@ -1,12 +1,11 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-config-provider :locale="zhCn">
 | 
			
		||||
  <el-config-provider>
 | 
			
		||||
    <router-view/>
 | 
			
		||||
  </el-config-provider>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {ElConfigProvider} from 'element-plus';
 | 
			
		||||
import zhCn from 'element-plus/es/locale/lang/zh-cn';
 | 
			
		||||
 | 
			
		||||
const debounce = (fn, delay) => {
 | 
			
		||||
  let timer
 | 
			
		||||
@@ -42,6 +41,8 @@ html, body {
 | 
			
		||||
  font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif
 | 
			
		||||
  -webkit-font-smoothing: antialiased;
 | 
			
		||||
  text-rendering: optimizeLegibility;
 | 
			
		||||
 | 
			
		||||
  --primary-color: #21aa93
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-overlay-dialog {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,6 @@
 | 
			
		||||
.page-apps {
 | 
			
		||||
  background-color: #282c34;
 | 
			
		||||
  height 100vh
 | 
			
		||||
 | 
			
		||||
  .title {
 | 
			
		||||
    text-align center
 | 
			
		||||
    background-color #25272d
 | 
			
		||||
    font-size 24px
 | 
			
		||||
    color #ffffff
 | 
			
		||||
    padding 10px
 | 
			
		||||
    border-bottom 1px solid #3c3c3c
 | 
			
		||||
  }
 | 
			
		||||
  height 100%
 | 
			
		||||
 | 
			
		||||
  .inner {
 | 
			
		||||
    display flex
 | 
			
		||||
@@ -19,51 +10,71 @@
 | 
			
		||||
    overflow-x hidden
 | 
			
		||||
 | 
			
		||||
    .list-box {
 | 
			
		||||
      .app-item {
 | 
			
		||||
        border 1px solid #666666
 | 
			
		||||
        border-radius 6px
 | 
			
		||||
        overflow hidden
 | 
			
		||||
        transition: all 0.3s ease; /* 添加过渡效果 */
 | 
			
		||||
      .item {
 | 
			
		||||
        display flex
 | 
			
		||||
        flex-flow row
 | 
			
		||||
        border 1px solid #3c3c3c
 | 
			
		||||
        padding 10px
 | 
			
		||||
 | 
			
		||||
        .el-image {
 | 
			
		||||
          padding 6px
 | 
			
		||||
 | 
			
		||||
          .el-image__inner {
 | 
			
		||||
            border-radius 10px
 | 
			
		||||
          }
 | 
			
		||||
        .image {
 | 
			
		||||
          width 80px
 | 
			
		||||
          height 80px
 | 
			
		||||
          min-width 80px
 | 
			
		||||
          border-radius 5px
 | 
			
		||||
          overflow hidden
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .title {
 | 
			
		||||
        .inner {
 | 
			
		||||
          display flex
 | 
			
		||||
          padding 10px
 | 
			
		||||
          flex-flow column
 | 
			
		||||
          padding 0 0 0 10px
 | 
			
		||||
          width 100%
 | 
			
		||||
 | 
			
		||||
          .name {
 | 
			
		||||
            width 100%
 | 
			
		||||
          .info {
 | 
			
		||||
            text-align left
 | 
			
		||||
            font-size 16px
 | 
			
		||||
            font-weight bold
 | 
			
		||||
            color #47fff1
 | 
			
		||||
 | 
			
		||||
            .info-title {
 | 
			
		||||
              color var(--el-text-color)
 | 
			
		||||
              font-size 1.25rem
 | 
			
		||||
              line-height 1.75rem
 | 
			
		||||
              letter-spacing: .025em;
 | 
			
		||||
              font-weight: 600;
 | 
			
		||||
              word-break: break-all;
 | 
			
		||||
              overflow: hidden;
 | 
			
		||||
              display: -webkit-box;
 | 
			
		||||
              -webkit-box-orient: vertical;
 | 
			
		||||
              -webkit-line-clamp: 1;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .info-text {
 | 
			
		||||
              padding 8px 0
 | 
			
		||||
              overflow: hidden;
 | 
			
		||||
              display: -webkit-box;
 | 
			
		||||
              -webkit-box-orient: vertical;
 | 
			
		||||
              -webkit-line-clamp: 2;
 | 
			
		||||
              word-break: break-all;
 | 
			
		||||
              height 34px
 | 
			
		||||
              font-size: .875rem;
 | 
			
		||||
              color #999999
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .opt {
 | 
			
		||||
            position: relative;
 | 
			
		||||
            width 100%
 | 
			
		||||
            top -5px
 | 
			
		||||
          .btn {
 | 
			
		||||
            margin-top 10px
 | 
			
		||||
            display flex
 | 
			
		||||
            justify-content right
 | 
			
		||||
 | 
			
		||||
            .el-button {
 | 
			
		||||
              margin-left 10px
 | 
			
		||||
 | 
			
		||||
              .el-icon {
 | 
			
		||||
                margin-right 5px
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .hello-msg {
 | 
			
		||||
          height 60px
 | 
			
		||||
          padding 10px
 | 
			
		||||
          font-size 14px
 | 
			
		||||
          color #999999
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
          box-shadow: 0 0 10px rgba(71, 255, 241, 0.6); /* 添加阴影效果 */
 | 
			
		||||
          transform: translateY(-10px); /* 向上移动10像素 */
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,313 +1,378 @@
 | 
			
		||||
#app {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside {
 | 
			
		||||
  background-color: #252526;
 | 
			
		||||
    background-color: #252526;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .title-box {
 | 
			
		||||
  padding: 6px 10px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
    padding: 6px 10px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .title-box span {
 | 
			
		||||
  padding-top: 5px;
 | 
			
		||||
  padding-left: 10px;
 | 
			
		||||
    padding-top: 5px;
 | 
			
		||||
    padding-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-flow: column;
 | 
			
		||||
  background-color: #28292a;
 | 
			
		||||
  border-top: 1px solid #2f3032;
 | 
			
		||||
  border-right: 1px solid #2f3032;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-flow: column;
 | 
			
		||||
    background-color: #28292a;
 | 
			
		||||
    border-top: 1px solid #2f3032;
 | 
			
		||||
    border-right: 1px solid #2f3032;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .search-box {
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
  padding: 10px 15px;
 | 
			
		||||
    flex-wrap: wrap;
 | 
			
		||||
    padding: 10px 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .search-box .el-input__wrapper {
 | 
			
		||||
  background-color: #363535;
 | 
			
		||||
  box-shadow: none;
 | 
			
		||||
    background-color: #363535;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list ::-webkit-scrollbar {
 | 
			
		||||
  width: 0;
 | 
			
		||||
  height: 0;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  overflow-y: scroll;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    overflow-y: scroll;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  justify-content: flex-start;
 | 
			
		||||
  padding: 8px 12px;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    justify-content: flex-start;
 | 
			
		||||
    padding: 8px 12px;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item:hover {
 | 
			
		||||
  background-color: #343540;
 | 
			
		||||
    background-color: #343540;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item .avatar {
 | 
			
		||||
  width: 28px;
 | 
			
		||||
  height: 28px;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
    width: 28px;
 | 
			
		||||
    height: 28px;
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title-input {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  margin-top: 4px;
 | 
			
		||||
  margin-left: 10px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  width: 190px;
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    margin-top: 4px;
 | 
			
		||||
    margin-left: 10px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
    width: 190px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item .chat-title {
 | 
			
		||||
  color: #c1c1c1;
 | 
			
		||||
  padding: 5px 10px;
 | 
			
		||||
  max-width: 220px;
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  white-space: nowrap;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
    color: #c1c1c1;
 | 
			
		||||
    padding: 5px 10px;
 | 
			
		||||
    max-width: 220px;
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    text-overflow: ellipsis;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item .btn {
 | 
			
		||||
  display: none;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 2px;
 | 
			
		||||
  top: 16px;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
    display: none;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 2px;
 | 
			
		||||
    top: 16px;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item .btn .el-icon {
 | 
			
		||||
  margin-right: 8px;
 | 
			
		||||
    margin-right: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item.active {
 | 
			
		||||
  background-color: #343540;
 | 
			
		||||
    background-color: #343540;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .chat-list .content .chat-list-item.active .btn {
 | 
			
		||||
  display: inline;
 | 
			
		||||
    display: inline;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: flex-end;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  padding: 0 20px 10px 20px;
 | 
			
		||||
  border-top: 1px solid #3c3c3c;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: flex-end;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    padding: 0 20px 10px 20px;
 | 
			
		||||
    border-top: 1px solid #3c3c3c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box .user-info {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  padding-top: 10px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    padding-top: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  display: flex;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    display: flex;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-image {
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  border-radius: 5px;
 | 
			
		||||
    width: 20px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
    border-radius: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .username {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  line-height: 22px;
 | 
			
		||||
  width: 230px;
 | 
			
		||||
  padding-left: 10px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    line-height: 22px;
 | 
			
		||||
    width: 230px;
 | 
			
		||||
    padding-left: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-aside .tool-box .user-info .el-dropdown-link .el-icon {
 | 
			
		||||
  color: #ccc;
 | 
			
		||||
  line-height: 24px;
 | 
			
		||||
    color: #ccc;
 | 
			
		||||
    line-height: 24px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  --el-main-padding: 0;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    --el-main-padding: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  height: 50px;
 | 
			
		||||
  background-color: #28292a;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 50px;
 | 
			
		||||
    background-color: #28292a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .chat-config {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  padding-top: 10px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    padding-top: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .chat-config .role-select-label {
 | 
			
		||||
  color: #fff;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .chat-config .el-select {
 | 
			
		||||
  max-width: 150px;
 | 
			
		||||
  margin-right: 10px;
 | 
			
		||||
    max-width: 150px;
 | 
			
		||||
    margin-right: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .chat-config .role-select {
 | 
			
		||||
  max-width: 130px;
 | 
			
		||||
    max-width: 130px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .chat-config .el-button .el-icon {
 | 
			
		||||
  margin-right: 5px;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .iconfont {
 | 
			
		||||
  margin-right: 5px;
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .is-circle {
 | 
			
		||||
  margin-left: 5px;
 | 
			
		||||
    margin-left: 5px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-head .is-circle .iconfont {
 | 
			
		||||
  margin-right: 0;
 | 
			
		||||
    margin-right: 0;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box {
 | 
			
		||||
  min-width: 0;
 | 
			
		||||
  flex: 1;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  border-left: 1px solid #4f4f4f;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box {
 | 
			
		||||
    min-width: 0;
 | 
			
		||||
    flex: 1;
 | 
			
		||||
    background-color: #fff;
 | 
			
		||||
    border-left: 1px solid #4f4f4f;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container ::-webkit-scrollbar {
 | 
			
		||||
  width: 0;
 | 
			
		||||
  height: 0;
 | 
			
		||||
  background-color: transparent;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container ::-webkit-scrollbar {
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .chat-box {
 | 
			
		||||
  overflow-y: scroll;
 | 
			
		||||
  --content-font-size: 16px;
 | 
			
		||||
  --content-color: #c1c1c1;
 | 
			
		||||
  font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
 | 
			
		||||
  padding: 0 0 50px 0;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .chat-box {
 | 
			
		||||
    overflow-y: scroll;
 | 
			
		||||
    --content-font-size: 16px;
 | 
			
		||||
    --content-color: #c1c1c1;
 | 
			
		||||
    font-family: 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
 | 
			
		||||
    padding: 0 0 50px 0;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .chat-box .chat-line {
 | 
			
		||||
  font-size: 14px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  align-items: flex-start;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .chat-box .chat-line {
 | 
			
		||||
    font-size: 14px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    align-items: flex-start;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .re-generate {
 | 
			
		||||
  position: relative;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .re-generate {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .re-generate .btn-box {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  bottom: 10px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .re-generate .btn-box {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    bottom: 10px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .re-generate .btn-box .el-button .el-icon {
 | 
			
		||||
  margin-right: 5px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .re-generate .btn-box .el-button .el-icon {
 | 
			
		||||
    margin-right: 5px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box {
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  box-shadow: 0 2px 15px rgba(0,0,0,0.1);
 | 
			
		||||
  padding: 0 15px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box {
 | 
			
		||||
    background-color: #fff;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
 | 
			
		||||
    padding: 0 15px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box .input-container {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  border: none;
 | 
			
		||||
  padding: 10px 0;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  position: relative;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box .input-container {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    border: none;
 | 
			
		||||
    padding: 10px 0;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: center;
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box .input-container .el-textarea .el-textarea__inner::-webkit-scrollbar {
 | 
			
		||||
  width: 0;
 | 
			
		||||
  height: 0;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box .input-container .el-textarea .el-textarea__inner::-webkit-scrollbar {
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box .input-container .select-file {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 48px;
 | 
			
		||||
  top: 20px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box .input-container .select-file {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 48px;
 | 
			
		||||
    top: 20px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  right: 12px;
 | 
			
		||||
  top: 20px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box .input-container .send-btn {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    right: 12px;
 | 
			
		||||
    top: 20px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container .input-box .input-container .send-btn .el-button {
 | 
			
		||||
  padding: 8px 5px;
 | 
			
		||||
  border-radius: 6px;
 | 
			
		||||
  background: #19c37d;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
  font-size: 20px;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container .input-box .input-container .send-btn .el-button {
 | 
			
		||||
    padding: 8px 5px;
 | 
			
		||||
    border-radius: 6px;
 | 
			
		||||
    background: #19c37d;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
}
 | 
			
		||||
#app .common-layout .el-main .right-box #container::-webkit-scrollbar {
 | 
			
		||||
  width: 0;
 | 
			
		||||
  height: 0;
 | 
			
		||||
 | 
			
		||||
#app .common-layout .el-main .chat-box #container::-webkit-scrollbar {
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .el-message-box {
 | 
			
		||||
  width: 90%;
 | 
			
		||||
  max-width: 420px;
 | 
			
		||||
    width: 90%;
 | 
			
		||||
    max-width: 420px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#app .el-message {
 | 
			
		||||
  min-width: 100px;
 | 
			
		||||
  max-width: 600px;
 | 
			
		||||
    min-width: 100px;
 | 
			
		||||
    max-width: 600px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-select-dropdown__wrap .el-select-dropdown__item .role-option {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-flow: row;
 | 
			
		||||
  margin-top: 8px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-flow: row;
 | 
			
		||||
    margin-top: 8px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-select-dropdown__wrap .el-select-dropdown__item .role-option .el-image {
 | 
			
		||||
  width: 20px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  border-radius: 50%;
 | 
			
		||||
    width: 20px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
    border-radius: 50%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-select-dropdown__wrap .el-select-dropdown__item .role-option span {
 | 
			
		||||
  margin-left: 5px;
 | 
			
		||||
  height: 20px;
 | 
			
		||||
  line-height: 20px;
 | 
			
		||||
    margin-left: 5px;
 | 
			
		||||
    height: 20px;
 | 
			
		||||
    line-height: 20px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  background-color: #90ffc2;
 | 
			
		||||
  color: #000;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  border-radius: 10px;
 | 
			
		||||
  padding: 10px;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    background-color: #90ffc2;
 | 
			
		||||
    color: #000;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    border-radius: 10px;
 | 
			
		||||
    padding: 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .vip-logo .el-image {
 | 
			
		||||
  width: 40px;
 | 
			
		||||
  height: 40px;
 | 
			
		||||
  border-radius: 100%;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
    width: 40px;
 | 
			
		||||
    height: 40px;
 | 
			
		||||
    border-radius: 100%;
 | 
			
		||||
    background-color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .vip-info {
 | 
			
		||||
  padding: 0 10px 0 10px;
 | 
			
		||||
    padding: 0 10px 0 10px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .vip-info h4,
 | 
			
		||||
.account .vip-info p {
 | 
			
		||||
  margin: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .vip-info h4 {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
    font-weight: bold;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .vip-info p {
 | 
			
		||||
  color: #333;
 | 
			
		||||
    color: #333;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.account .pay-btn {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: right;
 | 
			
		||||
  align-items: center;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    justify-content: right;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-overlay-dialog .el-dialog .el-dialog__body .notice {
 | 
			
		||||
  padding: 0 20px 0 20px;
 | 
			
		||||
  line-height: 1.8;
 | 
			
		||||
    padding: 0 20px 0 20px;
 | 
			
		||||
    line-height: 1.8;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-overlay-dialog .el-dialog .el-dialog__body .notice .el-text {
 | 
			
		||||
  font-size: 16px;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dialog-service {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.dialog-service .el-image {
 | 
			
		||||
  width: 360px;
 | 
			
		||||
    width: 360px;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,35 +10,26 @@ $borderColor = #4676d0;
 | 
			
		||||
    // left side
 | 
			
		||||
 | 
			
		||||
    .el-aside {
 | 
			
		||||
      background-color: $sideBgColor;
 | 
			
		||||
      height 100vh
 | 
			
		||||
 | 
			
		||||
      .title-box {
 | 
			
		||||
        padding: 6px 10px;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        color: #ffffff;
 | 
			
		||||
        font-size: 20px;
 | 
			
		||||
 | 
			
		||||
        span {
 | 
			
		||||
          padding-top: 5px;
 | 
			
		||||
          padding-left: 10px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      //background-color: $sideBgColor;
 | 
			
		||||
      padding 10px
 | 
			
		||||
      width var(--el-aside-width, 320px)
 | 
			
		||||
 | 
			
		||||
      .chat-list {
 | 
			
		||||
        display: flex
 | 
			
		||||
        flex-flow: column
 | 
			
		||||
        background-color: #28292A
 | 
			
		||||
        border-top: 1px solid #2F3032
 | 
			
		||||
        border-right: 1px solid #2F3032
 | 
			
		||||
        //background-color: $sideBgColor
 | 
			
		||||
        border-radius 10px
 | 
			
		||||
        padding 10px 0
 | 
			
		||||
 | 
			
		||||
        .search-box {
 | 
			
		||||
          flex-wrap: wrap
 | 
			
		||||
          padding: 10px 15px;
 | 
			
		||||
          //background-color #343540
 | 
			
		||||
          padding: 10px 0;
 | 
			
		||||
 | 
			
		||||
          .el-input__wrapper {
 | 
			
		||||
            background-color: #363535;
 | 
			
		||||
          .search-input {
 | 
			
		||||
            --el-input-bg-color: #363535
 | 
			
		||||
            --el-input-border-color: #464545
 | 
			
		||||
            --el-input-focus-border-color: #47fff1
 | 
			
		||||
            --el-input-hover-border-color: #2DA39A
 | 
			
		||||
            box-shadow: none
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
@@ -52,9 +43,6 @@ $borderColor = #4676d0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .content {
 | 
			
		||||
          //display flex
 | 
			
		||||
          //flex-wrap: wrap;
 | 
			
		||||
          //flex-direction column
 | 
			
		||||
          width: 100%
 | 
			
		||||
          overflow-y: scroll
 | 
			
		||||
 | 
			
		||||
@@ -65,14 +53,17 @@ $borderColor = #4676d0;
 | 
			
		||||
            padding: 8px 12px
 | 
			
		||||
            //border-bottom: 1px solid #3c3c3c
 | 
			
		||||
            cursor: pointer
 | 
			
		||||
            border: 1px solid #3c3c3c
 | 
			
		||||
            margin-bottom 6px
 | 
			
		||||
            border-radius 5px
 | 
			
		||||
 | 
			
		||||
            &:hover {
 | 
			
		||||
              background-color #343540
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .avatar {
 | 
			
		||||
              width: 28px;
 | 
			
		||||
              height: 28px;
 | 
			
		||||
              width: 32px;
 | 
			
		||||
              height: 32px;
 | 
			
		||||
              border-radius: 50%;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -96,13 +87,17 @@ $borderColor = #4676d0;
 | 
			
		||||
              text-overflow: ellipsis;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .btn {
 | 
			
		||||
              display none
 | 
			
		||||
 | 
			
		||||
            .chat-opt {
 | 
			
		||||
              position: absolute;
 | 
			
		||||
              right: 2px;
 | 
			
		||||
              top: 16px;
 | 
			
		||||
              color #ffffff
 | 
			
		||||
 | 
			
		||||
              .el-dropdown-link {
 | 
			
		||||
                color #ffffff
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              .el-icon {
 | 
			
		||||
                margin-right 8px;
 | 
			
		||||
              }
 | 
			
		||||
@@ -111,10 +106,7 @@ $borderColor = #4676d0;
 | 
			
		||||
 | 
			
		||||
          .chat-list-item.active {
 | 
			
		||||
            background-color: #343540;
 | 
			
		||||
 | 
			
		||||
            .btn {
 | 
			
		||||
              display inline
 | 
			
		||||
            }
 | 
			
		||||
            border-color #21aa93
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
@@ -122,40 +114,12 @@ $borderColor = #4676d0;
 | 
			
		||||
 | 
			
		||||
      .tool-box {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        justify-content: flex-end;
 | 
			
		||||
        align-items: center;
 | 
			
		||||
        padding 0 20px 10px 20px;
 | 
			
		||||
        justify-content: center;
 | 
			
		||||
        padding-top 12px
 | 
			
		||||
        border-top 1px solid #3c3c3c;
 | 
			
		||||
 | 
			
		||||
        .user-info {
 | 
			
		||||
          width 100%
 | 
			
		||||
          padding-top 10px;
 | 
			
		||||
 | 
			
		||||
          .el-dropdown-link {
 | 
			
		||||
            width 100%;
 | 
			
		||||
            cursor: pointer
 | 
			
		||||
            display flex
 | 
			
		||||
 | 
			
		||||
            .el-image {
 | 
			
		||||
              width: 20px;
 | 
			
		||||
              height: 20px;
 | 
			
		||||
              border-radius: 5px;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .username {
 | 
			
		||||
              display flex
 | 
			
		||||
              line-height 22px;
 | 
			
		||||
              width 230px;
 | 
			
		||||
              padding-left 10px;
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .el-icon {
 | 
			
		||||
              color: #cccccc;
 | 
			
		||||
              line-height 24px;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
        .iconfont {
 | 
			
		||||
          margin-right 5px
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -165,56 +129,11 @@ $borderColor = #4676d0;
 | 
			
		||||
      --el-main-padding: 0;
 | 
			
		||||
      margin: 0;
 | 
			
		||||
 | 
			
		||||
      .chat-head {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 50px;
 | 
			
		||||
        background-color: #28292A
 | 
			
		||||
 | 
			
		||||
        .chat-config {
 | 
			
		||||
          display flex
 | 
			
		||||
          flex-direction row
 | 
			
		||||
          align-items: center;
 | 
			
		||||
          justify-content center;
 | 
			
		||||
          padding-top 10px;
 | 
			
		||||
 | 
			
		||||
          .role-select-label {
 | 
			
		||||
            color #ffffff
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .el-select {
 | 
			
		||||
            max-width 150px;
 | 
			
		||||
            margin-right 10px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .role-select {
 | 
			
		||||
            max-width 130px;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .el-button {
 | 
			
		||||
            .el-icon {
 | 
			
		||||
              margin-right 5px;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .iconfont {
 | 
			
		||||
          margin-right 5px;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .is-circle {
 | 
			
		||||
          margin-left 5px
 | 
			
		||||
 | 
			
		||||
          .iconfont {
 | 
			
		||||
            margin-right 0
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .right-box {
 | 
			
		||||
      .chat-box {
 | 
			
		||||
        min-width: 0;
 | 
			
		||||
        flex: 1;
 | 
			
		||||
        background-color: #ffffff
 | 
			
		||||
        border-left: 1px solid #4f4f4f
 | 
			
		||||
        background-color: var(--el-bg-color)
 | 
			
		||||
        color var(--el-text-color-primary)
 | 
			
		||||
 | 
			
		||||
        #container {
 | 
			
		||||
          overflow: hidden;
 | 
			
		||||
@@ -245,23 +164,6 @@ $borderColor = #4676d0;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .re-generate {
 | 
			
		||||
            position: relative;
 | 
			
		||||
            display: flex;
 | 
			
		||||
            justify-content: center;
 | 
			
		||||
 | 
			
		||||
            .btn-box {
 | 
			
		||||
              position: absolute
 | 
			
		||||
              bottom: 10px;
 | 
			
		||||
 | 
			
		||||
              .el-button {
 | 
			
		||||
                .el-icon {
 | 
			
		||||
                  margin-right 5px;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .input-box {
 | 
			
		||||
            background-color: #ffffff
 | 
			
		||||
            display: flex;
 | 
			
		||||
@@ -270,6 +172,26 @@ $borderColor = #4676d0;
 | 
			
		||||
            box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
 | 
			
		||||
            padding 0 15px;
 | 
			
		||||
 | 
			
		||||
            .tool-item {
 | 
			
		||||
              margin-right 15px
 | 
			
		||||
              border-radius: 6px;
 | 
			
		||||
              color: #19c37d;
 | 
			
		||||
              display flex
 | 
			
		||||
              justify-content center
 | 
			
		||||
              justify-items center
 | 
			
		||||
              padding 6px
 | 
			
		||||
              cursor pointer
 | 
			
		||||
              background #F2F2F2
 | 
			
		||||
 | 
			
		||||
              &:hover {
 | 
			
		||||
                background #D5FAD3
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              .iconfont {
 | 
			
		||||
                font-size: 24px;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .input-container {
 | 
			
		||||
              width 100%
 | 
			
		||||
              margin: 0;
 | 
			
		||||
@@ -280,7 +202,6 @@ $borderColor = #4676d0;
 | 
			
		||||
              position relative
 | 
			
		||||
 | 
			
		||||
              .el-textarea {
 | 
			
		||||
 | 
			
		||||
                .el-textarea__inner::-webkit-scrollbar {
 | 
			
		||||
                  width: 0;
 | 
			
		||||
                  height: 0;
 | 
			
		||||
@@ -301,8 +222,6 @@ $borderColor = #4676d0;
 | 
			
		||||
                .el-button {
 | 
			
		||||
                  padding 8px 5px;
 | 
			
		||||
                  border-radius 6px;
 | 
			
		||||
                  background: rgb(25, 195, 125)
 | 
			
		||||
                  color #ffffff;
 | 
			
		||||
                  font-size 20px;
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
@@ -399,12 +318,9 @@ $borderColor = #4676d0;
 | 
			
		||||
  .el-dialog {
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
      .notice {
 | 
			
		||||
        padding 0 20px 0 20px
 | 
			
		||||
        //padding 0 20px 0 20px
 | 
			
		||||
        line-height 1.8
 | 
			
		||||
 | 
			
		||||
        .el-text {
 | 
			
		||||
          font-size 16px
 | 
			
		||||
        }
 | 
			
		||||
        font-size 16px
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										188
									
								
								web/src/assets/css/home.styl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								web/src/assets/css/home.styl
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,188 @@
 | 
			
		||||
.home {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  width 100%
 | 
			
		||||
  flex-flow column
 | 
			
		||||
 | 
			
		||||
  .header {
 | 
			
		||||
    display flex
 | 
			
		||||
    justify-content space-between
 | 
			
		||||
    height 50px
 | 
			
		||||
    line-height 50px
 | 
			
		||||
    background-color #1E1F22
 | 
			
		||||
    padding-right 20px
 | 
			
		||||
 | 
			
		||||
    .banner {
 | 
			
		||||
      display flex
 | 
			
		||||
 | 
			
		||||
      .logo {
 | 
			
		||||
        display flex
 | 
			
		||||
        padding 5px
 | 
			
		||||
        cursor pointer
 | 
			
		||||
 | 
			
		||||
        .el-image {
 | 
			
		||||
          width 40px
 | 
			
		||||
          height 40px
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .title {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        color: #ffffff;
 | 
			
		||||
        font-size: 20px;
 | 
			
		||||
        padding 0 10px
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .navbar {
 | 
			
		||||
      display flex
 | 
			
		||||
      flex-flow row
 | 
			
		||||
 | 
			
		||||
      .link-button {
 | 
			
		||||
        margin-right 15px
 | 
			
		||||
        color #e1e1e1
 | 
			
		||||
        padding 0 10px
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
          background-color #414141
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .iconfont {
 | 
			
		||||
          font-size 24px
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .user-info {
 | 
			
		||||
        width 100%
 | 
			
		||||
        padding 5px 0;
 | 
			
		||||
 | 
			
		||||
        .el-dropdown-link {
 | 
			
		||||
          width 100%;
 | 
			
		||||
          cursor: pointer
 | 
			
		||||
          display flex
 | 
			
		||||
 | 
			
		||||
          .el-image {
 | 
			
		||||
            width: 36px;
 | 
			
		||||
            height: 36px;
 | 
			
		||||
            border-radius: 50%
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .el-icon {
 | 
			
		||||
            color: #cccccc;
 | 
			
		||||
            line-height 24px;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  .main {
 | 
			
		||||
    width 100%
 | 
			
		||||
    display flex
 | 
			
		||||
    flex-flow row
 | 
			
		||||
 | 
			
		||||
    .navigator {
 | 
			
		||||
      display flex
 | 
			
		||||
      flex-flow column
 | 
			
		||||
      width 50px
 | 
			
		||||
      padding 10px 1px
 | 
			
		||||
      border-right: 1px solid #3c3c3c
 | 
			
		||||
      background-color: #1E1F22
 | 
			
		||||
 | 
			
		||||
      .nav-items {
 | 
			
		||||
        margin-top: 10px;
 | 
			
		||||
        padding 0 5px
 | 
			
		||||
 | 
			
		||||
        li {
 | 
			
		||||
          margin-bottom 15px
 | 
			
		||||
 | 
			
		||||
          a {
 | 
			
		||||
            color #DADBDC
 | 
			
		||||
            border-radius 10px
 | 
			
		||||
            width 40px
 | 
			
		||||
            height 40px
 | 
			
		||||
            display flex
 | 
			
		||||
            justify-content center
 | 
			
		||||
            align-items center
 | 
			
		||||
            cursor pointer
 | 
			
		||||
            background-color #414348
 | 
			
		||||
 | 
			
		||||
            .el-image {
 | 
			
		||||
              border-radius 10px
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .iconfont {
 | 
			
		||||
              font-size 20px
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          a:hover, a.active {
 | 
			
		||||
            color #47fff1
 | 
			
		||||
            background-color #0F7A71
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .title {
 | 
			
		||||
            font-size: 12px
 | 
			
		||||
            padding-top: 5px
 | 
			
		||||
            color: #e5e7eb;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .active {
 | 
			
		||||
            color #47fff1
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .content {
 | 
			
		||||
      width: 100%
 | 
			
		||||
      overflow auto
 | 
			
		||||
      box-sizing: border-box
 | 
			
		||||
      background-color #282c34
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-popper {
 | 
			
		||||
  .more-menus {
 | 
			
		||||
    li {
 | 
			
		||||
      padding 10px 15px
 | 
			
		||||
      cursor pointer
 | 
			
		||||
      border-radius 5px
 | 
			
		||||
      margin 5px 0
 | 
			
		||||
 | 
			
		||||
      .el-image {
 | 
			
		||||
        position: relative
 | 
			
		||||
        top 5px
 | 
			
		||||
        right 5px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        background-color #f1f1f1
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    li.active {
 | 
			
		||||
      background-color #f1f1f1
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .user-info-menu {
 | 
			
		||||
    li {
 | 
			
		||||
      a {
 | 
			
		||||
        width 100%
 | 
			
		||||
        justify-content left
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
          text-decoration none !important
 | 
			
		||||
          color var(--el-primary-text-color)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
.page-mj {
 | 
			
		||||
  background-color: #282c34;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  height 100%
 | 
			
		||||
 | 
			
		||||
  .inner {
 | 
			
		||||
    display: flex;
 | 
			
		||||
@@ -235,7 +235,7 @@
 | 
			
		||||
 | 
			
		||||
    .task-list-box {
 | 
			
		||||
      width 100%
 | 
			
		||||
      padding 10px
 | 
			
		||||
      padding 0 10px 10px 10px
 | 
			
		||||
      color #ffffff
 | 
			
		||||
      overflow-x hidden
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,10 +10,11 @@
 | 
			
		||||
      border 1px solid #454545
 | 
			
		||||
      min-width 300px
 | 
			
		||||
      max-width 300px
 | 
			
		||||
      padding 10px
 | 
			
		||||
      padding 10px 10px 20px 10px
 | 
			
		||||
      border-radius 10px
 | 
			
		||||
      color #ffffff;
 | 
			
		||||
      font-size 14px
 | 
			
		||||
      overflow auto
 | 
			
		||||
 | 
			
		||||
      h2 {
 | 
			
		||||
        font-weight: bold;
 | 
			
		||||
@@ -83,7 +84,7 @@
 | 
			
		||||
 | 
			
		||||
    .task-list-box {
 | 
			
		||||
      width 100%
 | 
			
		||||
      padding 10px
 | 
			
		||||
      padding 0 10px 10px 10px
 | 
			
		||||
      color #ffffff
 | 
			
		||||
      overflow-x hidden
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
.page-mark-map {
 | 
			
		||||
  background-color: #282c34;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  height 100%
 | 
			
		||||
 | 
			
		||||
  .inner {
 | 
			
		||||
    display: flex;
 | 
			
		||||
@@ -24,6 +24,7 @@
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 隐藏滚动条
 | 
			
		||||
 | 
			
		||||
      ::-webkit-scrollbar {
 | 
			
		||||
        width: 0;
 | 
			
		||||
        height: 0;
 | 
			
		||||
@@ -64,21 +65,15 @@
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .right-box {
 | 
			
		||||
 | 
			
		||||
    .chat-box {
 | 
			
		||||
      width 100%
 | 
			
		||||
 | 
			
		||||
      .top-bar {
 | 
			
		||||
        display flex
 | 
			
		||||
        justify-content space-between
 | 
			
		||||
        justify-content right
 | 
			
		||||
        align-items center
 | 
			
		||||
 | 
			
		||||
        h2 {
 | 
			
		||||
          color #ffffff
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .el-button {
 | 
			
		||||
          margin-right 20px
 | 
			
		||||
        }
 | 
			
		||||
        padding 10px 20px 10px 10px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .markdown {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
.member {
 | 
			
		||||
  background-color: #282c34;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  height 100%
 | 
			
		||||
 | 
			
		||||
  .el-dialog {
 | 
			
		||||
    .el-dialog__body {
 | 
			
		||||
@@ -65,9 +65,12 @@
 | 
			
		||||
    padding 15px 0 15px 15px;
 | 
			
		||||
    overflow-x hidden
 | 
			
		||||
    overflow-y visible
 | 
			
		||||
    display flex
 | 
			
		||||
    flex-flow row
 | 
			
		||||
 | 
			
		||||
    .user-profile {
 | 
			
		||||
      padding 10px 20px 20px 20px
 | 
			
		||||
      width 300px
 | 
			
		||||
      background-color #393F4A
 | 
			
		||||
      color #ffffff
 | 
			
		||||
      border-radius 10px
 | 
			
		||||
@@ -91,12 +94,15 @@
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    .product-box {
 | 
			
		||||
      padding 0 20px
 | 
			
		||||
      width 100%
 | 
			
		||||
 | 
			
		||||
      .info {
 | 
			
		||||
        .el-alert__description {
 | 
			
		||||
          font-size 14px !important
 | 
			
		||||
          margin 0
 | 
			
		||||
        }
 | 
			
		||||
        padding 10px 20px 20px 0
 | 
			
		||||
        padding 0 0 20px 0
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .list-box {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,8 @@
 | 
			
		||||
@font-face {
 | 
			
		||||
  font-family: "iconfont"; /* Project id 4125778 */
 | 
			
		||||
  src: url('iconfont.woff2?t=1713766977199') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1713766977199') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1713766977199') format('truetype');
 | 
			
		||||
  src: url('iconfont.woff2?t=1715987806624') format('woff2'),
 | 
			
		||||
       url('iconfont.woff?t=1715987806624') format('woff'),
 | 
			
		||||
       url('iconfont.ttf?t=1715987806624') format('truetype');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.iconfont {
 | 
			
		||||
@@ -13,6 +13,42 @@
 | 
			
		||||
  -moz-osx-font-smoothing: grayscale;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-control-simple:before {
 | 
			
		||||
  content: "\e624";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-mic-bold:before {
 | 
			
		||||
  content: "\e683";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-mic-thin:before {
 | 
			
		||||
  content: "\e8c2";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-attachment-cl:before {
 | 
			
		||||
  content: "\e66a";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-attachment-st:before {
 | 
			
		||||
  content: "\e63b";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-speaker:before {
 | 
			
		||||
  content: "\e607";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-clear:before {
 | 
			
		||||
  content: "\e900";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-bbs:before {
 | 
			
		||||
  content: "\e623";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-license:before {
 | 
			
		||||
  content: "\e65a";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.icon-more:before {
 | 
			
		||||
  content: "\e63c";
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -5,6 +5,69 @@
 | 
			
		||||
  "css_prefix_text": "icon-",
 | 
			
		||||
  "description": "",
 | 
			
		||||
  "glyphs": [
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "12243734",
 | 
			
		||||
      "name": "control",
 | 
			
		||||
      "font_class": "control-simple",
 | 
			
		||||
      "unicode": "e624",
 | 
			
		||||
      "unicode_decimal": 58916
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "6539424",
 | 
			
		||||
      "name": "麦克风",
 | 
			
		||||
      "font_class": "mic-bold",
 | 
			
		||||
      "unicode": "e683",
 | 
			
		||||
      "unicode_decimal": 59011
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "1727442",
 | 
			
		||||
      "name": "213麦克风",
 | 
			
		||||
      "font_class": "mic-thin",
 | 
			
		||||
      "unicode": "e8c2",
 | 
			
		||||
      "unicode_decimal": 59586
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "3730725",
 | 
			
		||||
      "name": "attach-attachment-cl",
 | 
			
		||||
      "font_class": "attachment-cl",
 | 
			
		||||
      "unicode": "e66a",
 | 
			
		||||
      "unicode_decimal": 58986
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "15748474",
 | 
			
		||||
      "name": "st-attachment",
 | 
			
		||||
      "font_class": "attachment-st",
 | 
			
		||||
      "unicode": "e63b",
 | 
			
		||||
      "unicode_decimal": 58939
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "1010",
 | 
			
		||||
      "name": "扬声器",
 | 
			
		||||
      "font_class": "speaker",
 | 
			
		||||
      "unicode": "e607",
 | 
			
		||||
      "unicode_decimal": 58887
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "8094805",
 | 
			
		||||
      "name": "clear",
 | 
			
		||||
      "font_class": "clear",
 | 
			
		||||
      "unicode": "e900",
 | 
			
		||||
      "unicode_decimal": 59648
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "34803640",
 | 
			
		||||
      "name": "论坛",
 | 
			
		||||
      "font_class": "bbs",
 | 
			
		||||
      "unicode": "e623",
 | 
			
		||||
      "unicode_decimal": 58915
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "310708",
 | 
			
		||||
      "name": "license",
 | 
			
		||||
      "font_class": "license",
 | 
			
		||||
      "unicode": "e65a",
 | 
			
		||||
      "unicode_decimal": 58970
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      "icon_id": "1421807",
 | 
			
		||||
      "name": "更多",
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -7,9 +7,9 @@
 | 
			
		||||
 | 
			
		||||
      <div class="chat-item">
 | 
			
		||||
        <div class="content" v-html="content"></div>
 | 
			
		||||
        <div class="bar" v-if="createdAt !== ''">
 | 
			
		||||
        <div class="bar" v-if="createdAt">
 | 
			
		||||
          <span class="bar-item"><el-icon><Clock/></el-icon> {{ createdAt }}</span>
 | 
			
		||||
          <span class="bar-item">Tokens: {{ finalTokens }}</span>
 | 
			
		||||
          <!--          <span class="bar-item">Tokens: {{ finalTokens }}</span>-->
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,67 +2,98 @@
 | 
			
		||||
  <div class="chat-line chat-line-reply">
 | 
			
		||||
    <div class="chat-line-inner">
 | 
			
		||||
      <div class="chat-icon">
 | 
			
		||||
        <img :src="icon" alt="ChatGPT">
 | 
			
		||||
        <img :src="data.icon" alt="ChatGPT">
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="chat-item">
 | 
			
		||||
        <div class="content" v-html="content"></div>
 | 
			
		||||
        <div class="bar" v-if="createdAt !== ''">
 | 
			
		||||
          <span class="bar-item"><el-icon><Clock/></el-icon> {{ createdAt }}</span>
 | 
			
		||||
          <span class="bar-item">Tokens: {{ tokens }}</span>
 | 
			
		||||
          <el-tooltip
 | 
			
		||||
              class="box-item"
 | 
			
		||||
              effect="dark"
 | 
			
		||||
              content="复制回答"
 | 
			
		||||
              placement="bottom"
 | 
			
		||||
          >
 | 
			
		||||
            <el-button type="info" class="copy-reply" :data-clipboard-text="orgContent">
 | 
			
		||||
              <el-icon>
 | 
			
		||||
                <DocumentCopy/>
 | 
			
		||||
              </el-icon>
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </el-tooltip>
 | 
			
		||||
        <div class="content" v-html="data.content"></div>
 | 
			
		||||
        <div class="bar" v-if="data.created_at">
 | 
			
		||||
          <span class="bar-item"><el-icon><Clock/></el-icon> {{ dateFormat(data.created_at) }}</span>
 | 
			
		||||
          <!--          <span class="bar-item">Tokens: {{ tokens }}</span>-->
 | 
			
		||||
          <span class="bar-item">
 | 
			
		||||
              <el-tooltip
 | 
			
		||||
                  class="box-item"
 | 
			
		||||
                  effect="dark"
 | 
			
		||||
                  content="复制回答"
 | 
			
		||||
                  placement="bottom"
 | 
			
		||||
              >
 | 
			
		||||
                <el-icon class="copy-reply" :data-clipboard-text="data.orgContent">
 | 
			
		||||
                  <DocumentCopy/>
 | 
			
		||||
                </el-icon>
 | 
			
		||||
              </el-tooltip>
 | 
			
		||||
            </span>
 | 
			
		||||
          <span v-if="!readOnly">
 | 
			
		||||
            <span class="bar-item" @click="reGenerate(data.prompt)">
 | 
			
		||||
            <el-tooltip
 | 
			
		||||
                class="box-item"
 | 
			
		||||
                effect="dark"
 | 
			
		||||
                content="重新生成"
 | 
			
		||||
                placement="bottom"
 | 
			
		||||
            >
 | 
			
		||||
              <el-icon><Refresh/></el-icon>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
 | 
			
		||||
          <span class="bar-item" @click="synthesis(data.orgContent)">
 | 
			
		||||
            <el-tooltip
 | 
			
		||||
                class="box-item"
 | 
			
		||||
                effect="dark"
 | 
			
		||||
                content="生成语音朗读"
 | 
			
		||||
                placement="bottom"
 | 
			
		||||
            >
 | 
			
		||||
              <i class="iconfont icon-speaker"></i>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </span>
 | 
			
		||||
          </span>
 | 
			
		||||
          <!--          <span class="bar-item">-->
 | 
			
		||||
          <!--            <el-dropdown trigger="click">-->
 | 
			
		||||
          <!--              <span class="el-dropdown-link">-->
 | 
			
		||||
          <!--                <el-icon><More/></el-icon>-->
 | 
			
		||||
          <!--              </span>-->
 | 
			
		||||
          <!--              <template #dropdown>-->
 | 
			
		||||
          <!--                <el-dropdown-menu>-->
 | 
			
		||||
          <!--                  <el-dropdown-item :icon="Headset" @click="synthesis(orgContent)">生成语音</el-dropdown-item>-->
 | 
			
		||||
          <!--                </el-dropdown-menu>-->
 | 
			
		||||
          <!--              </template>-->
 | 
			
		||||
          <!--            </el-dropdown>-->
 | 
			
		||||
          <!--          </span>-->
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import {defineComponent} from "vue"
 | 
			
		||||
import {Clock, DocumentCopy, Position} from "@element-plus/icons-vue";
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'ChatReply',
 | 
			
		||||
  components: {Position, Clock, DocumentCopy},
 | 
			
		||||
  props: {
 | 
			
		||||
    content: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: '',
 | 
			
		||||
    },
 | 
			
		||||
    orgContent: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: '',
 | 
			
		||||
    },
 | 
			
		||||
    createdAt: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: '',
 | 
			
		||||
    },
 | 
			
		||||
    tokens: {
 | 
			
		||||
      type: Number,
 | 
			
		||||
      default: 0,
 | 
			
		||||
    },
 | 
			
		||||
    icon: {
 | 
			
		||||
      type: String,
 | 
			
		||||
      default: 'images/gpt-icon.png',
 | 
			
		||||
    }
 | 
			
		||||
<script setup>
 | 
			
		||||
import {Clock, DocumentCopy, Refresh} from "@element-plus/icons-vue";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {dateFormat} from "@/utils/libs";
 | 
			
		||||
// eslint-disable-next-line no-undef,no-unused-vars
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  data: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: {},
 | 
			
		||||
  },
 | 
			
		||||
  data() {
 | 
			
		||||
    return {
 | 
			
		||||
      finalTokens: this.tokens
 | 
			
		||||
    }
 | 
			
		||||
  readOnly: {
 | 
			
		||||
    type: Boolean,
 | 
			
		||||
    default: false
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const emits = defineEmits(['regen']);
 | 
			
		||||
 | 
			
		||||
if (!props.data.icon) {
 | 
			
		||||
  props.data.icon = "images/gpt-icon.png"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const synthesis = (text) => {
 | 
			
		||||
  console.log(text)
 | 
			
		||||
  ElMessage.info("语音合成功能暂不可用")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 重新生成
 | 
			
		||||
const reGenerate = (prompt) => {
 | 
			
		||||
  emits('regen', prompt)
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
@@ -218,10 +249,12 @@ export default defineComponent({
 | 
			
		||||
            padding 3px 5px;
 | 
			
		||||
            margin-right 10px;
 | 
			
		||||
            border-radius 5px;
 | 
			
		||||
            cursor pointer
 | 
			
		||||
 | 
			
		||||
            .el-icon {
 | 
			
		||||
              position relative
 | 
			
		||||
              top 2px;
 | 
			
		||||
              cursor pointer
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,8 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-container class="file-list-box">
 | 
			
		||||
    <el-tooltip class="box-item" effect="dark" content="打开文件管理中心">
 | 
			
		||||
      <el-button class="file-upload-img" @click="fetchFiles">
 | 
			
		||||
        <el-icon>
 | 
			
		||||
          <PictureFilled/>
 | 
			
		||||
        </el-icon>
 | 
			
		||||
      </el-button>
 | 
			
		||||
    </el-tooltip>
 | 
			
		||||
 | 
			
		||||
    <a class="file-upload-img" @click="fetchFiles">
 | 
			
		||||
      <i class="iconfont icon-attachment-st"></i>
 | 
			
		||||
    </a>
 | 
			
		||||
    <el-dialog
 | 
			
		||||
        v-model="show"
 | 
			
		||||
        :close-on-click-modal="true"
 | 
			
		||||
@@ -58,7 +53,7 @@
 | 
			
		||||
import {ref} from "vue";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {Delete, PictureFilled, Plus} from "@element-plus/icons-vue";
 | 
			
		||||
import {Delete, Plus} from "@element-plus/icons-vue";
 | 
			
		||||
import {isImage, removeArrayItem} from "@/utils/libs";
 | 
			
		||||
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
@@ -132,11 +127,9 @@ const insertURL = (url) => {
 | 
			
		||||
 | 
			
		||||
.file-list-box {
 | 
			
		||||
  .file-upload-img {
 | 
			
		||||
    padding: 8px 5px;
 | 
			
		||||
    border-radius: 6px;
 | 
			
		||||
    background: #19c37d;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
    .iconfont {
 | 
			
		||||
      font-size: 24px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-dialog {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,19 +1,10 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="list-box" ref="container">
 | 
			
		||||
    <div class="list-inner">
 | 
			
		||||
      <div
 | 
			
		||||
          class="list-item"
 | 
			
		||||
          v-for="(item, index) in items"
 | 
			
		||||
          :key="index"
 | 
			
		||||
          :style="{width:itemWidth + 'px'}"
 | 
			
		||||
      >
 | 
			
		||||
        <div class="item-inner" :style="{padding: gap/2+'px'}">
 | 
			
		||||
          <div class="item-wrapper">
 | 
			
		||||
            <slot :item="item" :index="index" :width="itemWidth"></slot>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  <div class="list-box" ref="containerRef">
 | 
			
		||||
    <el-row :gutter="gap">
 | 
			
		||||
      <el-col v-for="item in items" :key="item.id" :span="span" :style="{marginBottom:gap+'px'} ">
 | 
			
		||||
        <slot :item="item"></slot>
 | 
			
		||||
      </el-col>
 | 
			
		||||
    </el-row>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -29,7 +20,7 @@ const props = defineProps({
 | 
			
		||||
  },
 | 
			
		||||
  gap: {
 | 
			
		||||
    type: Number,
 | 
			
		||||
    default: 12
 | 
			
		||||
    default: 10
 | 
			
		||||
  },
 | 
			
		||||
  width: {
 | 
			
		||||
    type: Number,
 | 
			
		||||
@@ -37,45 +28,35 @@ const props = defineProps({
 | 
			
		||||
  }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const container = ref(null)
 | 
			
		||||
const itemWidth = ref(props.width)
 | 
			
		||||
const containerRef = ref(null)
 | 
			
		||||
const span = ref(12)
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  computeSize()
 | 
			
		||||
  calcSpan()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const computeSize = () => {
 | 
			
		||||
  const w = container.value.offsetWidth - 10 // 减去滚动条的宽度
 | 
			
		||||
  let cols = Math.floor(w / props.width)
 | 
			
		||||
  itemWidth.value = Math.floor(w / cols)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
window.onresize = () => {
 | 
			
		||||
  computeSize()
 | 
			
		||||
const calcSpan = () => {
 | 
			
		||||
  let cols = Math.floor(containerRef.value.offsetWidth / props.width)
 | 
			
		||||
  if (cols >= 12) {
 | 
			
		||||
    span.value = 1
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  console.log(cols)
 | 
			
		||||
  while (cols > 1) {
 | 
			
		||||
    if (24 % cols === 0) {
 | 
			
		||||
      span.value = 24 / cols
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    cols -= 1
 | 
			
		||||
  }
 | 
			
		||||
  span.value = 12
 | 
			
		||||
}
 | 
			
		||||
window.onresize = () => calcSpan()
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="stylus">
 | 
			
		||||
 | 
			
		||||
.list-box {
 | 
			
		||||
 | 
			
		||||
  .list-inner {
 | 
			
		||||
    display flex
 | 
			
		||||
    flex-wrap wrap
 | 
			
		||||
 | 
			
		||||
    .list-item {
 | 
			
		||||
      .item-inner {
 | 
			
		||||
        display flex
 | 
			
		||||
 | 
			
		||||
        .item-wrapper {
 | 
			
		||||
          height 100%
 | 
			
		||||
          width 100%
 | 
			
		||||
          display flex
 | 
			
		||||
          justify-content center
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
</style>
 | 
			
		||||
@@ -221,7 +221,7 @@
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {computed, ref} from "vue"
 | 
			
		||||
import {ref, watch} from "vue"
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {setUserToken} from "@/store/session";
 | 
			
		||||
@@ -234,8 +234,9 @@ import {arrayContains} from "@/utils/libs";
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  show: Boolean,
 | 
			
		||||
});
 | 
			
		||||
const showDialog = computed(() => {
 | 
			
		||||
  return props.show
 | 
			
		||||
const showDialog = ref(false)
 | 
			
		||||
watch(() => props.show, (newValue) => {
 | 
			
		||||
  showDialog.value = newValue
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const login = ref(true)
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="user-info" id="user-info">
 | 
			
		||||
    <el-form :model="user" label-width="150px">
 | 
			
		||||
    <el-form :model="user" label-width="100px">
 | 
			
		||||
      <el-row>
 | 
			
		||||
        <el-upload
 | 
			
		||||
            class="avatar-uploader"
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
            content="您已经是 VIP 会员"
 | 
			
		||||
            placement="right"
 | 
			
		||||
        >
 | 
			
		||||
          <el-image v-if="user.vip" :src="vipImg" style="height: 25px;margin-left: 10px"/>
 | 
			
		||||
          <span class="vip-icon"><el-image v-if="user.vip" :src="vipImg" style="height: 25px;margin-left: 10px"/></span>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
      <el-form-item label="剩余算力">
 | 
			
		||||
@@ -37,7 +37,7 @@
 | 
			
		||||
      </el-form-item>
 | 
			
		||||
 | 
			
		||||
      <el-row class="opt-line">
 | 
			
		||||
        <el-button color="#47fff1" :dark="false" round @click="save">保存</el-button>
 | 
			
		||||
        <el-button color="#47fff1" :dark="false" @click="save">保存</el-button>
 | 
			
		||||
      </el-row>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </div>
 | 
			
		||||
@@ -107,13 +107,18 @@ const save = () => {
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
.user-info {
 | 
			
		||||
  padding 20px
 | 
			
		||||
  padding 20px 0
 | 
			
		||||
 | 
			
		||||
  .el-row {
 | 
			
		||||
    justify-content center
 | 
			
		||||
    margin-bottom 10px
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .vip-icon {
 | 
			
		||||
    position relative
 | 
			
		||||
    top 5px
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .opt-line {
 | 
			
		||||
    padding-top 20px
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@
 | 
			
		||||
import {createApp} from 'vue'
 | 
			
		||||
import ElementPlus from "element-plus"
 | 
			
		||||
import "element-plus/dist/index.css"
 | 
			
		||||
import '@/assets/iconfont/iconfont.css';
 | 
			
		||||
import 'vant/lib/index.css';
 | 
			
		||||
import App from './App.vue'
 | 
			
		||||
import {createPinia} from "pinia";
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,11 @@ const routes = [
 | 
			
		||||
                meta: {title: 'DALLE-3'},
 | 
			
		||||
                component: () => import('@/views/Dalle.vue'),
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                name: 'ExternalLink',
 | 
			
		||||
                path: '/external',
 | 
			
		||||
                component: () => import('@/views/ExternalPage.vue'),
 | 
			
		||||
            },
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								web/src/store/sharedata.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								web/src/store/sharedata.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
			
		||||
import {defineStore} from 'pinia';
 | 
			
		||||
 | 
			
		||||
export const useSharedStore = defineStore('shared', {
 | 
			
		||||
    state: () => ({
 | 
			
		||||
        showLoginDialog: false
 | 
			
		||||
    }),
 | 
			
		||||
    getters: {},
 | 
			
		||||
    actions: {
 | 
			
		||||
        setShowLoginDialog(value) {
 | 
			
		||||
            this.showLoginDialog = value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
@@ -1,19 +1,22 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="page-apps custom-scroll">
 | 
			
		||||
      <div class="title">
 | 
			
		||||
        AI 助手应用中心
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="inner" :style="{height: listBoxHeight + 'px'}">
 | 
			
		||||
        <ItemList :items="list" v-if="list.length > 0" :gap="20" :width="250">
 | 
			
		||||
        <ItemList :items="list" v-if="list.length > 0" :gap="15" :width="300">
 | 
			
		||||
          <template #default="scope">
 | 
			
		||||
            <div class="app-item" :style="{width: scope.width+'px'}">
 | 
			
		||||
              <el-image :src="scope.item.icon" fit="cover" :style="{height: scope.width+'px'}"/>
 | 
			
		||||
              <div class="title">
 | 
			
		||||
                <span class="name">{{ scope.item.name }}</span>
 | 
			
		||||
                <div class="opt">
 | 
			
		||||
            <div class="item">
 | 
			
		||||
              <div class="image">
 | 
			
		||||
                <el-image :src="scope.item.icon" fit="cover"/>
 | 
			
		||||
              </div>
 | 
			
		||||
 | 
			
		||||
              <div class="inner">
 | 
			
		||||
                <div class="info">
 | 
			
		||||
                  <div class="info-title">{{ scope.item.name }}</div>
 | 
			
		||||
                  <div class="info-text">{{ scope.item.hello_msg }}</div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="btn">
 | 
			
		||||
                  <div v-if="hasRole(scope.item.key)">
 | 
			
		||||
                    <el-button size="small" type="success" @click="useRole(scope.item)">使用</el-button>
 | 
			
		||||
                    <el-button size="small" color="#21aa93" @click="useRole(scope.item)">使用</el-button>
 | 
			
		||||
                    <el-button size="small" type="danger" @click="updateRole(scope.item,'remove')">移除</el-button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <el-button v-else size="small"
 | 
			
		||||
@@ -26,15 +29,34 @@
 | 
			
		||||
                  </el-button>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
              <div class="hello-msg" ref="elements">{{ scope.item.intro }}</div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
            <!--            <div class="app-item">-->
 | 
			
		||||
            <!--              <el-image :src="scope.item.icon" fit="cover"/>-->
 | 
			
		||||
            <!--              <div class="title">-->
 | 
			
		||||
            <!--                <span class="name">{{ scope.item.name }}</span>-->
 | 
			
		||||
            <!--                <div class="opt">-->
 | 
			
		||||
            <!--                  <div v-if="hasRole(scope.item.key)">-->
 | 
			
		||||
            <!--                    <el-button size="small" type="success" @click="useRole(scope.item)">使用</el-button>-->
 | 
			
		||||
            <!--                    <el-button size="small" type="danger" @click="updateRole(scope.item,'remove')">移除</el-button>-->
 | 
			
		||||
            <!--                  </div>-->
 | 
			
		||||
            <!--                  <el-button v-else size="small"-->
 | 
			
		||||
            <!--                             style="--el-color-primary:#009999"-->
 | 
			
		||||
            <!--                             @click="updateRole(scope.item, 'add')">-->
 | 
			
		||||
            <!--                    <el-icon>-->
 | 
			
		||||
            <!--                      <Plus/>-->
 | 
			
		||||
            <!--                    </el-icon>-->
 | 
			
		||||
            <!--                    <span>添加应用</span>-->
 | 
			
		||||
            <!--                  </el-button>-->
 | 
			
		||||
            <!--                </div>-->
 | 
			
		||||
            <!--              </div>-->
 | 
			
		||||
            <!--              <div class="hello-msg" ref="elements">{{ scope.item.intro }}</div>-->
 | 
			
		||||
            <!--            </div>-->
 | 
			
		||||
          </template>
 | 
			
		||||
        </ItemList>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="getRoles" @success=""/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -42,18 +64,18 @@
 | 
			
		||||
import {onMounted, ref} from "vue"
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import ItemList from "@/components/ItemList.vue";
 | 
			
		||||
import {Plus} from "@element-plus/icons-vue";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import {arrayContains, removeArrayItem, substr} from "@/utils/libs";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
import ItemList from "@/components/ItemList.vue";
 | 
			
		||||
import {Plus} from "@element-plus/icons-vue";
 | 
			
		||||
 | 
			
		||||
const listBoxHeight = window.innerHeight - 97
 | 
			
		||||
const listBoxHeight = window.innerHeight - 87
 | 
			
		||||
const list = ref([])
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const roles = ref([])
 | 
			
		||||
const elements = ref(null)
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  httpGet("/api/role/list?all=true").then((res) => {
 | 
			
		||||
    const items = res.data
 | 
			
		||||
@@ -70,7 +92,6 @@ onMounted(() => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const getRoles = () => {
 | 
			
		||||
  showLoginDialog.value = false
 | 
			
		||||
  checkSession().then(user => {
 | 
			
		||||
    roles.value = user.chat_roles
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
@@ -101,7 +122,7 @@ const updateRole = (row, opt) => {
 | 
			
		||||
      ElMessage.error(title.value + "失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -3,9 +3,6 @@
 | 
			
		||||
    <div class="chat-box" id="chat-box">
 | 
			
		||||
      <div class="title">
 | 
			
		||||
        <h2>{{ chatTitle }}</h2>
 | 
			
		||||
        <el-button type="success" @click="exportChat" :icon="Promotion">
 | 
			
		||||
          导出 PDF 文档
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div v-for="item in chatData" :key="item.id">
 | 
			
		||||
@@ -14,17 +11,10 @@
 | 
			
		||||
            :icon="item.icon"
 | 
			
		||||
            :created-at="dateFormat(item['created_at'])"
 | 
			
		||||
            :tokens="item['tokens']"
 | 
			
		||||
            :model="item['model']"
 | 
			
		||||
            :content="item.content"/>
 | 
			
		||||
        <chat-reply v-else-if="item.type==='reply'"
 | 
			
		||||
                    :icon="item.icon"
 | 
			
		||||
                    :org-content="item.orgContent"
 | 
			
		||||
                    :created-at="dateFormat(item['created_at'])"
 | 
			
		||||
                    :tokens="item['tokens']"
 | 
			
		||||
                    :content="item.content"/>
 | 
			
		||||
        <chat-mid-journey v-else-if="item.type==='mj'"
 | 
			
		||||
                          :content="item.content"
 | 
			
		||||
                          :icon="item.icon"
 | 
			
		||||
                          :created-at="dateFormat(item['created_at'])"/>
 | 
			
		||||
                    :data="item" :read-only="true"/>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div><!-- end chat box -->
 | 
			
		||||
  </div>
 | 
			
		||||
@@ -34,14 +24,13 @@
 | 
			
		||||
import {dateFormat} from "@/utils/libs";
 | 
			
		||||
import ChatReply from "@/components/ChatReply.vue";
 | 
			
		||||
import ChatPrompt from "@/components/ChatPrompt.vue";
 | 
			
		||||
import {nextTick, ref} from "vue";
 | 
			
		||||
import {nextTick, onMounted, ref} from "vue";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import 'highlight.js/styles/a11y-dark.css'
 | 
			
		||||
import hl from "highlight.js";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {Promotion} from "@element-plus/icons-vue";
 | 
			
		||||
import ChatMidJourney from "@/components/ChatMidJourney.vue";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
 | 
			
		||||
const chatData = ref([])
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
@@ -91,9 +80,16 @@ httpGet('/api/chat/detail?chat_id=' + chatId).then(res => {
 | 
			
		||||
  ElMessage.error("加载会失败: " + e.message)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const exportChat = () => {
 | 
			
		||||
  window.print()
 | 
			
		||||
}
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  const clipboard = new Clipboard('.copy-reply');
 | 
			
		||||
  clipboard.on('success', () => {
 | 
			
		||||
    ElMessage.success('复制成功!');
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  clipboard.on('error', () => {
 | 
			
		||||
    ElMessage.error('复制失败!');
 | 
			
		||||
  })
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
.chat-export {
 | 
			
		||||
@@ -115,12 +111,15 @@ const exportChat = () => {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    .chat-line {
 | 
			
		||||
    .chat-line-prompt {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
      display: flex;
 | 
			
		||||
      align-items: flex-start;
 | 
			
		||||
 | 
			
		||||
      .chat-line-inner {
 | 
			
		||||
        .chat-icon {
 | 
			
		||||
          margin-right: 0
 | 
			
		||||
        }
 | 
			
		||||
        .content {
 | 
			
		||||
          padding-top: 0
 | 
			
		||||
          font-size 16px;
 | 
			
		||||
@@ -138,10 +137,6 @@ const exportChat = () => {
 | 
			
		||||
      .chat-line-inner {
 | 
			
		||||
        display flex
 | 
			
		||||
 | 
			
		||||
        .copy-reply {
 | 
			
		||||
          display none
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .bar-item {
 | 
			
		||||
          background-color: #f7f7f8;
 | 
			
		||||
          color: #888;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,18 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="common-layout theme-white">
 | 
			
		||||
  <div class="common-layout">
 | 
			
		||||
    <el-container>
 | 
			
		||||
      <el-aside>
 | 
			
		||||
        <div class="title-box">
 | 
			
		||||
          <span>{{ title }}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="chat-list">
 | 
			
		||||
          <el-button @click="newChat" color="#21aa93">
 | 
			
		||||
            <el-icon style="margin-right: 5px">
 | 
			
		||||
              <Plus/>
 | 
			
		||||
            </el-icon>
 | 
			
		||||
            新建对话
 | 
			
		||||
          </el-button>
 | 
			
		||||
 | 
			
		||||
          <div class="search-box">
 | 
			
		||||
            <el-input v-model="chatName" class="w-50 m-2" size="small" placeholder="搜索会话" @keyup="searchChat">
 | 
			
		||||
            <el-input v-model="chatName" placeholder="搜索会话" @keyup="searchChat($event)" style=""
 | 
			
		||||
                      class="search-input">
 | 
			
		||||
              <template #prefix>
 | 
			
		||||
                <el-icon class="el-input__icon">
 | 
			
		||||
                  <Search/>
 | 
			
		||||
@@ -22,111 +27,45 @@
 | 
			
		||||
                   @click="changeChat(chat)">
 | 
			
		||||
                <el-image :src="chat.icon" class="avatar"/>
 | 
			
		||||
                <span class="chat-title-input" v-if="chat.edit">
 | 
			
		||||
              <el-input v-model="tmpChatTitle" size="small" @keydown="titleKeydown($event, chat)"
 | 
			
		||||
                        placeholder="请输入会话标题"/>
 | 
			
		||||
            </span>
 | 
			
		||||
                  <el-input v-model="tmpChatTitle" size="small" @keydown="titleKeydown($event, chat)"
 | 
			
		||||
                            :id="'chat-'+chat.chat_id"
 | 
			
		||||
                            @blur="editConfirm(chat)"
 | 
			
		||||
                            @click="stopPropagation($event)"
 | 
			
		||||
                            placeholder="请输入标题"/>
 | 
			
		||||
                </span>
 | 
			
		||||
                <span v-else class="chat-title">{{ chat.title }}</span>
 | 
			
		||||
                <span class="btn btn-check" v-if="chat.edit || chat.removing">
 | 
			
		||||
                <el-icon @click="confirm($event, chat)"><Check/></el-icon>
 | 
			
		||||
                <el-icon @click="cancel($event, chat)"><Close/></el-icon>
 | 
			
		||||
              </span>
 | 
			
		||||
                <span class="btn" v-else>
 | 
			
		||||
                <el-icon title="编辑" @click="editChatTitle($event, chat)"><Edit/></el-icon>
 | 
			
		||||
                <el-icon title="删除会话" @click="removeChat($event, chat)"><Delete/></el-icon>
 | 
			
		||||
              </span>
 | 
			
		||||
 | 
			
		||||
                <span class="chat-opt">
 | 
			
		||||
                  <el-dropdown trigger="click">
 | 
			
		||||
                    <span class="el-dropdown-link" @click="stopPropagation($event)">
 | 
			
		||||
                      <el-icon><More/></el-icon>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    <template #dropdown>
 | 
			
		||||
                      <el-dropdown-menu>
 | 
			
		||||
                        <el-dropdown-item :icon="Edit" @click="editChatTitle(chat)">重命名</el-dropdown-item>
 | 
			
		||||
                        <el-dropdown-item :icon="Delete"
 | 
			
		||||
                                          style="--el-text-color-regular: var(--el-color-danger);
 | 
			
		||||
                                          --el-dropdown-menuItem-hover-fill:#F8E1DE;
 | 
			
		||||
                                          --el-dropdown-menuItem-hover-color: var(--el-color-danger)"
 | 
			
		||||
                                          @click="removeChat(chat)">删除</el-dropdown-item>
 | 
			
		||||
                        <el-dropdown-item :icon="Share" @click="shareChat(chat)">分享</el-dropdown-item>
 | 
			
		||||
                      </el-dropdown-menu>
 | 
			
		||||
                    </template>
 | 
			
		||||
                  </el-dropdown>
 | 
			
		||||
                </span>
 | 
			
		||||
              </div>
 | 
			
		||||
            </el-row>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="tool-box">
 | 
			
		||||
          <el-dropdown :hide-on-click="true" class="user-info" trigger="click" v-if="isLogin">
 | 
			
		||||
                        <span class="el-dropdown-link">
 | 
			
		||||
                          <el-image :src="loginUser.avatar"/>
 | 
			
		||||
                          <span class="username">{{ loginUser.nickname }}</span>
 | 
			
		||||
                          <el-icon><ArrowDown/></el-icon>
 | 
			
		||||
                        </span>
 | 
			
		||||
            <template #dropdown>
 | 
			
		||||
              <el-dropdown-menu style="width: 296px;">
 | 
			
		||||
                <el-dropdown-item @click="showConfig">
 | 
			
		||||
                  <el-icon>
 | 
			
		||||
                    <Tools/>
 | 
			
		||||
                  </el-icon>
 | 
			
		||||
                  <span>账户信息</span>
 | 
			
		||||
                </el-dropdown-item>
 | 
			
		||||
 | 
			
		||||
                <el-dropdown-item @click="clearAllChats">
 | 
			
		||||
                  <el-icon>
 | 
			
		||||
                    <Delete/>
 | 
			
		||||
                  </el-icon>
 | 
			
		||||
                  <span>清除所有会话</span>
 | 
			
		||||
                </el-dropdown-item>
 | 
			
		||||
 | 
			
		||||
                <el-dropdown-item @click="logout">
 | 
			
		||||
                  <i class="iconfont icon-logout"></i>
 | 
			
		||||
                  <span>注销</span>
 | 
			
		||||
                </el-dropdown-item>
 | 
			
		||||
 | 
			
		||||
                <el-dropdown-item>
 | 
			
		||||
                  <i class="iconfont icon-github"></i>
 | 
			
		||||
                  <span>
 | 
			
		||||
                    powered by
 | 
			
		||||
                    <el-link type="primary" href="https://github.com/yangjian102621/chatgpt-plus" target="_blank">chatgpt-plus-v3</el-link>
 | 
			
		||||
                 </span>
 | 
			
		||||
                </el-dropdown-item>
 | 
			
		||||
              </el-dropdown-menu>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-dropdown>
 | 
			
		||||
          <el-button type="danger" size="small" @click="clearAllChats">
 | 
			
		||||
            <i class="iconfont icon-clear"></i> 清空聊天记录
 | 
			
		||||
          </el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </el-aside>
 | 
			
		||||
      <el-main v-loading="loading" element-loading-background="rgba(122, 122, 122, 0.3)">
 | 
			
		||||
        <div class="chat-head">
 | 
			
		||||
          <div class="chat-config">
 | 
			
		||||
            <el-select v-model="roleId" filterable placeholder="角色" class="role-select" @change="_newChat"
 | 
			
		||||
                       style="width:150px">
 | 
			
		||||
              <el-option
 | 
			
		||||
                  v-for="item in roles"
 | 
			
		||||
                  :key="item.id"
 | 
			
		||||
                  :label="item.name"
 | 
			
		||||
                  :value="item.id"
 | 
			
		||||
              >
 | 
			
		||||
                <div class="role-option">
 | 
			
		||||
                  <el-image :src="item.icon"></el-image>
 | 
			
		||||
                  <span>{{ item.name }}</span>
 | 
			
		||||
                </div>
 | 
			
		||||
              </el-option>
 | 
			
		||||
            </el-select>
 | 
			
		||||
 | 
			
		||||
            <el-select v-model="modelID" placeholder="模型" @change="_newChat" :disabled="disableModel"
 | 
			
		||||
                       style="width:150px">
 | 
			
		||||
              <el-option
 | 
			
		||||
                  v-for="item in models"
 | 
			
		||||
                  :key="item.id"
 | 
			
		||||
                  :label="item.name"
 | 
			
		||||
                  :value="item.id"
 | 
			
		||||
              >
 | 
			
		||||
                <span>{{ item.name }}</span>
 | 
			
		||||
                <el-tag style="margin-left: 5px; position: relative; top:-2px" type="info" size="small">{{
 | 
			
		||||
                    item.power
 | 
			
		||||
                  }}算力
 | 
			
		||||
                </el-tag>
 | 
			
		||||
              </el-option>
 | 
			
		||||
            </el-select>
 | 
			
		||||
            <el-button type="primary" @click="newChat">
 | 
			
		||||
              <el-icon>
 | 
			
		||||
                <Plus/>
 | 
			
		||||
              </el-icon>
 | 
			
		||||
              新建对话
 | 
			
		||||
            </el-button>
 | 
			
		||||
 | 
			
		||||
            <el-button type="success" @click="exportChat" plain>
 | 
			
		||||
              <i class="iconfont icon-export"></i>
 | 
			
		||||
              <span>导出会话</span>
 | 
			
		||||
            </el-button>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="right-box" :style="{height: mainWinHeight+'px'}">
 | 
			
		||||
        <div class="chat-box" :style="{height: mainWinHeight+'px'}">
 | 
			
		||||
          <div>
 | 
			
		||||
            <div id="container">
 | 
			
		||||
              <div class="chat-box" id="chat-box" :style="{height: chatBoxHeight+'px'}">
 | 
			
		||||
@@ -141,63 +80,103 @@
 | 
			
		||||
                      :tokens="item['tokens']"
 | 
			
		||||
                      :model="getModelValue(modelID)"
 | 
			
		||||
                      :content="item.content"/>
 | 
			
		||||
                  <chat-reply v-else-if="item.type==='reply'"
 | 
			
		||||
                              :icon="item.icon"
 | 
			
		||||
                              :org-content="item.orgContent"
 | 
			
		||||
                              :created-at="dateFormat(item['created_at'])"
 | 
			
		||||
                              :tokens="item['tokens']"
 | 
			
		||||
                              :content="item.content"/>
 | 
			
		||||
                  <chat-mid-journey v-else-if="item.type==='mj'"
 | 
			
		||||
                                    :content="item.content"
 | 
			
		||||
                                    :role-id="item.role_id"
 | 
			
		||||
                                    :chat-id="item.chat_id"
 | 
			
		||||
                                    :icon="item.icon"
 | 
			
		||||
                                    @disable-input="disableInput(true)"
 | 
			
		||||
                                    @enable-input="enableInput"
 | 
			
		||||
                                    :created-at="dateFormat(item['created_at'])"/>
 | 
			
		||||
                  <chat-reply v-else-if="item.type==='reply'" :data="item" @regen="reGenerate" :read-only="false"/>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div><!-- end chat box -->
 | 
			
		||||
 | 
			
		||||
              <div class="re-generate">
 | 
			
		||||
                <div class="btn-box">
 | 
			
		||||
                  <el-button type="info" v-if="showStopGenerate" @click="stopGenerate" plain>
 | 
			
		||||
                    <el-icon>
 | 
			
		||||
                      <VideoPause/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                    停止生成
 | 
			
		||||
                  </el-button>
 | 
			
		||||
              <el-affix position="bottom" :offset="0">
 | 
			
		||||
                <div class="input-box">
 | 
			
		||||
                  <span class="tool-item">
 | 
			
		||||
                      <el-popover
 | 
			
		||||
                          :width="300"
 | 
			
		||||
                          trigger="click"
 | 
			
		||||
                          placement="top-start"
 | 
			
		||||
                      >
 | 
			
		||||
                        <template #reference>
 | 
			
		||||
                          <div>
 | 
			
		||||
                            <el-tooltip effect="dark" content="模型选择">
 | 
			
		||||
                              <i class="iconfont icon-model"></i>
 | 
			
		||||
                            </el-tooltip>
 | 
			
		||||
                          </div>
 | 
			
		||||
                        </template>
 | 
			
		||||
 | 
			
		||||
                  <el-button type="primary" v-if="showReGenerate" @click="reGenerate" plain>
 | 
			
		||||
                    <el-icon>
 | 
			
		||||
                      <RefreshRight/>
 | 
			
		||||
                    </el-icon>
 | 
			
		||||
                    重新生成
 | 
			
		||||
                  </el-button>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
                        <template #default>
 | 
			
		||||
                          <div class="chat-config">
 | 
			
		||||
                            <el-select v-model="roleId" filterable placeholder="角色" @change="_newChat"
 | 
			
		||||
                                       class="role-select"
 | 
			
		||||
                                       style="width:150px">
 | 
			
		||||
                              <el-option
 | 
			
		||||
                                  v-for="item in roles"
 | 
			
		||||
                                  :key="item.id"
 | 
			
		||||
                                  :label="item.name"
 | 
			
		||||
                                  :value="item.id"
 | 
			
		||||
                              >
 | 
			
		||||
                                <div class="role-option">
 | 
			
		||||
                                  <el-image :src="item.icon"></el-image>
 | 
			
		||||
                                  <span>{{ item.name }}</span>
 | 
			
		||||
                                </div>
 | 
			
		||||
                              </el-option>
 | 
			
		||||
                            </el-select>
 | 
			
		||||
 | 
			
		||||
              <div class="input-box">
 | 
			
		||||
                <div class="input-container">
 | 
			
		||||
                  <el-input
 | 
			
		||||
                      ref="textInput"
 | 
			
		||||
                      v-model="prompt"
 | 
			
		||||
                      v-on:keydown="inputKeyDown"
 | 
			
		||||
                      autofocus
 | 
			
		||||
                      type="textarea"
 | 
			
		||||
                      :rows="2"
 | 
			
		||||
                      placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
 | 
			
		||||
                  />
 | 
			
		||||
                  <span class="select-file">
 | 
			
		||||
                    <file-select v-if="isLogin" :user-id="loginUser.id" @selected="insertURL"/>
 | 
			
		||||
                            <el-select v-model="modelID" filterable placeholder="模型" @change="_newChat"
 | 
			
		||||
                                       :disabled="disableModel"
 | 
			
		||||
                                       style="width:150px">
 | 
			
		||||
                              <el-option
 | 
			
		||||
                                  v-for="item in models"
 | 
			
		||||
                                  :key="item.id"
 | 
			
		||||
                                  :label="item.name"
 | 
			
		||||
                                  :value="item.id"
 | 
			
		||||
                              >
 | 
			
		||||
                                <span>{{ item.name }}</span>
 | 
			
		||||
                                <el-tag style="margin-left: 5px; position: relative; top:-2px" type="info" size="small">{{
 | 
			
		||||
                                    item.power
 | 
			
		||||
                                  }}算力
 | 
			
		||||
                                </el-tag>
 | 
			
		||||
                              </el-option>
 | 
			
		||||
                            </el-select>
 | 
			
		||||
                          </div>
 | 
			
		||||
                        </template>
 | 
			
		||||
                      </el-popover>
 | 
			
		||||
                  </span>
 | 
			
		||||
                  <span class="send-btn">
 | 
			
		||||
                    <el-button @click="sendMessage">
 | 
			
		||||
 | 
			
		||||
                  <span class="tool-item" @click="ElMessage.info('暂时不支持语音输入')">
 | 
			
		||||
                    <el-tooltip class="box-item" effect="dark" content="语音输入">
 | 
			
		||||
                      <i class="iconfont icon-mic-bold"></i>
 | 
			
		||||
                    </el-tooltip>
 | 
			
		||||
                  </span>
 | 
			
		||||
 | 
			
		||||
                  <span class="tool-item" v-if="isLogin">
 | 
			
		||||
                    <el-tooltip class="box-item" effect="dark" content="上传附件">
 | 
			
		||||
                      <file-select v-if="isLogin" :user-id="loginUser.id" @selected="insertURL"/>
 | 
			
		||||
                    </el-tooltip>
 | 
			
		||||
                  </span>
 | 
			
		||||
 | 
			
		||||
                  <div class="input-container">
 | 
			
		||||
                    <el-input
 | 
			
		||||
                        ref="textInput"
 | 
			
		||||
                        v-model="prompt"
 | 
			
		||||
                        v-on:keydown="inputKeyDown"
 | 
			
		||||
                        autofocus
 | 
			
		||||
                        type="textarea"
 | 
			
		||||
                        :rows="2"
 | 
			
		||||
                        style="--el-input-focus-border-color:#21AA93;
 | 
			
		||||
                        border: 1px solid #21AA93;--el-input-border-color:#21AA93;
 | 
			
		||||
                        border-radius: 5px; --el-input-hover-border-color:#21AA93;"
 | 
			
		||||
                        placeholder="按 Enter 键发送消息,使用 Ctrl + Enter 换行"
 | 
			
		||||
                    />
 | 
			
		||||
                    <span class="send-btn">
 | 
			
		||||
                    <el-button type="info" v-if="showStopGenerate" @click="stopGenerate" plain>
 | 
			
		||||
                      <el-icon>
 | 
			
		||||
                        <VideoPause/>
 | 
			
		||||
                      </el-icon>
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                    <el-button @click="sendMessage" color="#19c37d" style="color:#ffffff" v-else>
 | 
			
		||||
                      <el-icon><Promotion/></el-icon>
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                  </span>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div><!-- end input box -->
 | 
			
		||||
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div><!-- end input box -->
 | 
			
		||||
              </el-affix>
 | 
			
		||||
            </div><!-- end container -->
 | 
			
		||||
          </div><!-- end loading -->
 | 
			
		||||
        </div>
 | 
			
		||||
@@ -207,23 +186,17 @@
 | 
			
		||||
    <el-dialog
 | 
			
		||||
        v-model="showNotice"
 | 
			
		||||
        :show-close="true"
 | 
			
		||||
        custom-class="notice-dialog"
 | 
			
		||||
        class="notice-dialog"
 | 
			
		||||
        title="网站公告"
 | 
			
		||||
    >
 | 
			
		||||
      <div class="notice">
 | 
			
		||||
        <el-text type="primary">
 | 
			
		||||
          <div v-html="notice"></div>
 | 
			
		||||
        </el-text>
 | 
			
		||||
        <div v-html="notice"></div>
 | 
			
		||||
 | 
			
		||||
        <p style="text-align: right">
 | 
			
		||||
          <el-button @click="notShow" type="success" plain>我知道了,不再显示</el-button>
 | 
			
		||||
        </p>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-dialog>
 | 
			
		||||
 | 
			
		||||
    <config-dialog v-if="isLogin" :show="showConfigDialog" :models="models" @hide="showConfigDialog = false"/>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -232,19 +205,7 @@
 | 
			
		||||
import {nextTick, onMounted, onUnmounted, ref} from 'vue'
 | 
			
		||||
import ChatPrompt from "@/components/ChatPrompt.vue";
 | 
			
		||||
import ChatReply from "@/components/ChatReply.vue";
 | 
			
		||||
import {
 | 
			
		||||
  ArrowDown,
 | 
			
		||||
  Check,
 | 
			
		||||
  Close,
 | 
			
		||||
  Delete,
 | 
			
		||||
  Edit,
 | 
			
		||||
  Plus,
 | 
			
		||||
  Promotion,
 | 
			
		||||
  RefreshRight,
 | 
			
		||||
  Search,
 | 
			
		||||
  Tools,
 | 
			
		||||
  VideoPause
 | 
			
		||||
} from '@element-plus/icons-vue'
 | 
			
		||||
import {Delete, Edit, More, Plus, Promotion, Search, Share, VideoPause} from '@element-plus/icons-vue'
 | 
			
		||||
import 'highlight.js/styles/a11y-dark.css'
 | 
			
		||||
import {dateFormat, escapeHTML, isMobile, processContent, randString, removeArrayItem, UUID} from "@/utils/libs";
 | 
			
		||||
import {ElMessage, ElMessageBox} from "element-plus";
 | 
			
		||||
@@ -253,12 +214,10 @@ import {getSessionId, getUserToken, removeUserToken} from "@/store/session";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import ConfigDialog from "@/components/ConfigDialog.vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import Welcome from "@/components/Welcome.vue";
 | 
			
		||||
import ChatMidJourney from "@/components/ChatMidJourney.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
import FileSelect from "@/components/FileSelect.vue";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
 | 
			
		||||
const title = ref('ChatGPT-智能助手');
 | 
			
		||||
const models = ref([])
 | 
			
		||||
@@ -276,14 +235,13 @@ const roles = ref([]);
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
const roleId = ref(0)
 | 
			
		||||
const newChatItem = ref(null);
 | 
			
		||||
const showConfigDialog = ref(false);
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const showHello = ref(true)
 | 
			
		||||
const textInput = ref(null)
 | 
			
		||||
const showNotice = ref(false)
 | 
			
		||||
const notice = ref("")
 | 
			
		||||
const noticeKey = ref("SYSTEM_NOTICE")
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
if (isMobile()) {
 | 
			
		||||
  router.replace("/mobile/chat")
 | 
			
		||||
@@ -414,9 +372,9 @@ const getRoleById = function (rid) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const resizeElement = function () {
 | 
			
		||||
  chatBoxHeight.value = window.innerHeight - 51 - 82 - 38;
 | 
			
		||||
  mainWinHeight.value = window.innerHeight - 51;
 | 
			
		||||
  leftBoxHeight.value = window.innerHeight - 43 - 47 - 45;
 | 
			
		||||
  chatBoxHeight.value = window.innerHeight - 50 - 82 - 38;
 | 
			
		||||
  mainWinHeight.value = window.innerHeight - 50;
 | 
			
		||||
  leftBoxHeight.value = window.innerHeight - 90 - 45 - 82;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const _newChat = () => {
 | 
			
		||||
@@ -424,17 +382,17 @@ const _newChat = () => {
 | 
			
		||||
    newChat()
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const disableModel = ref(false)
 | 
			
		||||
// 新建会话
 | 
			
		||||
const newChat = () => {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  const role = getRoleById(roleId.value)
 | 
			
		||||
  showHello.value = role.key === 'gpt';
 | 
			
		||||
  // if the role bind a model, disable model change
 | 
			
		||||
  disableModel.value = false
 | 
			
		||||
  if (role.model_id > 0) {
 | 
			
		||||
    modelID.value = role.model_id
 | 
			
		||||
    disableModel.value = true
 | 
			
		||||
@@ -462,7 +420,6 @@ const newChat = () => {
 | 
			
		||||
  };
 | 
			
		||||
  activeChat.value = {} //取消激活的会话高亮
 | 
			
		||||
  showStopGenerate.value = false;
 | 
			
		||||
  showReGenerate.value = false;
 | 
			
		||||
  connect(null, roleId.value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -474,7 +431,7 @@ const changeChat = (chat) => {
 | 
			
		||||
 | 
			
		||||
const loadChat = function (chat) {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -487,69 +444,77 @@ const loadChat = function (chat) {
 | 
			
		||||
  roleId.value = chat.role_id;
 | 
			
		||||
  modelID.value = chat.model_id;
 | 
			
		||||
  showStopGenerate.value = false;
 | 
			
		||||
  showReGenerate.value = false;
 | 
			
		||||
  connect(chat.chat_id, chat.role_id)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 编辑会话标题
 | 
			
		||||
const curOpt = ref('')
 | 
			
		||||
const tmpChatTitle = ref('');
 | 
			
		||||
const editChatTitle = function (event, chat) {
 | 
			
		||||
  event.stopPropagation();
 | 
			
		||||
const editChatTitle = (chat) => {
 | 
			
		||||
  chat.edit = true;
 | 
			
		||||
  curOpt.value = 'edit';
 | 
			
		||||
  tmpChatTitle.value = chat.title;
 | 
			
		||||
  console.log(chat.chat_id)
 | 
			
		||||
  nextTick(() => {
 | 
			
		||||
    document.getElementById('chat-' + chat.chat_id).focus()
 | 
			
		||||
  })
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const titleKeydown = (e, chat) => {
 | 
			
		||||
  if (e.keyCode === 13) {
 | 
			
		||||
    e.stopPropagation();
 | 
			
		||||
    confirm(e, chat)
 | 
			
		||||
    editConfirm(chat)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const stopPropagation = (e) => {
 | 
			
		||||
  e.stopPropagation();
 | 
			
		||||
}
 | 
			
		||||
// 确认修改
 | 
			
		||||
const confirm = function (event, chat) {
 | 
			
		||||
  event.stopPropagation();
 | 
			
		||||
  if (curOpt.value === 'edit') {
 | 
			
		||||
    if (tmpChatTitle.value === '') {
 | 
			
		||||
      return ElMessage.error("请输入会话标题!");
 | 
			
		||||
    }
 | 
			
		||||
    if (!chat.chat_id) {
 | 
			
		||||
      return ElMessage.error("对话 ID 为空,请刷新页面再试!");
 | 
			
		||||
    }
 | 
			
		||||
    httpPost('/api/chat/update', {chat_id: chat.chat_id, title: tmpChatTitle.value}).then(() => {
 | 
			
		||||
      chat.title = tmpChatTitle.value;
 | 
			
		||||
      chat.edit = false;
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
    })
 | 
			
		||||
  } else if (curOpt.value === 'remove') {
 | 
			
		||||
    httpGet('/api/chat/remove?chat_id=' + chat.chat_id).then(() => {
 | 
			
		||||
      chatList.value = removeArrayItem(chatList.value, chat, function (e1, e2) {
 | 
			
		||||
        return e1.id === e2.id
 | 
			
		||||
      })
 | 
			
		||||
      // 重置会话
 | 
			
		||||
      newChat();
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
const editConfirm = function (chat) {
 | 
			
		||||
  if (tmpChatTitle.value === '') {
 | 
			
		||||
    return ElMessage.error("请输入会话标题!");
 | 
			
		||||
  }
 | 
			
		||||
  if (!chat.chat_id) {
 | 
			
		||||
    return ElMessage.error("对话 ID 为空,请刷新页面再试!");
 | 
			
		||||
  }
 | 
			
		||||
  if (tmpChatTitle.value === chat.title) {
 | 
			
		||||
    chat.edit = false;
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// 取消修改
 | 
			
		||||
const cancel = function (event, chat) {
 | 
			
		||||
  event.stopPropagation();
 | 
			
		||||
  chat.edit = false;
 | 
			
		||||
  chat.removing = false;
 | 
			
		||||
}
 | 
			
		||||
  httpPost('/api/chat/update', {chat_id: chat.chat_id, title: tmpChatTitle.value}).then(() => {
 | 
			
		||||
    chat.title = tmpChatTitle.value;
 | 
			
		||||
    chat.edit = false;
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
// 删除会话
 | 
			
		||||
const removeChat = function (event, chat) {
 | 
			
		||||
  event.stopPropagation();
 | 
			
		||||
  chat.removing = true;
 | 
			
		||||
  curOpt.value = 'remove';
 | 
			
		||||
const removeChat = function (chat) {
 | 
			
		||||
  ElMessageBox.confirm(
 | 
			
		||||
      `该操作会删除"${chat.title}"`,
 | 
			
		||||
      '删除聊天',
 | 
			
		||||
      {
 | 
			
		||||
        confirmButtonText: '删除',
 | 
			
		||||
        cancelButtonText: '取消',
 | 
			
		||||
        type: 'warning',
 | 
			
		||||
      }
 | 
			
		||||
  )
 | 
			
		||||
      .then(() => {
 | 
			
		||||
        httpGet('/api/chat/remove?chat_id=' + chat.chat_id).then(() => {
 | 
			
		||||
          chatList.value = removeArrayItem(chatList.value, chat, function (e1, e2) {
 | 
			
		||||
            return e1.id === e2.id
 | 
			
		||||
          })
 | 
			
		||||
          // 重置会话
 | 
			
		||||
          newChat();
 | 
			
		||||
        }).catch(e => {
 | 
			
		||||
          ElMessage.error("操作失败:" + e.message);
 | 
			
		||||
        })
 | 
			
		||||
      })
 | 
			
		||||
      .catch(() => {
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const latexPlugin = require('markdown-it-latex2img')
 | 
			
		||||
@@ -584,8 +549,6 @@ md.use(mathjaxPlugin)
 | 
			
		||||
// 创建 socket 连接
 | 
			
		||||
const prompt = ref('');
 | 
			
		||||
const showStopGenerate = ref(false); // 停止生成
 | 
			
		||||
const showReGenerate = ref(false); // 重新生成
 | 
			
		||||
const previousText = ref(''); // 上一次提问
 | 
			
		||||
const lineBuffer = ref(''); // 输出缓冲行
 | 
			
		||||
const socket = ref(null);
 | 
			
		||||
const activelyClose = ref(false); // 主动关闭
 | 
			
		||||
@@ -630,7 +593,6 @@ const connect = function (chat_id, role_id) {
 | 
			
		||||
  const _socket = new WebSocket(host + `/api/chat/new?session_id=${_sessionId}&role_id=${role_id}&chat_id=${chat_id}&model_id=${modelID.value}&token=${getUserToken()}`);
 | 
			
		||||
  _socket.addEventListener('open', () => {
 | 
			
		||||
    chatData.value = []; // 初始化聊天数据
 | 
			
		||||
    previousText.value = '';
 | 
			
		||||
    enableInput()
 | 
			
		||||
    activelyClose.value = false;
 | 
			
		||||
 | 
			
		||||
@@ -670,7 +632,7 @@ const connect = function (chat_id, role_id) {
 | 
			
		||||
          } else if (data.type === 'end') { // 消息接收完毕
 | 
			
		||||
            // 追加当前会话到会话列表
 | 
			
		||||
            if (isNewChat && newChatItem.value !== null) {
 | 
			
		||||
              newChatItem.value['title'] = previousText.value;
 | 
			
		||||
              newChatItem.value['title'] = tmpChatTitle.value;
 | 
			
		||||
              newChatItem.value['chat_id'] = chat_id;
 | 
			
		||||
              chatList.value.unshift(newChatItem.value);
 | 
			
		||||
              activeChat.value = newChatItem.value;
 | 
			
		||||
@@ -735,13 +697,11 @@ const connect = function (chat_id, role_id) {
 | 
			
		||||
 | 
			
		||||
const disableInput = (force) => {
 | 
			
		||||
  canSend.value = false;
 | 
			
		||||
  showReGenerate.value = false;
 | 
			
		||||
  showStopGenerate.value = !force;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const enableInput = () => {
 | 
			
		||||
  canSend.value = true;
 | 
			
		||||
  showReGenerate.value = previousText.value !== "";
 | 
			
		||||
  showStopGenerate.value = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -766,7 +726,7 @@ const autofillPrompt = (text) => {
 | 
			
		||||
// 发送消息
 | 
			
		||||
const sendMessage = function () {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -784,7 +744,7 @@ const sendMessage = function () {
 | 
			
		||||
    id: randString(32),
 | 
			
		||||
    icon: loginUser.value.avatar,
 | 
			
		||||
    content: md.render(escapeHTML(processContent(prompt.value))),
 | 
			
		||||
    created_at: new Date().getTime(),
 | 
			
		||||
    created_at: new Date().getTime() / 1000,
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  nextTick(() => {
 | 
			
		||||
@@ -794,15 +754,11 @@ const sendMessage = function () {
 | 
			
		||||
  showHello.value = false
 | 
			
		||||
  disableInput(false)
 | 
			
		||||
  socket.value.send(JSON.stringify({type: "chat", content: prompt.value}));
 | 
			
		||||
  previousText.value = prompt.value;
 | 
			
		||||
  tmpChatTitle.value = prompt.value
 | 
			
		||||
  prompt.value = '';
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const showConfig = function () {
 | 
			
		||||
  showConfigDialog.value = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const clearAllChats = function () {
 | 
			
		||||
  ElMessageBox.confirm(
 | 
			
		||||
      '确认要清空所有的会话历史记录吗?<br/>此操作不可以撤销!',
 | 
			
		||||
@@ -850,6 +806,9 @@ const loadChatHistory = function (chatId) {
 | 
			
		||||
    for (let i = 0; i < data.length; i++) {
 | 
			
		||||
      data[i].orgContent = data[i].content;
 | 
			
		||||
      data[i].content = md.render(processContent(data[i].content))
 | 
			
		||||
      if (i > 0 && data[i].type === 'reply') {
 | 
			
		||||
        data[i].prompt = data[i - 1].orgContent
 | 
			
		||||
      }
 | 
			
		||||
      chatData.value.push(data[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -871,9 +830,9 @@ const stopGenerate = function () {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 重新生成
 | 
			
		||||
const reGenerate = function () {
 | 
			
		||||
const reGenerate = function (prompt) {
 | 
			
		||||
  disableInput(false)
 | 
			
		||||
  const text = '重新生成上述问题的答案:' + previousText.value;
 | 
			
		||||
  const text = '重新生成下面问题的答案:' + prompt;
 | 
			
		||||
  // 追加消息
 | 
			
		||||
  chatData.value.push({
 | 
			
		||||
    type: "prompt",
 | 
			
		||||
@@ -881,32 +840,34 @@ const reGenerate = function () {
 | 
			
		||||
    icon: loginUser.value.avatar,
 | 
			
		||||
    content: md.render(text)
 | 
			
		||||
  });
 | 
			
		||||
  socket.value.send(JSON.stringify({type: "chat", content: previousText.value}));
 | 
			
		||||
  socket.value.send(JSON.stringify({type: "chat", content: prompt}));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const chatName = ref('')
 | 
			
		||||
// 搜索会话
 | 
			
		||||
const searchChat = function () {
 | 
			
		||||
const searchChat = function (e) {
 | 
			
		||||
  if (chatName.value === '') {
 | 
			
		||||
    chatList.value = allChats.value
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  const items = [];
 | 
			
		||||
  for (let i = 0; i < allChats.value.length; i++) {
 | 
			
		||||
    if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) {
 | 
			
		||||
      items.push(allChats.value[i]);
 | 
			
		||||
  if (e.keyCode === 13) {
 | 
			
		||||
    const items = [];
 | 
			
		||||
    for (let i = 0; i < allChats.value.length; i++) {
 | 
			
		||||
      if (allChats.value[i].title.toLowerCase().indexOf(chatName.value.toLowerCase()) !== -1) {
 | 
			
		||||
        items.push(allChats.value[i]);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    chatList.value = items;
 | 
			
		||||
  }
 | 
			
		||||
  chatList.value = items;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 导出会话
 | 
			
		||||
const exportChat = () => {
 | 
			
		||||
  if (!activeChat.value['chat_id']) {
 | 
			
		||||
const shareChat = (chat) => {
 | 
			
		||||
  if (!chat.chat_id) {
 | 
			
		||||
    return ElMessage.error("请先选中一个会话")
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  const url = location.protocol + '//' + location.host + '/chat/export?chat_id=' + activeChat.value['chat_id']
 | 
			
		||||
  const url = location.protocol + '//' + location.host + '/chat/export?chat_id=' + chat.chat_id
 | 
			
		||||
  // console.log(url)
 | 
			
		||||
  window.open(url, '_blank');
 | 
			
		||||
}
 | 
			
		||||
@@ -939,8 +900,58 @@ const insertURL = (url) => {
 | 
			
		||||
 | 
			
		||||
<style lang="stylus">
 | 
			
		||||
.notice-dialog {
 | 
			
		||||
  .el-dialog__header {
 | 
			
		||||
    padding-bottom 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-dialog__body {
 | 
			
		||||
    padding 0 20px
 | 
			
		||||
 | 
			
		||||
    ol, ul {
 | 
			
		||||
      padding-left 10px
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ol {
 | 
			
		||||
      list-style decimal-leading-zero
 | 
			
		||||
      padding-left 20px
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ul {
 | 
			
		||||
      list-style disc
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.input-container {
 | 
			
		||||
  .el-textarea {
 | 
			
		||||
    .el-textarea__inner {
 | 
			
		||||
      padding-right 40px
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.chat-config {
 | 
			
		||||
  display flex
 | 
			
		||||
  flex-direction row
 | 
			
		||||
  padding-top 10px;
 | 
			
		||||
 | 
			
		||||
  .role-select-label {
 | 
			
		||||
    color #ffffff
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-select {
 | 
			
		||||
    max-width 150px;
 | 
			
		||||
    margin-right 10px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .role-select {
 | 
			
		||||
    max-width 130px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .el-button {
 | 
			
		||||
    .el-icon {
 | 
			
		||||
      margin-right 5px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
        <div class="sd-box">
 | 
			
		||||
          <h2>DALL-E 创作中心</h2>
 | 
			
		||||
 | 
			
		||||
          <div class="sd-params" :style="{ height: paramBoxHeight + 'px' }">
 | 
			
		||||
          <div class="sd-params">
 | 
			
		||||
            <el-form :model="params" label-width="80px" label-position="left">
 | 
			
		||||
              <div class="param-line" style="padding-top: 10px">
 | 
			
		||||
                <el-form-item label="图片质量">
 | 
			
		||||
@@ -88,7 +88,7 @@
 | 
			
		||||
              <h2>任务列表</h2>
 | 
			
		||||
              <div class="running-job-list">
 | 
			
		||||
                <div class="running-job-box" v-if="runningJobs.length > 0">
 | 
			
		||||
                  <div class="job-item" v-for="item in runningJobs">
 | 
			
		||||
                  <div class="job-item" v-for="item in runningJobs" :key="item.id">
 | 
			
		||||
                    <div v-if="item.progress > 0" class="job-item-inner">
 | 
			
		||||
                      <el-image :src="item['img_url']" fit="cover" loading="lazy">
 | 
			
		||||
                        <template #placeholder>
 | 
			
		||||
@@ -221,32 +221,35 @@
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
    <el-image-viewer @close="() => { previewURL = '' }" v-if="previewURL !== ''" :url-list="[previewURL]"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import {onMounted, onUnmounted, ref} from "vue"
 | 
			
		||||
import {Delete, InfoFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import {Delete, InfoFilled, Picture} from "@element-plus/icons-vue";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import {ElMessage, ElMessageBox, ElNotification} from "element-plus";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const listBoxHeight = ref(window.innerHeight - 40)
 | 
			
		||||
const paramBoxHeight = ref(window.innerHeight - 150)
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const listBoxHeight = ref(0)
 | 
			
		||||
// const paramBoxHeight = ref(0)
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const colWidth = ref(240)
 | 
			
		||||
const colWidth = ref(220)
 | 
			
		||||
const isOver = ref(false)
 | 
			
		||||
const previewURL = ref("")
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
const resizeElement = function () {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 90
 | 
			
		||||
  // paramBoxHeight.value = window.innerHeight - 110
 | 
			
		||||
};
 | 
			
		||||
resizeElement()
 | 
			
		||||
window.onresize = () => {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 40
 | 
			
		||||
  paramBoxHeight.value = window.innerHeight - 150
 | 
			
		||||
  resizeElement()
 | 
			
		||||
}
 | 
			
		||||
const qualities = [
 | 
			
		||||
  {name: "标准", value: "standard"},
 | 
			
		||||
@@ -351,8 +354,8 @@ const connect = () => {
 | 
			
		||||
        const message = String(reader.result)
 | 
			
		||||
        if (message === "FINISH") {
 | 
			
		||||
          page.value = 0
 | 
			
		||||
          fetchFinishJobs(page.value)
 | 
			
		||||
          isOver.value = false
 | 
			
		||||
          fetchFinishJobs(page.value)
 | 
			
		||||
        }
 | 
			
		||||
        fetchRunningJobs()
 | 
			
		||||
      }
 | 
			
		||||
@@ -434,7 +437,7 @@ const generate = () => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  httpPost("/api/dall/image", params.value).then(() => {
 | 
			
		||||
@@ -458,7 +461,9 @@ const removeImage = (event, item) => {
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    httpPost("/api/dall/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => {
 | 
			
		||||
      ElMessage.success("任务删除成功")
 | 
			
		||||
      fetchFinishJobs(1)
 | 
			
		||||
      page.value = 0
 | 
			
		||||
      isOver.value = false
 | 
			
		||||
      fetchFinishJobs()
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("任务删除失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
@@ -480,6 +485,9 @@ const publishImage = (event, item, action) => {
 | 
			
		||||
  httpPost("/api/dall/publish", {id: item.id, action: action}).then(() => {
 | 
			
		||||
    ElMessage.success(text + "成功")
 | 
			
		||||
    item.publish = action
 | 
			
		||||
    page.value = 0
 | 
			
		||||
    isOver.value = false
 | 
			
		||||
    fetchFinishJobs()
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error(text + "失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										38
									
								
								web/src/views/ExternalPage.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								web/src/views/ExternalPage.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="page-iframe" v-loading="loading"
 | 
			
		||||
       style="--el-color-primary:#47fff1"
 | 
			
		||||
       element-loading-text="页面正在加载中..."
 | 
			
		||||
       element-loading-background="rgba(122, 122, 122, 0.8)">
 | 
			
		||||
    <iframe :src="externalUrl" class="iframe" @load="onIframeLoad"></iframe>
 | 
			
		||||
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup>
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {computed, ref} from "vue";
 | 
			
		||||
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const router = useRouter()
 | 
			
		||||
const externalUrl = computed(() => {
 | 
			
		||||
  loading.value = true
 | 
			
		||||
  return router.currentRoute.value.query.url || 'about:blank'
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const onIframeLoad = () => {
 | 
			
		||||
  loading.value = false
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="stylus">
 | 
			
		||||
.page-iframe {
 | 
			
		||||
  width 100%
 | 
			
		||||
  height 100%
 | 
			
		||||
  overflow hidden
 | 
			
		||||
 | 
			
		||||
  .iframe {
 | 
			
		||||
    width 100%
 | 
			
		||||
    height 100%
 | 
			
		||||
    border none
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
@@ -1,200 +1,225 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="home">
 | 
			
		||||
    <div class="navigator">
 | 
			
		||||
      <div class="logo">
 | 
			
		||||
        <el-image :src="logo" @click="router.push('/')"/>
 | 
			
		||||
        <div class="divider"></div>
 | 
			
		||||
    <div class="header">
 | 
			
		||||
      <div class="banner">
 | 
			
		||||
        <div class="logo">
 | 
			
		||||
          <el-image :src="logo" @click="router.push('/')"/>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="title">
 | 
			
		||||
          <span>{{ title }}</span>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
      <ul class="nav-items">
 | 
			
		||||
        <li v-for="item in mainNavs" :key="item.url">
 | 
			
		||||
          <a @click="changeNav(item)" :class="item.url === curPath ? 'active' : ''">
 | 
			
		||||
            <el-image :src="item.icon" style="width: 30px;height: 30px"/>
 | 
			
		||||
          </a>
 | 
			
		||||
          <div :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</div>
 | 
			
		||||
        </li>
 | 
			
		||||
 | 
			
		||||
        <el-popover
 | 
			
		||||
            v-if="moreNavs.length > 0"
 | 
			
		||||
            placement="right-end"
 | 
			
		||||
            trigger="hover"
 | 
			
		||||
        >
 | 
			
		||||
          <template #reference>
 | 
			
		||||
            <li>
 | 
			
		||||
              <a class="active">
 | 
			
		||||
                <el-image src="/images/menu/more.png" style="width: 30px;height: 30px"/>
 | 
			
		||||
              </a>
 | 
			
		||||
            </li>
 | 
			
		||||
      <div class="navbar">
 | 
			
		||||
 | 
			
		||||
        <el-tooltip
 | 
			
		||||
            class="box-item"
 | 
			
		||||
            effect="light"
 | 
			
		||||
            content="部署文档"
 | 
			
		||||
            placement="bottom">
 | 
			
		||||
          <a href="https://ai.r9it.com/docs/install/" class="link-button" target="_blank">
 | 
			
		||||
            <i class="iconfont icon-book"></i>
 | 
			
		||||
          </a>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
 | 
			
		||||
        <el-tooltip
 | 
			
		||||
            class="box-item"
 | 
			
		||||
            effect="light"
 | 
			
		||||
            content="项目源码"
 | 
			
		||||
            placement="bottom">
 | 
			
		||||
          <a href="https://github.com/yangjian102621/chatgpt-plus" class="link-button" target="_blank">
 | 
			
		||||
            <i class="iconfont icon-github"></i>
 | 
			
		||||
          </a>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
 | 
			
		||||
        <el-dropdown :hide-on-click="true" class="user-info" trigger="click" v-if="loginUser.id">
 | 
			
		||||
                        <span class="el-dropdown-link">
 | 
			
		||||
                          <el-image :src="loginUser.avatar"/>
 | 
			
		||||
                        </span>
 | 
			
		||||
          <template #dropdown>
 | 
			
		||||
            <el-dropdown-menu class="user-info-menu">
 | 
			
		||||
              <el-dropdown-item @click="showConfigDialog = true">
 | 
			
		||||
                <el-icon>
 | 
			
		||||
                  <UserFilled/>
 | 
			
		||||
                </el-icon>
 | 
			
		||||
                <span class="username">{{ loginUser.nickname }}</span>
 | 
			
		||||
              </el-dropdown-item>
 | 
			
		||||
 | 
			
		||||
              <el-dropdown-item>
 | 
			
		||||
                <i class="iconfont icon-book"></i>
 | 
			
		||||
                <a href="https://github.com/yangjian102621/chatgpt-plus" target="_blank">
 | 
			
		||||
                  用户手册
 | 
			
		||||
                </a>
 | 
			
		||||
              </el-dropdown-item>
 | 
			
		||||
 | 
			
		||||
              <el-dropdown-item>
 | 
			
		||||
                <i class="iconfont icon-github"></i>
 | 
			
		||||
                <a href="https://ai.r9it.com/docs/" target="_blank">
 | 
			
		||||
                  Geek-AI {{ version }}
 | 
			
		||||
                </a>
 | 
			
		||||
              </el-dropdown-item>
 | 
			
		||||
              <el-divider style="margin: 2px 0"/>
 | 
			
		||||
              <el-dropdown-item @click="logout">
 | 
			
		||||
                <i class="iconfont icon-logout"></i>
 | 
			
		||||
                <span>退出登录</span>
 | 
			
		||||
              </el-dropdown-item>
 | 
			
		||||
            </el-dropdown-menu>
 | 
			
		||||
          </template>
 | 
			
		||||
          <template #default>
 | 
			
		||||
            <ul class="more-menus">
 | 
			
		||||
              <li v-for="item in moreNavs" :key="item.url" :class="item.url === curPath ? 'active' : ''">
 | 
			
		||||
                <a @click="changeNav(item)">
 | 
			
		||||
                  <el-image :src="item.icon" style="width: 20px;height: 20px"/>
 | 
			
		||||
                  <span :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</span>
 | 
			
		||||
        </el-dropdown>
 | 
			
		||||
 | 
			
		||||
        <div v-else>
 | 
			
		||||
          <el-button size="small" color="#21aa93" @click="store.setShowLoginDialog(true)" round>登录</el-button>
 | 
			
		||||
          <el-button size="small" @click="router.push('/register')" round>注册</el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="main">
 | 
			
		||||
      <div class="navigator">
 | 
			
		||||
        <ul class="nav-items">
 | 
			
		||||
          <li v-for="item in mainNavs" :key="item.url">
 | 
			
		||||
            <el-tooltip
 | 
			
		||||
                effect="light"
 | 
			
		||||
                :content="item.name"
 | 
			
		||||
                placement="right">
 | 
			
		||||
              <a @click="changeNav(item)" :class="item.url === curPath ? 'active' : ''">
 | 
			
		||||
                <el-image :src="item.icon" style="width: 30px;height: 30px"/>
 | 
			
		||||
              </a>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </li>
 | 
			
		||||
 | 
			
		||||
          <el-popover
 | 
			
		||||
              v-if="moreNavs.length > 0"
 | 
			
		||||
              placement="right-end"
 | 
			
		||||
              trigger="hover"
 | 
			
		||||
          >
 | 
			
		||||
            <template #reference>
 | 
			
		||||
              <li>
 | 
			
		||||
                <a class="active">
 | 
			
		||||
                  <el-image src="/images/menu/more.png" style="width: 30px;height: 30px"/>
 | 
			
		||||
                </a>
 | 
			
		||||
              </li>
 | 
			
		||||
            </ul>
 | 
			
		||||
          </template>
 | 
			
		||||
        </el-popover>
 | 
			
		||||
      </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="content">
 | 
			
		||||
      <router-view v-slot="{ Component }">
 | 
			
		||||
        <transition name="move" mode="out-in">
 | 
			
		||||
          <component :is="Component"></component>
 | 
			
		||||
        </transition>
 | 
			
		||||
      </router-view>
 | 
			
		||||
            </template>
 | 
			
		||||
            <template #default>
 | 
			
		||||
              <ul class="more-menus">
 | 
			
		||||
                <li v-for="item in moreNavs" :key="item.url" :class="item.url === curPath ? 'active' : ''">
 | 
			
		||||
                  <a @click="changeNav(item)">
 | 
			
		||||
                    <el-image :src="item.icon" style="width: 20px;height: 20px"/>
 | 
			
		||||
                    <span :class="item.url === curPath ? 'title active' : 'title'">{{ item.name }}</span>
 | 
			
		||||
                  </a>
 | 
			
		||||
                </li>
 | 
			
		||||
              </ul>
 | 
			
		||||
            </template>
 | 
			
		||||
          </el-popover>
 | 
			
		||||
        </ul>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <div class="content custom-scroll" :style="{height: mainWinHeight+'px'}">
 | 
			
		||||
        <router-view :key="routerViewKey" v-slot="{ Component }">
 | 
			
		||||
          <transition name="move" mode="out-in">
 | 
			
		||||
            <component :is="Component"></component>
 | 
			
		||||
          </transition>
 | 
			
		||||
        </router-view>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="show" @hide="store.setShowLoginDialog(false)" @success="loginCallback"/>
 | 
			
		||||
    <config-dialog v-if="loginUser.id" :show="showConfigDialog" @hide="showConfigDialog = false"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {onMounted, ref} from "vue";
 | 
			
		||||
import {onMounted, ref, watch} from "vue";
 | 
			
		||||
import {httpGet} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {UserFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import {removeUserToken} from "@/store/session";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
import ConfigDialog from "@/components/ConfigDialog.vue";
 | 
			
		||||
 | 
			
		||||
const router = useRouter();
 | 
			
		||||
const logo = ref('/images/logo.png');
 | 
			
		||||
const mainNavs = ref([])
 | 
			
		||||
const moreNavs = ref([])
 | 
			
		||||
const curPath = ref(router.currentRoute.value.path)
 | 
			
		||||
const title = ref("")
 | 
			
		||||
const mainWinHeight = window.innerHeight - 50
 | 
			
		||||
const loginUser = ref({})
 | 
			
		||||
const version = ref(process.env.VUE_APP_VERSION)
 | 
			
		||||
const routerViewKey = ref(0)
 | 
			
		||||
const showConfigDialog = ref(false)
 | 
			
		||||
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
const show = ref(false)
 | 
			
		||||
watch(() => store.showLoginDialog, (newValue) => {
 | 
			
		||||
  show.value = newValue
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
if (curPath.value === "/external") {
 | 
			
		||||
  curPath.value = router.currentRoute.value.query.url
 | 
			
		||||
}
 | 
			
		||||
const changeNav = (item) => {
 | 
			
		||||
  curPath.value = item.url
 | 
			
		||||
  router.push(item.url)
 | 
			
		||||
  if (item.url.indexOf("http") !== -1) { // 外部链接
 | 
			
		||||
    router.push({name: 'ExternalLink', query: {url: item.url}})
 | 
			
		||||
  } else {
 | 
			
		||||
    router.push(item.url)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  httpGet("/api/config/get?key=system").then(res => {
 | 
			
		||||
    logo.value = res.data['logo']
 | 
			
		||||
    logo.value = res.data.logo
 | 
			
		||||
    title.value = res.data.title
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  // 获取菜单
 | 
			
		||||
  httpGet("/api/menu/list").then(res => {
 | 
			
		||||
    mainNavs.value = res.data
 | 
			
		||||
    if (res.data.length > 7) {
 | 
			
		||||
      mainNavs.value = res.data.slice(0, 7)
 | 
			
		||||
      moreNavs.value = res.data.slice(7)
 | 
			
		||||
    // 根据窗口的高度计算应该显示多少菜单
 | 
			
		||||
    const rows = Math.floor((window.innerHeight - 90) / 60)
 | 
			
		||||
    if (res.data.length > rows) {
 | 
			
		||||
      mainNavs.value = res.data.slice(0, rows)
 | 
			
		||||
      moreNavs.value = res.data.slice(rows)
 | 
			
		||||
    }
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取系统菜单失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  init()
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const init = () => {
 | 
			
		||||
  checkSession().then(user => {
 | 
			
		||||
    loginUser.value = user
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const logout = function () {
 | 
			
		||||
  httpGet('/api/user/logout').then(() => {
 | 
			
		||||
    removeUserToken()
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    loginUser.value = {}
 | 
			
		||||
    // 刷新组件
 | 
			
		||||
    routerViewKey.value += 1
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
    ElMessage.error('注销失败!');
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const loginCallback = () => {
 | 
			
		||||
  init()
 | 
			
		||||
  // 刷新组件
 | 
			
		||||
  routerViewKey.value += 1
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
@import '@/assets/iconfont/iconfont.css';
 | 
			
		||||
.home {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  width 100%
 | 
			
		||||
 | 
			
		||||
  .navigator {
 | 
			
		||||
    display flex
 | 
			
		||||
    flex-flow column
 | 
			
		||||
    width 60px
 | 
			
		||||
    padding 10px 6px
 | 
			
		||||
    border-right: 1px solid #3c3c3c
 | 
			
		||||
    background-color: #25272D
 | 
			
		||||
 | 
			
		||||
    .logo {
 | 
			
		||||
      display flex
 | 
			
		||||
      flex-flow column
 | 
			
		||||
      align-items center
 | 
			
		||||
      cursor pointer
 | 
			
		||||
 | 
			
		||||
      .el-image {
 | 
			
		||||
        width 50px
 | 
			
		||||
        height 50px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .divider {
 | 
			
		||||
        border-bottom 1px solid #4A4A4A
 | 
			
		||||
        width 80%
 | 
			
		||||
        height 10px
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .nav-items {
 | 
			
		||||
      margin-top: 10px;
 | 
			
		||||
      padding 0 5px
 | 
			
		||||
 | 
			
		||||
      li {
 | 
			
		||||
        margin-bottom 15px
 | 
			
		||||
 | 
			
		||||
        a {
 | 
			
		||||
          color #DADBDC
 | 
			
		||||
          border-radius 10px
 | 
			
		||||
          width 48px
 | 
			
		||||
          height 48px
 | 
			
		||||
          display flex
 | 
			
		||||
          justify-content center
 | 
			
		||||
          align-items center
 | 
			
		||||
          cursor pointer
 | 
			
		||||
 | 
			
		||||
          .el-image {
 | 
			
		||||
            border-radius 10px
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          .iconfont {
 | 
			
		||||
            font-size 20px
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        a:hover, a.active {
 | 
			
		||||
          color #47fff1
 | 
			
		||||
          background-color #0F7A71
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .title {
 | 
			
		||||
          font-size: 12px
 | 
			
		||||
          padding-top: 5px
 | 
			
		||||
          color: #e5e7eb;
 | 
			
		||||
          text-align: center;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .active {
 | 
			
		||||
          color #47fff1
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .content {
 | 
			
		||||
    width: 100%
 | 
			
		||||
    height: 100vh
 | 
			
		||||
    box-sizing: border-box
 | 
			
		||||
    background-color #282c34
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.el-popper {
 | 
			
		||||
  .more-menus {
 | 
			
		||||
    li {
 | 
			
		||||
      padding 10px 15px
 | 
			
		||||
      cursor pointer
 | 
			
		||||
      border-radius 5px
 | 
			
		||||
      margin 5px 0
 | 
			
		||||
 | 
			
		||||
      .el-image {
 | 
			
		||||
        position: relative
 | 
			
		||||
        top 5px
 | 
			
		||||
        right 5px
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        background-color #f1f1f1
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    li.active {
 | 
			
		||||
      background-color #f1f1f1
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@import "@/assets/css/custom-scroll.styl"
 | 
			
		||||
@import "@/assets/css/home.styl"
 | 
			
		||||
</style>
 | 
			
		||||
 
 | 
			
		||||
@@ -600,8 +600,6 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <el-image-viewer @close="() => { previewURL = '' }" v-if="previewURL !== ''" :url-list="[previewURL]"/>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -616,19 +614,24 @@ import {checkSession} from "@/action/session";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {getSessionId} from "@/store/session";
 | 
			
		||||
import {copyObj, removeArrayItem} from "@/utils/libs";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const listBoxHeight = ref(window.innerHeight - 40)
 | 
			
		||||
const paramBoxHeight = ref(window.innerHeight - 150)
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const listBoxHeight = ref(0)
 | 
			
		||||
const paramBoxHeight = ref(0)
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const colWidth = ref(240)
 | 
			
		||||
const colWidth = ref(220)
 | 
			
		||||
const previewURL = ref("")
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
const resizeElement = function () {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 80
 | 
			
		||||
  paramBoxHeight.value = window.innerHeight - 160
 | 
			
		||||
};
 | 
			
		||||
resizeElement()
 | 
			
		||||
window.onresize = () => {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 40
 | 
			
		||||
  paramBoxHeight.value = window.innerHeight - 150
 | 
			
		||||
  resizeElement()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const rates = [
 | 
			
		||||
  {css: "square", value: "1:1", text: "1:1", img: "/images/mj/rate_1_1.png"},
 | 
			
		||||
  {css: "size1-2", value: "1:2", text: "1:2", img: "/images/mj/rate_1_2.png"},
 | 
			
		||||
@@ -746,8 +749,8 @@ const connect = () => {
 | 
			
		||||
        const message = String(reader.result)
 | 
			
		||||
        if (message === "FINISH") {
 | 
			
		||||
          page.value = 0
 | 
			
		||||
          fetchFinishJobs(page.value)
 | 
			
		||||
          isOver.value = false
 | 
			
		||||
          fetchFinishJobs(page.value)
 | 
			
		||||
        }
 | 
			
		||||
        fetchRunningJobs()
 | 
			
		||||
      }
 | 
			
		||||
@@ -898,7 +901,7 @@ const beforeUpload = (key) => {
 | 
			
		||||
// 图片上传
 | 
			
		||||
const uploadImg = (file) => {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -931,7 +934,7 @@ const uploadImg = (file) => {
 | 
			
		||||
const promptRef = ref(null)
 | 
			
		||||
const generate = () => {
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -993,6 +996,9 @@ const removeImage = (item) => {
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    httpPost("/api/mj/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => {
 | 
			
		||||
      ElMessage.success("任务删除成功")
 | 
			
		||||
      page.value = 0
 | 
			
		||||
      isOver.value = false
 | 
			
		||||
      fetchFinishJobs()
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("任务删除失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
@@ -1009,6 +1015,9 @@ const publishImage = (item, action) => {
 | 
			
		||||
  httpPost("/api/mj/publish", {id: item.id, action: action}).then(() => {
 | 
			
		||||
    ElMessage.success(text + "成功")
 | 
			
		||||
    item.publish = action
 | 
			
		||||
    page.value = 0
 | 
			
		||||
    isOver.value = false
 | 
			
		||||
    fetchFinishJobs()
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error(text + "失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
        <div class="sd-box">
 | 
			
		||||
          <h2>Stable Diffusion 创作中心</h2>
 | 
			
		||||
 | 
			
		||||
          <div class="sd-params" :style="{ height: paramBoxHeight + 'px' }">
 | 
			
		||||
          <div class="sd-params">
 | 
			
		||||
            <el-form :model="params" label-width="80px" label-position="left">
 | 
			
		||||
              <div class="param-line" style="padding-top: 10px">
 | 
			
		||||
                <el-form-item label="采样方法">
 | 
			
		||||
@@ -497,8 +497,6 @@
 | 
			
		||||
 | 
			
		||||
      </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -511,21 +509,25 @@ import Clipboard from "clipboard";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import {useRouter} from "vue-router";
 | 
			
		||||
import {getSessionId} from "@/store/session";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const listBoxHeight = ref(window.innerHeight - 40)
 | 
			
		||||
const paramBoxHeight = ref(window.innerHeight - 150)
 | 
			
		||||
const listBoxHeight = ref(0)
 | 
			
		||||
// const paramBoxHeight = ref(0)
 | 
			
		||||
const fullImgHeight = ref(window.innerHeight - 60)
 | 
			
		||||
const showTaskDialog = ref(false)
 | 
			
		||||
const item = ref({})
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const colWidth = ref(240)
 | 
			
		||||
const colWidth = ref(220)
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
const resizeElement = function () {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 80
 | 
			
		||||
  // paramBoxHeight.value = window.innerHeight - 200
 | 
			
		||||
};
 | 
			
		||||
resizeElement()
 | 
			
		||||
window.onresize = () => {
 | 
			
		||||
  listBoxHeight.value = window.innerHeight - 40
 | 
			
		||||
  paramBoxHeight.value = window.innerHeight - 150
 | 
			
		||||
  resizeElement()
 | 
			
		||||
}
 | 
			
		||||
const samplers = ["Euler a", "DPM++ 2S a", "DPM++ 2M", "DPM++ SDE", "DPM++ 2M SDE", "UniPC", "Restart"]
 | 
			
		||||
const schedulers = ["Automatic", "Karras", "Exponential", "Uniform"]
 | 
			
		||||
@@ -600,8 +602,8 @@ const connect = () => {
 | 
			
		||||
        const message = String(reader.result)
 | 
			
		||||
        if (message === "FINISH") {
 | 
			
		||||
          page.value = 0
 | 
			
		||||
          fetchFinishJobs()
 | 
			
		||||
          isOver.value = false
 | 
			
		||||
          fetchFinishJobs()
 | 
			
		||||
        }
 | 
			
		||||
        fetchRunningJobs()
 | 
			
		||||
      }
 | 
			
		||||
@@ -726,7 +728,7 @@ const generate = () => {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -765,6 +767,9 @@ const removeImage = (event, item) => {
 | 
			
		||||
  ).then(() => {
 | 
			
		||||
    httpPost("/api/sd/remove", {id: item.id, img_url: item.img_url, user_id: userId.value}).then(() => {
 | 
			
		||||
      ElMessage.success("任务删除成功")
 | 
			
		||||
      page.value = 0
 | 
			
		||||
      isOver.value = false
 | 
			
		||||
      fetchFinishJobs()
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("任务删除失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
@@ -782,6 +787,9 @@ const publishImage = (event, item, action) => {
 | 
			
		||||
  httpPost("/api/sd/publish", {id: item.id, action: action}).then(() => {
 | 
			
		||||
    ElMessage.success(text + "成功")
 | 
			
		||||
    item.publish = action
 | 
			
		||||
    page.value = 0
 | 
			
		||||
    isOver.value = false
 | 
			
		||||
    fetchFinishJobs()
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error(text + "失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
 
 | 
			
		||||
@@ -310,8 +310,8 @@ const data = ref({
 | 
			
		||||
const loading = ref(true)
 | 
			
		||||
const isOver = ref(false)
 | 
			
		||||
const imgType = ref("mj") // 图片类别
 | 
			
		||||
const listBoxHeight = window.innerHeight - 74
 | 
			
		||||
const colWidth = ref(240)
 | 
			
		||||
const listBoxHeight = window.innerHeight - 124
 | 
			
		||||
const colWidth = ref(220)
 | 
			
		||||
const fullImgHeight = ref(window.innerHeight - 60)
 | 
			
		||||
const showTaskDialog = ref(false)
 | 
			
		||||
const item = ref({})
 | 
			
		||||
@@ -395,6 +395,7 @@ onUnmounted(() => {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const changeImgType = () => {
 | 
			
		||||
  console.log(imgType.value)
 | 
			
		||||
  document.getElementById('waterfall-box').scrollTo(0, 0)
 | 
			
		||||
  page.value = 0
 | 
			
		||||
  data.value = {
 | 
			
		||||
 
 | 
			
		||||
@@ -84,8 +84,6 @@
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -97,17 +95,17 @@ import {ElMessage} from "element-plus";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import InviteList from "@/components/InviteList.vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const inviteURL = ref("")
 | 
			
		||||
const qrImg = ref("")
 | 
			
		||||
const qrImg = ref("/images/wx.png")
 | 
			
		||||
const inviteChatCalls = ref(0)
 | 
			
		||||
const inviteImgCalls = ref(0)
 | 
			
		||||
const hits = ref(0)
 | 
			
		||||
const regNum = ref(0)
 | 
			
		||||
const rate = ref(0)
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const store = useSharedStore()
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  initData()
 | 
			
		||||
@@ -152,7 +150,7 @@ const initData = () => {
 | 
			
		||||
      ElMessage.error("获取系统配置失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
@@ -163,7 +161,7 @@ const initData = () => {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  background-color: #282c34;
 | 
			
		||||
  height 100vh
 | 
			
		||||
  height 100%
 | 
			
		||||
  overflow-x hidden
 | 
			
		||||
  overflow-y visible
 | 
			
		||||
 | 
			
		||||
@@ -176,6 +174,7 @@ const initData = () => {
 | 
			
		||||
 | 
			
		||||
    h2 {
 | 
			
		||||
      color #ffffff;
 | 
			
		||||
      text-align center
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .share-box {
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,12 @@
 | 
			
		||||
 | 
			
		||||
          <el-row class="opt" :gutter="20">
 | 
			
		||||
            <el-col :span="8"><el-link type="primary" @click="router.push('/register')">注册</el-link></el-col>
 | 
			
		||||
            <el-col :span="8"><el-link @click="showResetPass = true">重置密码</el-link></el-col>
 | 
			
		||||
            <el-col :span="8"><el-link @click="router.push('/')">首页</el-link></el-col>
 | 
			
		||||
            <el-col :span="8">
 | 
			
		||||
              <el-link type="info" @click="showResetPass = true">重置密码</el-link>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <el-col :span="8">
 | 
			
		||||
              <el-link type="info" @click="router.push('/')">首页</el-link>
 | 
			
		||||
            </el-col>
 | 
			
		||||
          </el-row>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,10 @@
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="page-mark-map">
 | 
			
		||||
      <div class="inner custom-scroll">
 | 
			
		||||
        <div class="mark-map-box">
 | 
			
		||||
        <div class="mark-map-box" :style="{ height: leftBoxHeight + 'px' }">
 | 
			
		||||
          <h2>思维导图创作中心</h2>
 | 
			
		||||
 | 
			
		||||
          <div class="mark-map-params" :style="{ height: leftBoxHeight + 'px' }">
 | 
			
		||||
          <div class="mark-map-params">
 | 
			
		||||
            <el-form label-width="80px" label-position="left">
 | 
			
		||||
              <div class="param-line">
 | 
			
		||||
                你的需求?
 | 
			
		||||
@@ -69,9 +69,8 @@
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="right-box">
 | 
			
		||||
        <div class="chat-box">
 | 
			
		||||
          <div class="top-bar">
 | 
			
		||||
            <h2>思维导图</h2>
 | 
			
		||||
            <el-button @click="downloadImage" type="primary">
 | 
			
		||||
              <el-icon>
 | 
			
		||||
                <Download/>
 | 
			
		||||
@@ -91,13 +90,10 @@
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog =  false" @success="initData"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup>
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {nextTick, onMounted, onUnmounted, ref} from 'vue';
 | 
			
		||||
import {Markmap} from 'markmap-view';
 | 
			
		||||
import {Transformer} from 'markmap-lib';
 | 
			
		||||
@@ -106,9 +102,10 @@ import {httpGet} from "@/utils/http";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {Download} from "@element-plus/icons-vue";
 | 
			
		||||
import {Toolbar} from 'markmap-toolbar';
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const leftBoxHeight = ref(window.innerHeight - 105)
 | 
			
		||||
const rightBoxHeight = ref(window.innerHeight - 85)
 | 
			
		||||
const rightBoxHeight = ref(window.innerHeight - 115)
 | 
			
		||||
 | 
			
		||||
const prompt = ref("")
 | 
			
		||||
const text = ref(`# Geek-AI 助手
 | 
			
		||||
@@ -126,10 +123,10 @@ const md = require('markdown-it')({breaks: true});
 | 
			
		||||
const content = ref(text.value)
 | 
			
		||||
const html = ref("")
 | 
			
		||||
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const isLogin = ref(false)
 | 
			
		||||
const loginUser = ref({power: 0})
 | 
			
		||||
const transformer = new Transformer();
 | 
			
		||||
const store = useSharedStore();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const svgRef = ref(null)
 | 
			
		||||
@@ -151,21 +148,21 @@ onMounted(() => {
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const initData = () => {
 | 
			
		||||
  httpGet("/api/model/list").then(res => {
 | 
			
		||||
    for (let v of res.data) {
 | 
			
		||||
      if (v.platform === "OpenAI" && v.value.indexOf("gpt-4-gizmo") === -1) {
 | 
			
		||||
        models.value.push(v)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    modelID.value = models.value[0].id
 | 
			
		||||
  }).catch(e => {
 | 
			
		||||
    ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
  })
 | 
			
		||||
  
 | 
			
		||||
  checkSession().then(user => {
 | 
			
		||||
    loginUser.value = user
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
 | 
			
		||||
    httpGet("/api/model/list").then(res => {
 | 
			
		||||
      for (let v of res.data) {
 | 
			
		||||
        if (v.platform === "OpenAI" && v.value.indexOf("gpt-4-gizmo") === -1) {
 | 
			
		||||
          models.value.push(v)
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      modelID.value = models.value[0].id
 | 
			
		||||
      connect(user.id)
 | 
			
		||||
    }).catch(e => {
 | 
			
		||||
      ElMessage.error("获取模型失败:" + e.message)
 | 
			
		||||
    })
 | 
			
		||||
    connect(user.id)
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  });
 | 
			
		||||
}
 | 
			
		||||
@@ -206,7 +203,7 @@ window.onresize = () => {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const socket = ref(null)
 | 
			
		||||
const heartbeatHandle = ref(null)
 | 
			
		||||
const heartbeatHandle = ref(0)
 | 
			
		||||
const connect = (userId) => {
 | 
			
		||||
  if (socket.value !== null) {
 | 
			
		||||
    socket.value.close()
 | 
			
		||||
@@ -293,7 +290,7 @@ const generateAI = () => {
 | 
			
		||||
    return ElMessage.error("请输入你的需求")
 | 
			
		||||
  }
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
  loading.value = true
 | 
			
		||||
 
 | 
			
		||||
@@ -1,102 +1,93 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
    <div class="member custom-scroll">
 | 
			
		||||
      <div class="title">
 | 
			
		||||
        会员充值中心
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="inner" :style="{height: listBoxHeight + 'px'}">
 | 
			
		||||
        <el-row :gutter="20">
 | 
			
		||||
          <el-col :span="7">
 | 
			
		||||
            <div class="user-profile">
 | 
			
		||||
              <user-profile/>
 | 
			
		||||
      <div class="inner">
 | 
			
		||||
        <div class="user-profile">
 | 
			
		||||
          <user-profile/>
 | 
			
		||||
 | 
			
		||||
              <el-row class="user-opt" :gutter="20">
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                  <el-button type="primary" @click="showPasswordDialog = true">修改密码</el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                  <el-button type="primary" @click="showBindMobileDialog = true">更改账号</el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                  <el-button type="primary" v-if="enableReward" @click="showRewardDialog = true">加入众筹</el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
                <el-col :span="12">
 | 
			
		||||
                  <el-button type="primary" v-if="enableReward" @click="showRewardVerifyDialog = true">众筹核销
 | 
			
		||||
                  </el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
          <el-row class="user-opt" :gutter="20">
 | 
			
		||||
            <el-col :span="12">
 | 
			
		||||
              <el-button type="primary" @click="showPasswordDialog = true">修改密码</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <el-col :span="12">
 | 
			
		||||
              <el-button type="primary" @click="showBindMobileDialog = true">更改账号</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <el-col :span="12">
 | 
			
		||||
              <el-button type="primary" v-if="enableReward" @click="showRewardDialog = true">加入众筹</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
            <el-col :span="12">
 | 
			
		||||
              <el-button type="primary" v-if="enableReward" @click="showRewardVerifyDialog = true">众筹核销
 | 
			
		||||
              </el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
 | 
			
		||||
                <el-col :span="24" style="padding-top: 30px" v-if="isLogin">
 | 
			
		||||
                  <el-button type="danger" round @click="logout">退出登录</el-button>
 | 
			
		||||
                </el-col>
 | 
			
		||||
              </el-row>
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-col>
 | 
			
		||||
            <el-col :span="24" style="padding-top: 30px" v-if="isLogin">
 | 
			
		||||
              <el-button type="danger" round @click="logout">退出登录</el-button>
 | 
			
		||||
            </el-col>
 | 
			
		||||
          </el-row>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
          <el-col :span="17">
 | 
			
		||||
            <div class="product-box">
 | 
			
		||||
              <div class="info" v-if="orderPayInfoText !== ''">
 | 
			
		||||
                <el-alert type="success" show-icon :closable="false" effect="dark">
 | 
			
		||||
                  <strong>说明:</strong> {{ vipInfoText }}
 | 
			
		||||
                </el-alert>
 | 
			
		||||
              </div>
 | 
			
		||||
        <div class="product-box">
 | 
			
		||||
          <div class="info" v-if="orderPayInfoText !== ''">
 | 
			
		||||
            <el-alert type="success" show-icon :closable="false" effect="dark">
 | 
			
		||||
              <strong>说明:</strong> {{ vipInfoText }}
 | 
			
		||||
            </el-alert>
 | 
			
		||||
          </div>
 | 
			
		||||
 | 
			
		||||
              <ItemList :items="list" v-if="list.length > 0" :gap="30" :width="240">
 | 
			
		||||
                <template #default="scope">
 | 
			
		||||
                  <div class="product-item" :style="{width: scope.width+'px'}">
 | 
			
		||||
                    <div class="image-container">
 | 
			
		||||
                      <el-image :src="vipImg" fit="cover"/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="product-title">
 | 
			
		||||
                      <span class="name">{{ scope.item.name }}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="product-info">
 | 
			
		||||
                      <div class="info-line">
 | 
			
		||||
                        <span class="label">商品原价:</span>
 | 
			
		||||
                        <span class="price">¥{{ scope.item.price }}</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div class="info-line">
 | 
			
		||||
                        <span class="label">促销立减:</span>
 | 
			
		||||
                        <span class="price">¥{{ scope.item.discount }}</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
                      <div class="info-line">
 | 
			
		||||
                        <span class="label">有效期:</span>
 | 
			
		||||
                        <span class="expire" v-if="scope.item.days > 0">{{ scope.item.days }}天</span>
 | 
			
		||||
                        <span class="expire" v-else>长期有效</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
 | 
			
		||||
                      <div class="info-line">
 | 
			
		||||
                        <span class="label">算力值:</span>
 | 
			
		||||
                        <span class="power" v-if="scope.item.power > 0">{{ scope.item.power }}</span>
 | 
			
		||||
                        <span class="power" v-else>{{ vipMonthPower }}</span>
 | 
			
		||||
                      </div>
 | 
			
		||||
 | 
			
		||||
                      <div class="pay-way">
 | 
			
		||||
                        <el-button type="primary" @click="alipay(scope.item)" size="small" v-if="payWays['alipay']">
 | 
			
		||||
                          <i class="iconfont icon-alipay"></i> 支付宝
 | 
			
		||||
                        </el-button>
 | 
			
		||||
                        <el-button type="success" @click="huPiPay(scope.item)" size="small" v-if="payWays['hupi']">
 | 
			
		||||
                          <span v-if="payWays['hupi']['name'] === 'wechat'"><i class="iconfont icon-wechat-pay"></i> 微信</span>
 | 
			
		||||
                          <span v-else><i class="iconfont icon-alipay"></i> 支付宝</span>
 | 
			
		||||
                        </el-button>
 | 
			
		||||
 | 
			
		||||
                        <el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
 | 
			
		||||
                          <span><i class="iconfont icon-wechat-pay"></i> 微信</span>
 | 
			
		||||
                        </el-button>
 | 
			
		||||
                      </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
          <ItemList :items="list" v-if="list.length > 0" :gap="15" :width="240">
 | 
			
		||||
            <template #default="scope">
 | 
			
		||||
              <div class="product-item">
 | 
			
		||||
                <div class="image-container">
 | 
			
		||||
                  <el-image :src="vipImg" fit="cover"/>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="product-title">
 | 
			
		||||
                  <span class="name">{{ scope.item.name }}</span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="product-info">
 | 
			
		||||
                  <div class="info-line">
 | 
			
		||||
                    <span class="label">商品原价:</span>
 | 
			
		||||
                    <span class="price">¥{{ scope.item.price }}</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="info-line">
 | 
			
		||||
                    <span class="label">促销立减:</span>
 | 
			
		||||
                    <span class="price">¥{{ scope.item.discount }}</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                  <div class="info-line">
 | 
			
		||||
                    <span class="label">有效期:</span>
 | 
			
		||||
                    <span class="expire" v-if="scope.item.days > 0">{{ scope.item.days }}天</span>
 | 
			
		||||
                    <span class="expire" v-else>长期有效</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </template>
 | 
			
		||||
              </ItemList>
 | 
			
		||||
 | 
			
		||||
              <h2 class="headline">消费账单</h2>
 | 
			
		||||
                  <div class="info-line">
 | 
			
		||||
                    <span class="label">算力值:</span>
 | 
			
		||||
                    <span class="power" v-if="scope.item.power > 0">{{ scope.item.power }}</span>
 | 
			
		||||
                    <span class="power" v-else>{{ vipMonthPower }}</span>
 | 
			
		||||
                  </div>
 | 
			
		||||
 | 
			
		||||
              <div class="user-order">
 | 
			
		||||
                <user-order v-if="isLogin"/>
 | 
			
		||||
                  <div class="pay-way">
 | 
			
		||||
                    <el-button type="primary" @click="alipay(scope.item)" size="small" v-if="payWays['alipay']">
 | 
			
		||||
                      <i class="iconfont icon-alipay"></i> 支付宝
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                    <el-button type="success" @click="huPiPay(scope.item)" size="small" v-if="payWays['hupi']">
 | 
			
		||||
                      <span v-if="payWays['hupi']['name'] === 'wechat'"><i
 | 
			
		||||
                          class="iconfont icon-wechat-pay"></i> 微信</span>
 | 
			
		||||
                      <span v-else><i class="iconfont icon-alipay"></i> 支付宝</span>
 | 
			
		||||
                    </el-button>
 | 
			
		||||
 | 
			
		||||
                    <el-button type="success" @click="PayJs(scope.item)" size="small" v-if="payWays['payjs']">
 | 
			
		||||
                      <span><i class="iconfont icon-wechat-pay"></i> 微信</span>
 | 
			
		||||
                    </el-button>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </div>
 | 
			
		||||
              </div>
 | 
			
		||||
            </div>
 | 
			
		||||
          </el-col>
 | 
			
		||||
        </el-row>
 | 
			
		||||
            </template>
 | 
			
		||||
          </ItemList>
 | 
			
		||||
 | 
			
		||||
          <h2 class="headline">消费账单</h2>
 | 
			
		||||
 | 
			
		||||
          <div class="user-order">
 | 
			
		||||
            <user-order v-if="isLogin"/>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
 | 
			
		||||
      <password-dialog v-if="isLogin" :show="showPasswordDialog" @hide="showPasswordDialog = false"
 | 
			
		||||
@@ -157,7 +148,6 @@
 | 
			
		||||
      </el-dialog>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <login-dialog :show="showLoginDialog" @hide="showLoginDialog = false" @success="loginSuccess"/>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
@@ -167,7 +157,6 @@ import {ElMessage} from "element-plus";
 | 
			
		||||
import {httpGet, httpPost} from "@/utils/http";
 | 
			
		||||
import ItemList from "@/components/ItemList.vue";
 | 
			
		||||
import {InfoFilled, SuccessFilled} from "@element-plus/icons-vue";
 | 
			
		||||
import LoginDialog from "@/components/LoginDialog.vue";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
import UserProfile from "@/components/UserProfile.vue";
 | 
			
		||||
import PasswordDialog from "@/components/PasswordDialog.vue";
 | 
			
		||||
@@ -177,10 +166,9 @@ import {useRouter} from "vue-router";
 | 
			
		||||
import {removeUserToken} from "@/store/session";
 | 
			
		||||
import UserOrder from "@/components/UserOrder.vue";
 | 
			
		||||
import CountDown from "@/components/CountDown.vue";
 | 
			
		||||
import {useSharedStore} from "@/store/sharedata";
 | 
			
		||||
 | 
			
		||||
const listBoxHeight = window.innerHeight - 97
 | 
			
		||||
const list = ref([])
 | 
			
		||||
const showLoginDialog = ref(false)
 | 
			
		||||
const showPayDialog = ref(false)
 | 
			
		||||
const vipImg = ref("/images/vip.png")
 | 
			
		||||
const enableReward = ref(false) // 是否启用众筹功能
 | 
			
		||||
@@ -208,6 +196,7 @@ const amount = ref(0)
 | 
			
		||||
const payName = ref("支付宝")
 | 
			
		||||
const curPay = ref("alipay") // 当前支付方式
 | 
			
		||||
const vipInfoText = ref("")
 | 
			
		||||
const store = useSharedStore()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
@@ -215,7 +204,7 @@ onMounted(() => {
 | 
			
		||||
    user.value = _user
 | 
			
		||||
    isLogin.value = true
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
  })
 | 
			
		||||
 | 
			
		||||
  httpGet("/api/product/list").then((res) => {
 | 
			
		||||
@@ -281,7 +270,7 @@ const alipay = (row) => {
 | 
			
		||||
  curPay.value = "alipay"
 | 
			
		||||
  amount.value = (row.price - row.discount).toFixed(2)
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -297,7 +286,7 @@ const huPiPay = (row) => {
 | 
			
		||||
  curPay.value = "hupi"
 | 
			
		||||
  amount.value = (row.price - row.discount).toFixed(2)
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -313,7 +302,7 @@ const PayJs = (row) => {
 | 
			
		||||
  curPay.value = "payjs"
 | 
			
		||||
  amount.value = (row.price - row.discount).toFixed(2)
 | 
			
		||||
  if (!isLogin.value) {
 | 
			
		||||
    showLoginDialog.value = true
 | 
			
		||||
    store.setShowLoginDialog(true)
 | 
			
		||||
    return
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="power-log" v-loading="loading">
 | 
			
		||||
    <div class="inner">
 | 
			
		||||
      <h2>消费日志</h2>
 | 
			
		||||
 | 
			
		||||
      <div class="list-box" :style="{height: listBoxHeight + 'px'}">
 | 
			
		||||
  <div class="power-log custom-scroll" v-loading="loading">
 | 
			
		||||
    <div class="inner" :style="{height: listBoxHeight + 'px'}">
 | 
			
		||||
      <div class="list-box">
 | 
			
		||||
        <div class="handle-box">
 | 
			
		||||
          <el-input v-model="query.model" placeholder="模型" class="handle-input mr10" clearable></el-input>
 | 
			
		||||
          <el-date-picker
 | 
			
		||||
@@ -13,9 +11,9 @@
 | 
			
		||||
              end-placeholder="结束日期"
 | 
			
		||||
              format="YYYY-MM-DD"
 | 
			
		||||
              value-format="YYYY-MM-DD"
 | 
			
		||||
              style="margin: 0 10px;width: 200px; position: relative;top:3px;"
 | 
			
		||||
              style="margin: 0 10px;width: 200px;"
 | 
			
		||||
          />
 | 
			
		||||
          <el-button type="primary" :icon="Search" @click="fetchData">搜索</el-button>
 | 
			
		||||
          <el-button color="#21aa93" :icon="Search" @click="fetchData">搜索</el-button>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <el-row v-if="items.length > 0">
 | 
			
		||||
@@ -73,21 +71,25 @@ import {Search} from "@element-plus/icons-vue";
 | 
			
		||||
import Clipboard from "clipboard";
 | 
			
		||||
import {ElMessage} from "element-plus";
 | 
			
		||||
import {httpPost} from "@/utils/http";
 | 
			
		||||
import {checkSession} from "@/action/session";
 | 
			
		||||
 | 
			
		||||
const items = ref([])
 | 
			
		||||
const total = ref(0)
 | 
			
		||||
const page = ref(1)
 | 
			
		||||
const pageSize = ref(20)
 | 
			
		||||
const loading = ref(false)
 | 
			
		||||
const listBoxHeight = window.innerHeight - 117
 | 
			
		||||
const listBoxHeight = window.innerHeight - 87
 | 
			
		||||
const query = ref({
 | 
			
		||||
  model: "",
 | 
			
		||||
  date: []
 | 
			
		||||
})
 | 
			
		||||
const tagColors = ref(["", "success", "", "danger", "info", "warning"])
 | 
			
		||||
const tagColors = ref(["primary", "success", "primary", "danger", "info", "warning"])
 | 
			
		||||
 | 
			
		||||
onMounted(() => {
 | 
			
		||||
  fetchData()
 | 
			
		||||
  checkSession().then(() => {
 | 
			
		||||
    fetchData()
 | 
			
		||||
  }).catch(() => {
 | 
			
		||||
  })
 | 
			
		||||
  const clipboard = new Clipboard('.copy-order-no');
 | 
			
		||||
  clipboard.on('success', () => {
 | 
			
		||||
    ElMessage.success("复制成功!");
 | 
			
		||||
@@ -123,33 +125,12 @@ const fetchData = () => {
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style lang="stylus" scoped>
 | 
			
		||||
@import "@/assets/css/custom-scroll.styl"
 | 
			
		||||
.power-log {
 | 
			
		||||
  color #ffffff
 | 
			
		||||
  .inner {
 | 
			
		||||
    padding 0 20px 20px 20px
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar {
 | 
			
		||||
      width: 8px; /* 滚动条宽度 */
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条轨道的背景颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-track {
 | 
			
		||||
      background-color: #ffffff;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条的滑块颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-thumb {
 | 
			
		||||
      background-color: #cccccc;
 | 
			
		||||
      border-radius 8px
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /* 修改滚动条的滑块的悬停颜色 */
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-thumb:hover {
 | 
			
		||||
      background-color: #999999;
 | 
			
		||||
    }
 | 
			
		||||
    overflow auto
 | 
			
		||||
 | 
			
		||||
    .list-box {
 | 
			
		||||
      overflow-x hidden
 | 
			
		||||
 
 | 
			
		||||
@@ -528,6 +528,10 @@ const onUploadImg = (files, callback) => {
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .el-input {
 | 
			
		||||
          width 100%
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .el-descriptions {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user