├── .gitattributes ├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── config.json ├── config └── config.go ├── controllers ├── AlpacaAI.go ├── Github.go └── Pong.go ├── go.mod ├── go.sum ├── lib ├── ai │ ├── baiduAI.go │ ├── tuling.go │ └── xiaosi.go ├── mysql │ └── mysql.go └── redis │ └── redis.go ├── main.go ├── middleware └── jwt │ └── jwt.go ├── models └── model.json ├── route └── routes.go └── views ├── babel.config.js ├── dist ├── css │ ├── app.a225fa1f.css │ ├── chunk-2e1de229.60951e7e.css │ ├── chunk-62af08d6.1d96d0bd.css │ ├── chunk-7ce5de4d.d6814b87.css │ └── chunk-vendors.0d331718.css ├── favicon.ico ├── finger.cur ├── fonts │ ├── element-icons.535877f5.woff │ └── element-icons.732389de.ttf ├── img │ └── avatar.5c94d5d3.jpeg ├── index.html └── js │ ├── app.e0b6bc08.js │ ├── chunk-2e1de229.ec6496b8.js │ ├── chunk-62af08d6.46a79f12.js │ ├── chunk-7ce5de4d.fc1a92e8.js │ └── chunk-vendors.bd9905e2.js ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── finger.cur └── index.html ├── src ├── App.vue ├── assets │ ├── images │ │ └── avatar.jpeg │ └── logo.png ├── components │ ├── AboutSection │ │ ├── Contact.vue │ │ ├── Info.vue │ │ ├── Profile.vue │ │ └── Skills.vue │ ├── AlpacaAI.vue │ ├── HelloWorld.vue │ ├── LeftMenu.vue │ ├── LoginDialog.vue │ └── TopBar.vue ├── data │ └── data.ts ├── image.d.ts ├── main.ts ├── router.ts ├── shime-global.d.ts ├── shims-tsx.d.ts ├── shims-vue.d.ts ├── store.ts ├── utils │ ├── ajax.ts │ └── sleep.ts └── views │ ├── Home.vue │ └── Home1.vue ├── tsconfig.json ├── tslint.json └── vue.config.js /.gitattributes: -------------------------------------------------------------------------------- 1 | *.vue linguist-language=TypeScript 2 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: DEPLOY_ALPACA_RUN 4 | # Controls when the action will run. 5 | on: 6 | # Triggers the workflow on push or pull request events but only for the main branch 7 | push: 8 | branches: [ master ] 9 | pull_request: 10 | branches: [ master ] 11 | 12 | # Allows you to run this workflow manually from the Actions tab 13 | workflow_dispatch: 14 | 15 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 16 | jobs: 17 | # This workflow contains a single job called "build" 18 | build: 19 | # The type of runner that the job will run on 20 | runs-on: ubuntu-20.04 21 | 22 | # Steps represent a sequence of tasks that will be executed as part of the job 23 | steps: 24 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it 25 | - uses: actions/checkout@v2 26 | 27 | # use scp to copy file to my server 28 | - name: copy public folder to web server 29 | uses: appleboy/scp-action@master 30 | with: 31 | host: ${{ secrets.HOST }} 32 | username: ${{ secrets.USER }} 33 | key: ${{ secrets.SSH_KEY }} 34 | passphrase: ${{ secrets.PASSWORD }} 35 | port: ${{ secrets.PORT }} 36 | source: "views/dist/." 37 | target: "/home/alpaca_blog/" 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | views/node_modules 3 | 4 | # local env files 5 | .env.local 6 | .env.*.local 7 | 8 | # Log files 9 | views/npm-debug.log* 10 | views/yarn-debug.log* 11 | views/yarn-error.log* 12 | 13 | # Editor directories and files 14 | .idea 15 | .vscode 16 | *.suo 17 | *.ntvs* 18 | *.njsproj 19 | *.sln 20 | *.sw 21 | 22 | #golang 23 | __debug_bin 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Alpaca Run 2 | 3 | ## 简介 4 | 本项目是一个个人网站,开发的技术栈和工具有 5 | - TypeScript 6 | - Vue.js 7 | - Golang 8 | - Gin 9 | - Redis 10 | - MySQL 11 | - JWT 12 | - Graphql(暂时没上) 13 | 14 | ## 如何运行 15 | 注意:本项目目前还在开发中,大部分功能尚未开发完成 16 | 17 | ### 事先做好准备: 18 | - 安装Node.js 19 | - 安装Go和配置相关环境变量 20 | - 装好redis和mysql 21 | - 服务器端安装nginx 22 | - 安装以下Go库(go get一把梭就好) 23 | - github.com/gin-gonic/gin 24 | - github.com/go-redis/redis 25 | - github.com/go-sql-driver/mysql 26 | - github.com/jmoiron/sqlx 27 | - github.com/json-iterator/go 28 | - github.com/bitly/go-simplejson 29 | 30 | ### 前端: 31 | 本项目的前端部分在根目录的`views`文件夹下,所以要先进入`views`文件夹 32 | 本前端项目是由vue-cli3搭建的,所以也是常规方式: 33 | 安装npm包 `npm install` 34 | 开发模式 `npm run serve` 35 | 打包 `npm run build` 36 | 当你打包好后,把打包好的文件丢到linux服务器,再用nginx配置下就好了,怎么配置自己google 37 | 38 | ### 后端: 39 | 1. 把项目复制到Go目录的src目录下,直接`go build main.go`就能打包出可执行文件`main`了 40 | 2. 因为我用的linux电脑,所以可以直接这么来,如果你用的是window电脑,要交叉编译改参数,这个你google就好,很简单的 41 | 3. 把可执行文件`main`和`config.json`,直接塞进你的linux服务器里,直接`nohup ./main &`就能跑起来了(他会自动读config.json配置的 42 | 43 | 如果想开发中调试,我用的vscode,可以给你参考下launch.json,args根据你电脑文件目录来 44 | ```json 45 | { 46 | "version": "1.0.0", 47 | "configurations": [ 48 | { 49 | "name": "Launch", 50 | "type": "go", 51 | "request": "launch", 52 | "mode": "debug", 53 | "program": "${workspaceRoot}", 54 | "env": {}, 55 | "args": ["-config", "/home/alpaca/GoEnv/src/alpaca_blog/config.json"] 56 | } 57 | ] 58 | } 59 | ``` 60 | ### config.json 61 | 可以更改config.json配置来动态更改go项目参数配置,重启你的go web服务就能生效 62 | ```json 63 | { 64 | "listen":":9527", 65 | "debug": true, 66 | "logFile": "alpaca_bi.log", 67 | "mysql": { 68 | "host": "localhost", 69 | "port": 3306, 70 | "user": "root", 71 | "password": "填你自己的mysql密码", 72 | "db": "alpacablog", 73 | "dbprefix": "alpaca_blog_" 74 | }, 75 | "redis": { 76 | "host": "localhost", 77 | "port": 6379, 78 | "auth": "填你自己的redis密码,一般没特地设置的话密码为空", 79 | "db": 0, 80 | "poolSize": 300 81 | }, 82 | "tuling":{ 83 | "apiKey":"填你自己的图灵机器人APIKey,去官网注册就能免费拿", 84 | "apiURL":"http://openapi.tuling123.com/openapi/api/v2" 85 | }, 86 | "xiaosi":{ 87 | "appID":"填你自己的小思机器人AppID,去官网注册就能免费拿", 88 | "apiURL":"https://api.ownthink.com/bot" 89 | }, 90 | "baiduAI":{ 91 | "apiKey":"填你自己百度AI的APIKey,去官网注册就能免费拿", 92 | "secretKey":"填你自己百度AI的SecretKey,去官网注册就能免费拿" 93 | } 94 | } 95 | ``` 96 | 97 | ## 联系我 98 | 如果你遇到问题,或者想交流技术,可以加我微信或者电报 99 |

100 | wechat 101 |

102 | 103 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "listen":":9527", 3 | "debug": true, 4 | "logFile": "alpaca_bi.log", 5 | "mysql": { 6 | "host": "localhost", 7 | "port": 3306, 8 | "user": "root", 9 | "password": "填你自己的mysql密码", 10 | "db": "alpacablog", 11 | "dbprefix": "alpaca_blog_" 12 | }, 13 | "redis": { 14 | "host": "localhost", 15 | "port": 6379, 16 | "auth": "填你自己的redis密码,一般没特地设置的话密码为空", 17 | "db": 0, 18 | "poolSize": 300 19 | }, 20 | "tuling":{ 21 | "apiKey":"填你自己的图灵机器人APIKey,去官网注册就能免费拿", 22 | "apiURL":"http://openapi.tuling123.com/openapi/api/v2" 23 | }, 24 | "xiaosi":{ 25 | "appID":"填你自己的小思机器人AppID,去官网注册就能免费拿", 26 | "apiURL":"https://api.ownthink.com/bot" 27 | }, 28 | "baiduAI":{ 29 | "apiKey":"填你自己百度AI的APIKey,去官网注册就能免费拿", 30 | "secretKey":"填你自己百度AI的SecretKey,去官网注册就能免费拿" 31 | } 32 | } -------------------------------------------------------------------------------- /config/config.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | import ( 4 | "alpaca_blog/lib/mysql" 5 | "alpaca_blog/lib/redis" 6 | "flag" 7 | "log" 8 | "os" 9 | "os/exec" 10 | "path" 11 | "path/filepath" 12 | 13 | jsoniter "github.com/json-iterator/go" 14 | ) 15 | 16 | var json = jsoniter.ConfigCompatibleWithStandardLibrary 17 | 18 | type configuration struct { 19 | Listen string `json:"listen"` 20 | Debug bool `json:"debug"` 21 | LogFile string `json:"logFile"` //日志 22 | Mysql mysql.Config `json:"mysql"` 23 | Redis redis.Config `json:"redis"` 24 | Tuling Tuling `json:"tuling"` //图灵机器人 25 | Xiaosi Xiaosi `json:"xiaosi"` //小思机器人 26 | BaiduAI BaiduAI `json:"baiduAI"` //小思机器人 27 | 28 | } 29 | 30 | //Tuling 图灵机器人参数 31 | type Tuling struct { 32 | APIKey string `json:"apiKey"` //图灵机器人APIKey 33 | APIURL string `json:"apiURL"` //图灵机器人接口URL 34 | } 35 | 36 | //Xiaosi 小思机器人参数 37 | type Xiaosi struct { 38 | AppID string `json:"appID"` //小思机器人APIKey 39 | APIURL string `json:"apiURL"` //小思机器人接口URL 40 | } 41 | 42 | //BaiduAI 百度AI机器人参数 43 | type BaiduAI struct { 44 | APIKey string `json:"apiKey"` //百度AI APIKey 45 | SecretKey string `json:"secretKey"` //百度AI SecretKey 46 | } 47 | 48 | //Current the current configuration 49 | var Current configuration 50 | 51 | //Init init the configuration 52 | func init() { 53 | Current = configuration{ 54 | ":9527", 55 | true, 56 | "alpaca_blog.log", 57 | mysql.Config{ 58 | "", 59 | 0, 60 | "", 61 | "", 62 | "", 63 | "", 64 | 0, 65 | 0, 66 | 0, 67 | }, 68 | redis.Config{ 69 | "", 70 | 0, 71 | "", 72 | 0, 73 | 0, 74 | }, 75 | Tuling{ 76 | "", 77 | "", 78 | }, 79 | Xiaosi{ 80 | "", 81 | "", 82 | }, 83 | BaiduAI{ 84 | "", 85 | "", 86 | }, 87 | } 88 | 89 | basePath, _ := exec.LookPath(os.Args[0]) 90 | path, _ := filepath.Abs(basePath) 91 | configFile := filepath.Join(filepath.Dir(path), "config.json") 92 | if len(os.Args) > 1 { 93 | configFile = os.Args[1] 94 | } 95 | file, err := os.Open(configFile) 96 | 97 | if err != nil { 98 | return 99 | } 100 | defer file.Close() 101 | 102 | decoder := json.NewDecoder(file) 103 | err = decoder.Decode(&Current) 104 | if err != nil { 105 | log.Print(err) 106 | return 107 | } 108 | } 109 | 110 | //LoadFromFile load config from file 111 | func LoadFromFile(path string) error { 112 | file, err := os.Open(path) 113 | if err != nil { 114 | return err 115 | } 116 | defer file.Close() 117 | decoder := json.NewDecoder(file) 118 | return decoder.Decode(&Current) 119 | } 120 | 121 | func GetRootPath() string { 122 | basePath, _ := exec.LookPath(os.Args[0]) 123 | path, _ := filepath.Abs(basePath) 124 | return filepath.Dir(path) 125 | } 126 | 127 | func LoadConfig() { 128 | configFile := flag.String("config", "", "The config file path.") 129 | flag.Parse() 130 | 131 | // load config 132 | if len(*configFile) > 0 { 133 | log.Printf("load config from file: %s\n", *configFile) 134 | LoadFromFile(*configFile) 135 | } 136 | 137 | //setup log store path 138 | logPath := Current.LogFile 139 | if !filepath.IsAbs(logPath) { 140 | logPath = path.Join(GetRootPath(), logPath) 141 | } 142 | 143 | if !Current.Debug { //如果是调试模式,则直接输出到标准控制输出 144 | file, err := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 145 | if err != nil { 146 | panic(err) 147 | } 148 | log.SetOutput(file) 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /controllers/AlpacaAI.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "alpaca_blog/config" 5 | "alpaca_blog/lib/ai" 6 | "fmt" 7 | "math/rand" 8 | "strconv" 9 | "time" 10 | 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | // AIText 用于文字AI处理 15 | func AIText(c *gin.Context) { 16 | textType := c.Request.FormValue("textType") 17 | text := c.Request.FormValue("text") 18 | robot := ai.NewXiaosiRobot(config.Current.Xiaosi.AppID) 19 | 20 | isDirty := 0 21 | 22 | dirtyWord := [...]string{ 23 | "你是不是性無能所以在網上自我高潮找存在感", 24 | "你爸今晚连夜庭院种枇杷树", 25 | "你爸妈真会生 好的东西都自己留着", 26 | "我真的很想帮你治疗,但我是一名家庭医生,而你是一个孤儿。", 27 | "咋滴你管那么多呢?收粪车从你家门前路过你都要拿勺子尝尝咸淡?", 28 | "以前只知道厕所能被屎堵了,今天竟然看见有人脑子被屎堵了", 29 | "你能讲文明,讲素质的时候,我想是我再次投胎做人的时候。", 30 | "上帝把智慧洒满人间,就你打了个伞。", 31 | "你的户口本就是一动物百科", 32 | "你是我见过的容量最大的铅笔盒了,装那么多笔你不累吗?", 33 | "你这种脑残程度我称之为珍稀物种", 34 | "和你接触的时间越长,我就越喜欢狗,狗永远是狗,人有时候不是人。", 35 | "现在网上冲浪不需要智商的吗", 36 | "我是灵长类动物,和家禽没什么好说的", 37 | "我留你狗命是因为我想保护动物毕竟你做只狗不容易", 38 | "请你不要用你的排泄器官对我说话,这是很不礼貌的,谢谢!", 39 | "阁下长得真是天生励志!", 40 | "如果长的丑也算残疾的话,那你就不用工作了。", 41 | "我把你挂到迎客松上喜迎八方贵客", 42 | "你的嘴简直能给农田施肥", 43 | "把我气死,你当孤儿?", 44 | "只希望你吃饭有人喂 走路有人推 夜夜缠绵于病却长命百岁 不能生育却儿孙满堂 寿比昙花福如母猪 ​​​​", 45 | "别跟我说话,我有洁癖。", 46 | "别对着我叫,我小时候被狗吓过。", 47 | "你走的那天,风很大,走得很痛苦,火化的 时候还诈尸,一直喊着没有死,最后用铁链绑着烧完的。火很旺,家属很坚强一个哭的都 没有,甚至有一个忍不住笑出声。运骨灰的路上车翻了 ,把骨灰盒摔了,刚要捧点灰,来了一辆洒水车,洒水车走后,众人只好把混着泥巴的骨灰,随便捧点埋了,不久之后该地方拆迁,上面开了一家迪厅,每天重复播放着今天是个好日子。", 48 | "这么喜欢装逼 下辈子当条内裤好了", 49 | "百度不一定可以搜得到你 但搜狗一定可以", 50 | "W D N M D", 51 | "刚好,我QQ农场缺条🐶,我看你不错今天下午就来上班吧", 52 | "以后不要再说你一无所有了,你不是还有病吗", 53 | "真羡慕这种身份证拿出来就是全家福的人", 54 | "你妈买菜必涨价", 55 | "你的出生是杜蕾斯的一封道歉信", 56 | "天工造物不测,怎么造出你这么个东西", 57 | "尘归尘,土归土,把你骨灰扬了都不配做PM2.5", 58 | } 59 | 60 | baiduAI := ai.NewBaiduAI() 61 | info2, err := baiduAI.TextCensor(text) 62 | 63 | if err != nil { 64 | fmt.Println(err) 65 | } 66 | 67 | var msg string 68 | if info2.Get("conclusionType").MustInt() == 1 { 69 | msg = robot.GetXiaosiReplyMsg(text, "1") 70 | } else { 71 | 72 | isDirty = 1 73 | 74 | if textType == "npx" { 75 | 76 | msg = "检测到你的发言带有恶意!!!\n" 77 | 78 | keyword := "" 79 | 80 | for i := 0; i < len(info2.Get("data").MustArray()); i++ { 81 | if info2.Get("data").GetIndex(i).Get("type").MustInt() == 12 { 82 | 83 | fmt.Println(info2.Get("data").GetIndex(i).Get("type").MustInt()) 84 | subType := info2.Get("data").GetIndex(i).Get("subType").MustInt() 85 | 86 | probability, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("probability").MustFloat64()*100), 64) 87 | 88 | for j := 0; j < len(info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("words").MustArray()); j++ { 89 | keyword = keyword + "【" + info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("words").GetIndex(j).MustString() + "】" 90 | } 91 | 92 | if subType == 5 { 93 | msg = msg + "低俗辱骂:" 94 | } else if subType == 2 { 95 | msg = msg + "文本色情:" 96 | } else if subType == 1 { 97 | msg = msg + "暴恐违禁:" 98 | } else if subType == 3 { 99 | msg = msg + "政治敏感:" 100 | } 101 | 102 | msg = msg + "(" + strconv.FormatFloat(probability, 'f', -1, 64) + "%)\n" 103 | 104 | } 105 | 106 | } 107 | 108 | if keyword != "" { 109 | msg = msg + "关键词:" + keyword 110 | } 111 | 112 | rand.Seed(time.Now().UnixNano()) 113 | msg = msg + "\n\n\n" + dirtyWord[rand.Intn(len(dirtyWord)+1)] + "\n\n\n" 114 | 115 | } else { 116 | 117 | msg = "检测到你的发言带有恶意:
" 118 | 119 | keyword := "" 120 | 121 | for i := 0; i < len(info2.Get("data").MustArray()); i++ { 122 | if info2.Get("data").GetIndex(i).Get("type").MustInt() == 12 { 123 | 124 | fmt.Println(info2.Get("data").GetIndex(i).Get("type").MustInt()) 125 | subType := info2.Get("data").GetIndex(i).Get("subType").MustInt() 126 | 127 | probability, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("probability").MustFloat64()*100), 64) 128 | 129 | for j := 0; j < len(info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("words").MustArray()); j++ { 130 | keyword = keyword + "【" + info2.Get("data").GetIndex(i).Get("hits").GetIndex(0).Get("words").GetIndex(j).MustString() + "】" 131 | } 132 | 133 | if subType == 5 { 134 | msg = msg + "低俗辱骂:" 135 | } else if subType == 2 { 136 | msg = msg + "文本色情:" 137 | } else if subType == 1 { 138 | msg = msg + "暴恐违禁:" 139 | } else if subType == 3 { 140 | msg = msg + "政治敏感:" 141 | } 142 | 143 | msg = msg + "(" + strconv.FormatFloat(probability, 'f', -1, 64) + "%)
" 144 | 145 | } 146 | 147 | } 148 | 149 | if keyword != "" { 150 | msg = msg + "关键词:
" + keyword 151 | } 152 | 153 | rand.Seed(time.Now().UnixNano()) 154 | msg = msg + "


" + dirtyWord[rand.Intn(len(dirtyWord)+1)] 155 | } 156 | 157 | } 158 | 159 | c.JSON(200, gin.H{ 160 | "status": "ok", 161 | "message": msg, 162 | "isDirty": isDirty, 163 | }) 164 | 165 | return 166 | } 167 | 168 | // AIImage 用于图像识别AI处理 169 | func AIImage(c *gin.Context) { 170 | 171 | base64URL := c.Request.FormValue("imgBase64") 172 | 173 | baiduAI := ai.NewBaiduAI() 174 | 175 | msg, err := baiduAI.ImageClassify(base64URL) 176 | 177 | if err != nil { 178 | c.JSON(200, gin.H{ 179 | "status": "ok", 180 | "message": err, 181 | }) 182 | } else { 183 | c.JSON(200, gin.H{ 184 | "status": "ok", 185 | "message": msg, 186 | }) 187 | } 188 | 189 | return 190 | } 191 | -------------------------------------------------------------------------------- /controllers/Github.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io/ioutil" 7 | "net/http" 8 | "sort" 9 | 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | type GithubData struct { 14 | Name string `json:"name"` 15 | Description string `json:"description"` 16 | StargazersCount int `json:"stargazers_count"` 17 | HtmlUrl string `json:"html_url"` 18 | Forks int `json:"forks"` 19 | Language string `json:"language"` 20 | } 21 | 22 | type ResData struct { 23 | Status string `json:"status"` 24 | Data []GithubData `json:"data"` 25 | } 26 | 27 | type GithubDatas []GithubData 28 | 29 | func (g GithubDatas) Len() int { return len(g) } 30 | 31 | func (g GithubDatas) Less(i, j int) bool { 32 | return g[i].StargazersCount > g[j].StargazersCount 33 | } 34 | 35 | func (g GithubDatas) Swap(i, j int) { g[i], g[j] = g[j], g[i] } 36 | 37 | //Github API 38 | func Github(c *gin.Context) { 39 | 40 | var url string = "https://api.github.com/users/alpacabi/repos" 41 | 42 | resp, err := http.Get(url) 43 | if err != nil { 44 | // handle error 45 | fmt.Println(err) 46 | return 47 | } 48 | 49 | defer resp.Body.Close() 50 | body, err := ioutil.ReadAll(resp.Body) 51 | if err != nil { 52 | // handle error 53 | return 54 | } 55 | 56 | var data GithubDatas 57 | 58 | if err := json.Unmarshal(body, &data); err != nil { 59 | fmt.Println(err) 60 | return 61 | } 62 | 63 | sort.Sort(data) 64 | 65 | data2 := data[:6] 66 | 67 | resData := ResData{ 68 | Status: "ok", 69 | Data: data2, 70 | } 71 | 72 | c.JSON(http.StatusOK, resData) 73 | return 74 | } 75 | -------------------------------------------------------------------------------- /controllers/Pong.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "alpaca_blog/lib/mysql" 5 | "alpaca_blog/lib/redis" 6 | "fmt" 7 | "net/http" 8 | "time" 9 | 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | //Pong 测试用api,本项目第一个api 14 | func Pong(c *gin.Context) { 15 | db := mysql.GetDB() 16 | 17 | // 测试mysql 18 | updateSQL := fmt.Sprintf("update #__ping set count=count+1 where id = %d", 1) 19 | _, err := db.Exec(mysql.Prefix(updateSQL)) 20 | if err != nil { 21 | c.JSON(http.StatusOK, gin.H{ 22 | "status": "error", 23 | "error": err.Error(), 24 | }) 25 | return 26 | } 27 | 28 | seleceSQL := fmt.Sprintf("select count from #__ping where id = %d", 1) 29 | var count int 30 | err2 := db.Get(&count, mysql.Prefix(seleceSQL)) 31 | if err2 != nil { 32 | c.JSON(http.StatusOK, gin.H{ 33 | "status": "error", 34 | "error": err2.Error(), 35 | }) 36 | return 37 | } 38 | 39 | // 测试redis 40 | redis.Set("ping", time.Now().Format("2006-01-02 15:04:05"), 2*time.Hour) 41 | value, err := redis.Get("ping") 42 | if err != nil { 43 | fmt.Println(err.Error()) 44 | } 45 | 46 | c.JSON(http.StatusOK, gin.H{ 47 | "status": "ok", 48 | "message": value, 49 | "count": count, 50 | }) 51 | return 52 | } 53 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module alpaca_blog 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/bitly/go-simplejson v0.5.0 7 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect 8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible 9 | github.com/gin-gonic/gin v1.5.0 10 | github.com/go-redis/redis v6.15.7+incompatible 11 | github.com/go-sql-driver/mysql v1.5.0 12 | github.com/jmoiron/sqlx v1.2.0 13 | github.com/json-iterator/go v1.1.9 14 | github.com/kr/pretty v0.2.0 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y= 2 | github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= 3 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= 4 | github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= 5 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 7 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= 9 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 10 | github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= 11 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 12 | github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc= 13 | github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do= 14 | github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= 15 | github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= 16 | github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= 17 | github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= 18 | github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U= 19 | github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= 20 | github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 21 | github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= 22 | github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 23 | github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= 24 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 25 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 26 | github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= 27 | github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= 28 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 29 | github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= 30 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 31 | github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= 32 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 33 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 34 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 35 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 36 | github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= 37 | github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= 38 | github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 39 | github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= 40 | github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= 41 | github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 42 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= 43 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 44 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg= 45 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 46 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 47 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 48 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 49 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 50 | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= 51 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 52 | github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= 53 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 54 | github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= 55 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 56 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= 57 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 58 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 59 | gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= 60 | gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc= 61 | gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= 62 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 63 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 64 | -------------------------------------------------------------------------------- /lib/ai/baiduAI.go: -------------------------------------------------------------------------------- 1 | package ai 2 | 3 | import ( 4 | "alpaca_blog/config" 5 | "alpaca_blog/lib/redis" 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | "net/url" 10 | "time" 11 | 12 | sjson "github.com/bitly/go-simplejson" 13 | ) 14 | 15 | // baiduAPI 百度AI接口 16 | type baiduAPI struct { 17 | AccessToken string //获取accesstoken地址 18 | TextCensor string //文本审核 19 | ImageClassify string //图像识别 20 | } 21 | 22 | // baiduAI 百度AI对象结构体 23 | type baiduAI struct { 24 | APIkey string 25 | SecretKey string 26 | BaiduAPI *baiduAPI 27 | rnet *http.Client 28 | } 29 | 30 | // NewBaiduAI 初始化百度AI 31 | func NewBaiduAI() *baiduAI { 32 | return &baiduAI{ 33 | APIkey: config.Current.BaiduAI.APIKey, 34 | SecretKey: config.Current.BaiduAI.SecretKey, 35 | BaiduAPI: &baiduAPI{ 36 | AccessToken: "https://aip.baidubce.com/oauth/2.0/token", 37 | TextCensor: "https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined", 38 | ImageClassify: "https://aip.baidubce.com/rest/2.0/image-classify/v2/advanced_general", 39 | }, 40 | rnet: &http.Client{}, 41 | } 42 | } 43 | 44 | // getAccessToken 获取AccessToken 45 | func (baiduAI *baiduAI) getAccessToken() (accessToken string, err error) { 46 | 47 | //从redis找有没有access_token,如果没有从网络请求access_token 48 | //access_token请求回来后,存在redis里面 49 | value, err := redis.Get("baidu_ai_access_token") 50 | if err != nil { 51 | fmt.Println(err.Error()) 52 | } 53 | if value != "" { 54 | accessToken = value 55 | return 56 | } 57 | 58 | //能走到这里表示redis没有access_token,从网络请求access_token 59 | accessTokenURL := fmt.Sprintf("%s?grant_type=client_credentials&client_id=%s&client_secret=%s", baiduAI.BaiduAPI.AccessToken, baiduAI.APIkey, baiduAI.SecretKey) 60 | 61 | req, err := http.NewRequest("GET", accessTokenURL, nil) 62 | if err != nil { 63 | return 64 | } 65 | 66 | req.Header.Set("Content-Type", "appliction/json;charset=utf-8") 67 | resp, err := baiduAI.rnet.Do(req) 68 | if err != nil { 69 | return 70 | } 71 | 72 | body, _ := ioutil.ReadAll(resp.Body) 73 | defer resp.Body.Close() 74 | 75 | info, err := sjson.NewJson(body) 76 | if err != nil { 77 | return 78 | } 79 | 80 | accessToken = info.Get("access_token").MustString("") 81 | 82 | //把access_token存进redis里面,有效期24个小时 83 | redis.Set("baidu_ai_access_token", accessToken, 24*time.Hour) 84 | 85 | return 86 | } 87 | 88 | // ImageClassify 图像识别 89 | func (baiduAI *baiduAI) ImageClassify(base64URL string) (msg *sjson.Json, err error) { 90 | 91 | accessToken, err := baiduAI.getAccessToken() 92 | if err != nil { 93 | fmt.Println(err) 94 | return 95 | } 96 | 97 | url2 := fmt.Sprintf("%s?access_token=%s", baiduAI.BaiduAPI.ImageClassify, accessToken) 98 | 99 | resp2, err := http.PostForm(url2, url.Values{"image": {base64URL}, "baike_num": {"1"}}) 100 | if err != nil { 101 | fmt.Println(err) 102 | return 103 | } 104 | defer resp2.Body.Close() 105 | body, _ := ioutil.ReadAll(resp2.Body) 106 | 107 | msg, err = sjson.NewJson(body) 108 | if err != nil { 109 | fmt.Println(err) 110 | return 111 | } 112 | return 113 | } 114 | 115 | // ImageClassify 文本审核 116 | func (baiduAI *baiduAI) TextCensor(text string) (msg *sjson.Json, err error) { 117 | 118 | accessToken, err := baiduAI.getAccessToken() 119 | if err != nil { 120 | fmt.Println(err) 121 | return 122 | } 123 | 124 | url2 := fmt.Sprintf("%s?access_token=%s", baiduAI.BaiduAPI.TextCensor, accessToken) 125 | 126 | resp2, err := http.PostForm(url2, url.Values{"text": {text}}) 127 | if err != nil { 128 | fmt.Println(err) 129 | return 130 | } 131 | defer resp2.Body.Close() 132 | boo2, _ := ioutil.ReadAll(resp2.Body) 133 | 134 | msg, err = sjson.NewJson(boo2) 135 | if err != nil { 136 | fmt.Println(err) 137 | return 138 | } 139 | return 140 | } 141 | -------------------------------------------------------------------------------- /lib/ai/tuling.go: -------------------------------------------------------------------------------- 1 | package ai 2 | 3 | import ( 4 | "alpaca_blog/config" 5 | "bytes" 6 | "encoding/json" 7 | "fmt" 8 | "io/ioutil" 9 | "net/http" 10 | 11 | sjson "github.com/bitly/go-simplejson" 12 | ) 13 | 14 | // ReqPara 图灵机器人请求体JSON格式 15 | type tulingReqData struct { 16 | ReqType int32 `json:"reqType"` 17 | Perception struct { 18 | InputText struct { 19 | Text string `json:"text"` 20 | } `json:"inputText"` 21 | } `json:"perception"` 22 | UserInfo struct { 23 | APIKey string `json:"apiKey"` 24 | UserID string `json:"userId"` 25 | } `json:"userInfo"` 26 | } 27 | 28 | // post 给Robot对象封装好post 29 | func (r *tulingRobot) post(url string, para []byte) ([]byte, error) { 30 | body := bytes.NewBuffer(para) 31 | req, err := http.NewRequest("POST", url, body) 32 | if err != nil { 33 | return nil, err 34 | } 35 | 36 | req.Header.Set("Content-Type", "appliction/json;charset=utf-8") 37 | resp, err := r.rnet.Do(req) 38 | if err != nil { 39 | return nil, err 40 | } 41 | defer resp.Body.Close() 42 | return ioutil.ReadAll(resp.Body) 43 | } 44 | 45 | // tulingRobot 图灵机器人对象结构体 46 | type tulingRobot struct { 47 | APIkey string 48 | APIURL string 49 | rnet *http.Client 50 | } 51 | 52 | // NewTulingRobot 初始化图灵机器人 53 | func NewTulingRobot(apikey string) *tulingRobot { 54 | return &tulingRobot{ 55 | APIkey: apikey, 56 | APIURL: config.Current.Tuling.APIURL, 57 | rnet: &http.Client{}, 58 | } 59 | } 60 | 61 | // GetReplyMsg 正式调用图灵机器人接口 62 | func (r *tulingRobot) GetTulingReplyMsg(text string, userid string) string { 63 | var para tulingReqData 64 | para.ReqType = 0 65 | para.Perception.InputText.Text = text 66 | para.UserInfo.APIKey = r.APIkey 67 | para.UserInfo.UserID = userid 68 | jsondata, _ := json.Marshal(para) 69 | 70 | body, err := r.post(r.APIURL, jsondata) 71 | if err != nil { 72 | fmt.Println("get tuling reply err:", err) 73 | return "" 74 | } 75 | 76 | info, err := sjson.NewJson(body) 77 | if err != nil { 78 | fmt.Println("get tuling reply parse para err:", err) 79 | return "" 80 | } 81 | 82 | msg := info.Get("results").GetIndex(0).Get("values").Get("text").MustString("") 83 | return msg 84 | } 85 | -------------------------------------------------------------------------------- /lib/ai/xiaosi.go: -------------------------------------------------------------------------------- 1 | package ai 2 | 3 | import ( 4 | "alpaca_blog/config" 5 | "bytes" 6 | "encoding/json" 7 | "fmt" 8 | "io/ioutil" 9 | "net/http" 10 | 11 | sjson "github.com/bitly/go-simplejson" 12 | ) 13 | 14 | // ReqPara 小思机器人请求体JSON格式 15 | type xiaosiReqData struct { 16 | Spoken string `json:"spoken"` 17 | AppID string `json:"appid"` 18 | UserID string `json:"userid"` 19 | } 20 | 21 | // post 给Robot对象封装好post 22 | func (r *xiaosiRobot) post(url string, para []byte) ([]byte, error) { 23 | body := bytes.NewBuffer(para) 24 | req, err := http.NewRequest("POST", url, body) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | req.Header.Set("Content-Type", "appliction/json;charset=utf-8") 30 | resp, err := r.rnet.Do(req) 31 | if err != nil { 32 | return nil, err 33 | } 34 | defer resp.Body.Close() 35 | return ioutil.ReadAll(resp.Body) 36 | } 37 | 38 | // Robot 小思机器人对象结构体 39 | type xiaosiRobot struct { 40 | AppID string 41 | APIURL string 42 | rnet *http.Client 43 | } 44 | 45 | // NewXiaosiRobot 初始化小思机器人 46 | func NewXiaosiRobot(appid string) *xiaosiRobot { 47 | return &xiaosiRobot{ 48 | AppID: appid, 49 | APIURL: config.Current.Xiaosi.APIURL, 50 | rnet: &http.Client{}, 51 | } 52 | } 53 | 54 | // GetReplyMsg 正式调用小思机器人接口 55 | func (r *xiaosiRobot) GetXiaosiReplyMsg(text string, userid string) string { 56 | var para xiaosiReqData 57 | para.Spoken = text 58 | para.AppID = r.AppID 59 | para.UserID = userid 60 | jsondata, _ := json.Marshal(para) 61 | 62 | body, err := r.post(r.APIURL, jsondata) 63 | if err != nil { 64 | fmt.Println("get xiaosi reply err:", err) 65 | return "" 66 | } 67 | 68 | info, err := sjson.NewJson(body) 69 | if err != nil { 70 | fmt.Println("get xiaosi reply parse para err:", err) 71 | return "" 72 | } 73 | 74 | msg := info.Get("data").Get("info").Get("text").MustString("") 75 | return msg 76 | } 77 | -------------------------------------------------------------------------------- /lib/mysql/mysql.go: -------------------------------------------------------------------------------- 1 | package mysql 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "strings" 7 | "sync" 8 | "time" 9 | 10 | _ "github.com/go-sql-driver/mysql" //import mysql impolementation for sql 11 | "github.com/jmoiron/sqlx" 12 | "github.com/jmoiron/sqlx/reflectx" 13 | ) 14 | 15 | //Config Mysql的配置 16 | type Config struct { 17 | Host string `json:"host"` 18 | Port int `json:"port"` 19 | User string `json:"user"` 20 | Password string `json:"password"` 21 | Db string `json:"db"` 22 | Dbprefix string `json:"dbprefix"` 23 | ConnLifeTime int `json:"connlifetime"` //以秒为单位 24 | MaxIdleConn int `json:"maxidleconn"` 25 | MaxOpenConn int `json:"maxopenconn"` 26 | } 27 | 28 | //IDB 数据库接口 29 | type IDB interface { 30 | GetDB() *sqlx.DB 31 | Prefix(str string) string 32 | } 33 | 34 | type sqlServer struct { 35 | Config Config 36 | DB *sqlx.DB 37 | } 38 | 39 | //init 初始化sql 40 | func (sql *sqlServer) init(config Config) error { 41 | var dbonce sync.Once 42 | var db *sqlx.DB 43 | var err error 44 | dbonce.Do(func() { 45 | db, err = sqlx.Open( 46 | "mysql", 47 | fmt.Sprintf( 48 | "%s:%s@tcp(%s:%d)/%s", 49 | config.User, 50 | config.Password, 51 | config.Host, 52 | config.Port, 53 | config.Db, 54 | ), 55 | ) 56 | if err != nil { 57 | log.Printf("get mysql database error: %s", err) 58 | } else { 59 | db.SetConnMaxLifetime(time.Duration(config.ConnLifeTime) * time.Second) 60 | db.SetMaxIdleConns(config.MaxIdleConn) 61 | db.SetMaxOpenConns(config.MaxOpenConn) 62 | db.Mapper = reflectx.NewMapperFunc("json", strings.ToLower) 63 | } 64 | }) 65 | 66 | sql.DB = db 67 | return err 68 | } 69 | 70 | //GetDB GetDB 71 | func (sql *sqlServer) GetDB() *sqlx.DB { 72 | return sql.DB 73 | } 74 | 75 | //Prefix change the relative sql to real sql with prefix 76 | func (sql sqlServer) Prefix(str string) string { 77 | return strings.Replace(str, "#__", sql.Config.Dbprefix, -1) 78 | } 79 | 80 | var s IDB 81 | 82 | //InitSQL 初始化数据库 83 | func InitMYSQL(config Config) { 84 | ss := &sqlServer{ 85 | Config: config, 86 | } 87 | err := ss.init(config) 88 | if err != nil { 89 | fmt.Println(err) 90 | } 91 | s = ss 92 | } 93 | 94 | //GetDB 获取数据库 95 | func GetDB() *sqlx.DB { 96 | return s.GetDB() 97 | } 98 | 99 | //改sql表前缀 100 | func Prefix(sql string) string { 101 | return s.Prefix(sql) 102 | } 103 | -------------------------------------------------------------------------------- /lib/redis/redis.go: -------------------------------------------------------------------------------- 1 | package redis 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | "time" 7 | 8 | redis "github.com/go-redis/redis" 9 | ) 10 | 11 | //Config redis的配置文件 12 | type Config struct { 13 | Host string `json:"host"` 14 | Port int `json:"port"` 15 | Auth string `json:"auth"` 16 | Db int `json:"db"` 17 | PoolSize int `json:"poolSize"` 18 | } 19 | 20 | var config Config 21 | 22 | //InitRedis 设置Redis配置文件 23 | func InitRedis(conf Config) { 24 | config = conf 25 | } 26 | 27 | var redisOnce sync.Once 28 | var client *redis.Client 29 | 30 | //ErrKeyNotExists not exists 31 | var ErrKeyNotExists = redis.Nil 32 | 33 | //GetRedisClient get the client of redis 34 | func getRedisClient() *redis.Client { 35 | redisOnce.Do(func() { 36 | client = redis.NewClient(&redis.Options{ 37 | Addr: fmt.Sprintf("%s:%d", config.Host, config.Port), 38 | Password: config.Auth, 39 | DB: config.Db, 40 | MaxRetries: 2, 41 | PoolSize: config.PoolSize, 42 | }) 43 | }) 44 | return client 45 | } 46 | 47 | //Get get redis value 48 | func Get(key string) (string, error) { 49 | return getRedisClient().Get(key).Result() 50 | } 51 | 52 | //Set set redis key value 53 | func Set(key string, val string, expiration time.Duration) error { 54 | return getRedisClient().Set(key, val, expiration).Err() 55 | } 56 | 57 | //Del delete the key 58 | func Del(key string) error { 59 | return getRedisClient().Del(key).Err() 60 | } 61 | 62 | //TTL change the Ttl 63 | func TTL(key string) (time.Duration, error) { 64 | r := getRedisClient().TTL(key) 65 | return r.Val(), r.Err() 66 | } 67 | 68 | //Client return the raw redis client 69 | func Client() *redis.Client { 70 | return getRedisClient() 71 | } 72 | 73 | func RPush(key string, value string) error { 74 | 75 | return getRedisClient().RPush(key, value).Err() 76 | } 77 | 78 | func LPush(key string, value string) error { 79 | return getRedisClient().LPush(key, value).Err() 80 | } 81 | 82 | func RPop(key string) error { 83 | return getRedisClient().RPop(key).Err() 84 | } 85 | 86 | func LPop(key string) error { 87 | return getRedisClient().LPop(key).Err() 88 | } 89 | 90 | func LLen(key string) (int64, error) { 91 | r := getRedisClient().LLen(key) 92 | return r.Val(), r.Err() 93 | } 94 | 95 | func LRem(key string, count int64, value string) error { 96 | return getRedisClient().LRem(key, count, value).Err() 97 | } 98 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "alpaca_blog/config" 5 | "alpaca_blog/lib/mysql" 6 | "alpaca_blog/lib/redis" 7 | "alpaca_blog/route" 8 | "net/http" 9 | 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | func main() { 14 | //全局设置环境,此为开发环境,线上环境为gin.ReleaseMode 15 | if config.Current.Debug { 16 | gin.SetMode(gin.DebugMode) 17 | } else { 18 | gin.SetMode(gin.ReleaseMode) 19 | } 20 | 21 | //读取配置文件 22 | config.LoadConfig() 23 | //初始化Mysql 24 | mysql.InitMYSQL(config.Current.Mysql) 25 | //初始化Redis 26 | redis.InitRedis(config.Current.Redis) 27 | //初始化api路由 28 | router := route.InitRoutes() 29 | //开始监听 30 | http.ListenAndServe(config.Current.Listen, router) 31 | } 32 | -------------------------------------------------------------------------------- /middleware/jwt/jwt.go: -------------------------------------------------------------------------------- 1 | package jwt 2 | 3 | import ( 4 | "errors" 5 | "log" 6 | "net/http" 7 | "time" 8 | 9 | "github.com/dgrijalva/jwt-go" 10 | "github.com/gin-gonic/gin" 11 | ) 12 | 13 | // JWTAuth 中间件,检查token 14 | func JWTAuth() gin.HandlerFunc { 15 | return func(c *gin.Context) { 16 | token := c.Request.Header.Get("token") 17 | if token == "" { 18 | c.JSON(http.StatusOK, gin.H{ 19 | "status": "error", 20 | "msg": "请求未携带token,无权限访问,请刷新页面重新登录!!", 21 | }) 22 | c.Abort() 23 | return 24 | } 25 | 26 | log.Print("get token: ", token) 27 | 28 | j := NewJWT() 29 | // parseToken 解析token包含的信息 30 | claims, err := j.ParseToken(token) 31 | if err != nil { 32 | if err == TokenExpired { 33 | c.JSON(http.StatusOK, gin.H{ 34 | "status": "error", 35 | "msg": "token授权已过期,,请刷新页面重新登录!!", 36 | }) 37 | c.Abort() 38 | return 39 | } 40 | c.JSON(http.StatusOK, gin.H{ 41 | "status": "error", 42 | "msg": err.Error(), 43 | }) 44 | c.Abort() 45 | return 46 | } 47 | // 继续交由下一个路由处理,并将解析出的信息传递下去 48 | c.Set("claims", claims) 49 | } 50 | } 51 | 52 | // JWT 签名结构 53 | type JWT struct { 54 | SigningKey []byte 55 | } 56 | 57 | // 一些常量 58 | var ( 59 | TokenExpired error = errors.New("Token is expired") 60 | TokenNotValidYet error = errors.New("Token not active yet") 61 | TokenMalformed error = errors.New("That's not even a token") 62 | TokenInvalid error = errors.New("Couldn't handle this token:") 63 | SignKey string = "newtrekWang" 64 | ) 65 | 66 | // 载荷,可以加一些自己需要的信息 67 | type CustomClaims struct { 68 | ID string `json:"userId"` 69 | Name string `json:"name"` 70 | Phone string `json:"phone"` 71 | jwt.StandardClaims 72 | } 73 | 74 | // 新建一个jwt实例 75 | func NewJWT() *JWT { 76 | return &JWT{ 77 | []byte(GetSignKey()), 78 | } 79 | } 80 | 81 | // 获取signKey 82 | func GetSignKey() string { 83 | return SignKey 84 | } 85 | 86 | // 这是SignKey 87 | func SetSignKey(key string) string { 88 | SignKey = key 89 | return SignKey 90 | } 91 | 92 | // CreateToken 生成一个token 93 | func (j *JWT) CreateToken(claims CustomClaims) (string, error) { 94 | token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) 95 | return token.SignedString(j.SigningKey) 96 | } 97 | 98 | // 解析Tokne 99 | func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) { 100 | token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { 101 | return j.SigningKey, nil 102 | }) 103 | if err != nil { 104 | if ve, ok := err.(*jwt.ValidationError); ok { 105 | if ve.Errors&jwt.ValidationErrorMalformed != 0 { 106 | return nil, TokenMalformed 107 | } else if ve.Errors&jwt.ValidationErrorExpired != 0 { 108 | // Token is expired 109 | return nil, TokenExpired 110 | } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 { 111 | return nil, TokenNotValidYet 112 | } else { 113 | return nil, TokenInvalid 114 | } 115 | } 116 | } 117 | if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { 118 | return claims, nil 119 | } 120 | return nil, TokenInvalid 121 | } 122 | 123 | // 更新token 124 | func (j *JWT) RefreshToken(tokenString string) (string, error) { 125 | jwt.TimeFunc = func() time.Time { 126 | return time.Unix(0, 0) 127 | } 128 | token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) { 129 | return j.SigningKey, nil 130 | }) 131 | if err != nil { 132 | return "", err 133 | } 134 | if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid { 135 | jwt.TimeFunc = time.Now 136 | claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix() 137 | return j.CreateToken(*claims) 138 | } 139 | return "", TokenInvalid 140 | } 141 | -------------------------------------------------------------------------------- /models/model.json: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/models/model.json -------------------------------------------------------------------------------- /route/routes.go: -------------------------------------------------------------------------------- 1 | package route 2 | 3 | import ( 4 | "alpaca_blog/controllers" 5 | 6 | "github.com/gin-gonic/gin" 7 | ) 8 | 9 | //InitRoutes 路由初始化 10 | func InitRoutes() (router *gin.Engine) { 11 | router = gin.Default() //获得路由实例 12 | router.Use(Middleware) //中间件 13 | 14 | AI := router.Group("/ai") 15 | { 16 | AI.POST("/text", controllers.AIText) 17 | AI.POST("/image", controllers.AIImage) 18 | } 19 | 20 | router.GET("/github", controllers.Github) //测试!!! 21 | 22 | router.GET("/ping", controllers.Pong) //测试!!! 23 | return 24 | } 25 | 26 | //Middleware Middleware 27 | func Middleware(c *gin.Context) { 28 | //fmt.Println("this is a middleware!") 29 | } 30 | -------------------------------------------------------------------------------- /views/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ], 5 | "plugins": [ 6 | [ 7 | "component", 8 | { 9 | "libraryName": "element-ui", 10 | "styleLibraryName": "theme-chalk" 11 | } 12 | ] 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /views/dist/css/app.a225fa1f.css: -------------------------------------------------------------------------------- 1 | .el-menu-vertical-demo[data-v-2db4ef16]:not(.el-menu--collapse){width:300px}.left-nav[data-v-2db4ef16]{position:fixed;background-color:#545c64;height:100%;width:300px;color:#fff;z-index:6}.left-nav .el-menu[data-v-2db4ef16]{border-right:none}.left-nav .avator[data-v-2db4ef16]{text-align:center}.left-nav .avator img[data-v-2db4ef16]{margin-top:1vh;width:20vh;border-radius:100%;cursor:pointer}.left-nav .avator .name[data-v-2db4ef16]{font-size:4vh}.left-nav .avator .info[data-v-2db4ef16]{text-align:left;margin-left:80px;margin-top:3vh}.left-nav .avator .info .item[data-v-2db4ef16]{margin-bottom:1vh}.left-nav .avator .info .item .text[data-v-2db4ef16]{margin-left:1.5vh;text-decoration:none;color:#fff;cursor:pointer}.left-nav .avator .info .item .text[data-v-2db4ef16]:hover{text-decoration:underline;color:#fff}.left-nav .avator .info .item img[data-v-2db4ef16]{width:2vh;margin-top:0}.left-nav .beian[data-v-2db4ef16]{position:absolute;bottom:3vh;text-align:center;width:300px}.left-nav .beian a[data-v-2db4ef16]{text-decoration:none;color:#fff;cursor:pointer}.left-nav .beian a[data-v-2db4ef16]:hover{text-decoration:underline;color:#fff}.nav[data-v-5f6cfc3c]{position:fixed;left:20px;top:45%;z-index:2;color:grey}.nav a[data-v-5f6cfc3c]{-webkit-text-decoration-line:none;text-decoration-line:none}.nav .nav-item[data-v-5f6cfc3c]{display:block;font-size:11px;margin-top:5px;height:12px;width:12px;border-radius:100%;border:1px solid #fff;opacity:.5}.nav .router-link-active .nav-item[data-v-5f6cfc3c]{background-color:#fff!important}.page[data-v-5f6cfc3c]{position:absolute;top:0;background-color:#000}@media screen and (max-width:767px){.nav[data-v-5f6cfc3c]{display:none}}@media screen and (min-width:769px){.ai[data-v-75dbc408]{position:fixed;z-index:3;width:450px;top:0;right:0;height:100vh;background:#fff;-webkit-box-shadow:-10px 0 10px rgba(0,0,0,.05);box-shadow:-10px 0 10px rgba(0,0,0,.05);opacity:1}.ai .title[data-v-75dbc408]{text-align:left;background:#f90;color:#fff;height:60px;font-size:30px;padding-top:15px;padding-left:20px;position:absolute;width:100%;font-weight:700;cursor:pointer}.ai .close[data-v-75dbc408]{width:35px;height:35px;position:absolute;right:12px;top:12px;cursor:pointer}.ai .content[data-v-75dbc408]{width:100%;overflow:auto;top:60px;position:absolute;z-index:10;bottom:55px;background:#1b1b1b;padding-bottom:80px}.ai .content .left-bubble[data-v-75dbc408]{float:left;color:#000;background-color:#f90;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset;box-shadow:0 1px 4px rgba(0,0,0,.3),inset 0 0 40px rgba(0,0,0,.1)}.ai .content .left-bubble[data-v-75dbc408],.ai .content .right-bubble[data-v-75dbc408]{width:300px;text-align:left;padding:10px;margin:10px;word-break:break-all;border-radius:8px;-o-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset}.ai .content .right-bubble[data-v-75dbc408]{float:right;color:#fff;background-color:grey;-webkit-box-shadow:-10px 0 10px rgba(0,0,0,.05);box-shadow:-10px 0 10px rgba(0,0,0,.05);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset;box-shadow:0 1px 4px rgba(0,0,0,.3),inset 0 0 40px rgba(0,0,0,.1)}.ai .content[data-v-75dbc408]::-webkit-scrollbar{margin-right:20px;width:4px;height:4px}.ai .content[data-v-75dbc408]::-webkit-scrollbar-thumb{border-radius:2px;--webkit-box-shadow:inset 0 0 5px grey;background:#efefef}.ai .content[data-v-75dbc408]::-webkit-scrollbar-track{--webkit-box-shadow:inset 0 0 5px transparent;border-radius:0;background:transparent}.ai .footer[data-v-75dbc408]{position:absolute;bottom:0;width:100%;height:55px;background:#f90;text-align:left}.ai .footer input[data-v-75dbc408]{display:inline-block;width:270px;height:32px;border-radius:6px;margin-top:11px;margin-left:40px;outline:none;border:none;font-size:12px;padding-right:10px;padding-left:10px}.ai .footer .sendtext[data-v-75dbc408]{display:inline-block;vertical-align:bottom;margin-left:7px;height:30px;width:34px;cursor:pointer}.ai .footer .sendtext[data-v-75dbc408]:active{-webkit-transform:scale(.9);transform:scale(.9)}.ai .footer .file-upload[data-v-75dbc408]{position:relative;display:inline-block;vertical-align:bottom}.ai .footer .file-upload .sendimg[data-v-75dbc408]{display:inline-block;vertical-align:bottom;margin-left:7px;height:34px;width:34px;cursor:pointer}.ai .footer .file-upload .sendimg[data-v-75dbc408]:active{-webkit-transform:scale(.9);transform:scale(.9)}.ai .footer .file-upload .uploadimg[data-v-75dbc408]{background-color:transparent;position:absolute;width:40px;top:-6px;padding-left:77px;right:-94px}.ai-button[data-v-75dbc408]{position:fixed;z-index:3;width:60px;background:#f90;top:0;right:0;height:60px;cursor:pointer}.ai-button .title[data-v-75dbc408]{text-align:center;color:#fff;height:60px;font-size:30px;position:absolute;top:10px;width:100%;font-weight:700}}@media screen and (max-width:767px){.ai[data-v-75dbc408]{position:fixed;z-index:3;width:100%;top:0;right:0;height:100%;background:#fff;-webkit-box-shadow:-10px 0 10px rgba(0,0,0,.05);box-shadow:-10px 0 10px rgba(0,0,0,.05);opacity:1}.ai .title[data-v-75dbc408]{text-align:left;background:#f90;color:#fff;height:60px;font-size:30px;padding-top:15px;padding-left:20px;position:absolute;width:100%;font-weight:700;cursor:pointer}.ai .close[data-v-75dbc408]{width:35px;height:35px;position:absolute;right:12px;top:12px;cursor:pointer}.ai .content[data-v-75dbc408]{width:100%;overflow:auto;top:60px;position:absolute;z-index:10;bottom:55px;background:#1b1b1b;padding-bottom:80px}.ai .content .left-bubble[data-v-75dbc408]{float:left;color:#000;background-color:#f90;-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset;box-shadow:0 1px 4px rgba(0,0,0,.3),inset 0 0 40px rgba(0,0,0,.1)}.ai .content .left-bubble[data-v-75dbc408],.ai .content .right-bubble[data-v-75dbc408]{width:80%;text-align:left;padding:10px;margin:10px;word-break:break-all;border-radius:8px;-o-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset}.ai .content .right-bubble[data-v-75dbc408]{float:right;color:#fff;background-color:grey;-webkit-box-shadow:-10px 0 10px rgba(0,0,0,.05);box-shadow:-10px 0 10px rgba(0,0,0,.05);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset;box-shadow:0 1px 4px rgba(0,0,0,.3),inset 0 0 40px rgba(0,0,0,.1)}.ai .content[data-v-75dbc408]::-webkit-scrollbar{margin-right:20px;width:4px;height:4px}.ai .content[data-v-75dbc408]::-webkit-scrollbar-thumb{border-radius:2px;--webkit-box-shadow:inset 0 0 5px grey;background:#efefef}.ai .content[data-v-75dbc408]::-webkit-scrollbar-track{--webkit-box-shadow:inset 0 0 5px transparent;border-radius:0;background:transparent}.ai .footer[data-v-75dbc408]{position:absolute;bottom:0;width:100%;height:55px;background:#f90;text-align:left}.ai .footer input[data-v-75dbc408]{display:inline-block;width:62%;height:32px;border-radius:6px;margin-top:11px;margin-left:4%;outline:none;border:none;font-size:12px;padding-right:10px;padding-left:10px}.ai .footer .sendtext[data-v-75dbc408]{display:inline-block;vertical-align:bottom;margin-left:7px;height:30px;width:34px;cursor:pointer}.ai .footer .sendtext[data-v-75dbc408]:active{-webkit-transform:scale(.9);transform:scale(.9)}.ai .footer .file-upload[data-v-75dbc408]{position:relative;display:inline-block;vertical-align:bottom}.ai .footer .file-upload .sendimg[data-v-75dbc408]{display:inline-block;vertical-align:bottom;margin-left:7px;height:34px;width:34px;cursor:pointer}.ai .footer .file-upload .sendimg[data-v-75dbc408]:active{-webkit-transform:scale(.9);transform:scale(.9)}.ai .footer .file-upload .uploadimg[data-v-75dbc408]{background-color:transparent;position:absolute;width:40px;top:-6px;padding-left:77px;right:-94px}.ai-button[data-v-75dbc408]{position:fixed;z-index:3;width:60px;background:#f90;top:0;right:0;height:60px;cursor:pointer}.ai-button .title[data-v-75dbc408]{text-align:center;color:#fff;height:60px;font-size:30px;position:absolute;top:10px;width:100%;font-weight:700}}.el-dialog[data-v-3495f196]{width:500px!important}#header[data-v-53a2d0ed]{display:grid;width:100%;grid-template-rows:60px 40px;z-index:2;position:fixed}#header #headerWrapper[data-v-53a2d0ed]{width:100%;background-color:#1b1b1b}#header #headerWrapper #headerContainer[data-v-53a2d0ed]{height:100%;display:grid;grid-template-columns:200px 1fr 250px 220px;grid-gap:10px;justify-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;margin:auto;min-width:991px;max-width:1323px;width:96%}#header #headerWrapper #headerContainer .logo[data-v-53a2d0ed]{display:inline-block;font-size:30px;font-family:Arial,Helvetica,sans-serif;font-weight:700;margin:0;padding:0;cursor:pointer}#header #headerWrapper #headerContainer .logo .text1[data-v-53a2d0ed]{color:#fff;padding:5px 5px}#header #headerWrapper #headerContainer .logo .text2[data-v-53a2d0ed]{color:#000;background-color:#f90;padding:5px 10px;border-radius:7px}body{margin:0;color:#fff;background:#000}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center}.right-content{margin-left:300px;background:#24292e;height:100vh} -------------------------------------------------------------------------------- /views/dist/css/chunk-2e1de229.60951e7e.css: -------------------------------------------------------------------------------- 1 | @media screen and (min-width:769px){.section[data-v-377a5208]{height:calc(100vh - 80px);width:98vw;background-color:#000!important}.section .profile-title[data-v-377a5208]{color:#fff;font-weight:700;font-size:32px;margin-top:80px}.section .github-status[data-v-377a5208]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.section .github-status .item[data-v-377a5208]{border:1px dashed #f90;margin:20px}.section .github-status .item img[data-v-377a5208]{width:400px;height:160px}.section .profile-title2[data-v-377a5208]{color:#fff;font-weight:700;font-size:32px;margin-top:15px;margin-bottom:25px}.section .github-repo[data-v-377a5208]{display:grid;grid-template-columns:300px 300px 300px;grid-template-rows:100px 100px 100px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;grid-gap:20px 30px}.section .github-repo .item[data-v-377a5208]{position:relative;border:1px dashed #f90}.section .github-repo .item .title[data-v-377a5208]{position:absolute;top:8px;left:10px;color:#f90;font-weight:700;font-size:18px}.section .github-repo .item .info[data-v-377a5208]{position:absolute;text-align:left;top:35px;left:10px;width:280px;color:#f90;font-size:10px}.section .github-repo .item .data[data-v-377a5208]{position:absolute;text-align:left;bottom:5px;left:10px;color:#f90;font-size:14px}.section .github-repo .item .data .star[data-v-377a5208]{display:inline-block;width:60px}.section .github-repo .item .data .star .icon[data-v-377a5208]{margin-right:6px}.section .github-repo .item .data .fork[data-v-377a5208]{display:inline-block;width:60px}.section .github-repo .item .data .fork .icon[data-v-377a5208]{margin-right:6px}.section .github-repo .item .data .language[data-v-377a5208]{display:inline-block}.section .github-repo .item .data .language .icon[data-v-377a5208]{margin-right:6px}.section .github-repo .item[data-v-377a5208]:hover{-webkit-transition:all .5s;-webkit-transition:.5s;transition:.5s;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transfrom:scale(1.1);transform:scale(1.1)}.section .next[data-v-377a5208]{display:none}}@media screen and (max-width:767px){.section[data-v-377a5208]{height:100vh;width:100vw;background-color:#000!important}.section .profile-title[data-v-377a5208]{color:#fff;font-weight:700;font-size:28px;margin-top:80px}.section .github-status[data-v-377a5208]{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.section .github-status .item[data-v-377a5208]{border:1px dashed #f90;margin:10px}.section .github-status .item img[data-v-377a5208]{max-width:90%;height:auto}.section .profile-title2[data-v-377a5208]{color:#fff;font-weight:700;font-size:28px;margin-top:10px}.section .github-repo[data-v-377a5208]{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.section .github-repo .item[data-v-377a5208]{border:1px dashed #f90;margin:10px;width:100%;height:100px;position:relative}.section .github-repo .item .title[data-v-377a5208]{position:absolute;top:8px;left:4%;color:#f90;font-weight:700;font-size:18px}.section .github-repo .item .info[data-v-377a5208]{position:absolute;text-align:left;top:35px;left:4%;width:92%;color:#f90;font-size:10px}.section .github-repo .item .data[data-v-377a5208]{position:absolute;text-align:left;bottom:5px;left:10px;color:#f90;font-size:14px}.section .github-repo .item .data .star[data-v-377a5208]{display:inline-block;width:60px}.section .github-repo .item .data .star .icon[data-v-377a5208]{margin-right:6px}.section .github-repo .item .data .fork[data-v-377a5208]{display:inline-block;width:60px}.section .github-repo .item .data .fork .icon[data-v-377a5208]{margin-right:6px}.section .github-repo .item .data .language[data-v-377a5208]{display:inline-block}.section .github-repo .item .data .language .icon[data-v-377a5208]{margin-right:6px}.next[data-v-377a5208]{margin-top:40px;margin-bottom:40px;color:#f90;font-size:24px;text-decoration:underline}} -------------------------------------------------------------------------------- /views/dist/css/chunk-62af08d6.1d96d0bd.css: -------------------------------------------------------------------------------- 1 | .section[data-v-b71281fe]{height:calc(100vh - 80px);width:98vw;background-color:#000!important;overflow:hidden;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.section .contact-title[data-v-b71281fe]{color:#fff;font-weight:700;font-size:60px;padding-top:8vh;margin-bottom:4vh}@media screen and (min-width:769px){.section .welcome[data-v-b71281fe]{color:#fff;font-size:50px;margin-bottom:80px}.section .next[data-v-b71281fe]{display:none}}@media screen and (max-width:767px){.section .welcome[data-v-b71281fe]{color:#fff;font-size:25px;margin-bottom:80px}.section .next[data-v-b71281fe]{position:absolute;color:#f90;bottom:20px;font-size:24px;text-decoration:underline}}.section .cards .card[data-v-b71281fe]{width:330px;height:55px;margin:20px;cursor:pointer;background-color:#f90;border-radius:6px;text-align:left;box-shadow:0 1px 4px rgba(0,0,0,.3),inset 0 0 40px rgba(0,0,0,.1);-webkit-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset;-o-box-shadow:0 1px 4px rgba(0,0,0,.3),0 0 40px rgba(0,0,0,.1) inset}.section .cards .card img[data-v-b71281fe]{width:40px;margin-top:7px;margin-left:16px}.section .cards .card .text[data-v-b71281fe]{color:#000;display:inline-block;vertical-align:top;margin-top:16px;margin-left:10px;font-size:20px}.section .cards .card .text a[data-v-b71281fe]{display:inline-block;margin-top:0;text-decoration:none;color:#000}.section .cards .card[data-v-b71281fe]:hover{-webkit-transition:all .5s;-webkit-transition:.5s;transition:.5s;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transfrom:scale(1.1);transform:scale(1.1)}.section .mp[data-v-b71281fe]{margin-top:60px}.section .mp img[data-v-b71281fe]{width:150px;height:150px}.section .mp .text[data-v-b71281fe]{color:#fff;margin-top:10px;font-size:20px} -------------------------------------------------------------------------------- /views/dist/css/chunk-7ce5de4d.d6814b87.css: -------------------------------------------------------------------------------- 1 | .info[data-v-3ce94835]{position:absolute;display:-webkit-box;display:-ms-flexbox;display:flex;top:0;height:calc(100vh - 80px);width:98vw;color:#fff;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center}@media screen and (min-width:769px){.info .name[data-v-3ce94835]{font-size:80px}.info .intro[data-v-3ce94835]{font-size:40px;margin-bottom:200px}.info .more[data-v-3ce94835]{margin-bottom:15px}.info .terminal[data-v-3ce94835]{border:1px solid #f90;border-radius:8px;padding:13px;font-size:20px;color:#f90}.info .terminal[data-v-3ce94835]:hover{color:#fff;background:#f90}.info .next[data-v-3ce94835]{display:none}.info .icp[data-v-3ce94835]{position:absolute;bottom:20px}}@media screen and (max-width:767px){.info .name[data-v-3ce94835]{font-size:60px;margin-bottom:20px}.info .intro[data-v-3ce94835]{font-size:22px;margin-bottom:180px}.info .more[data-v-3ce94835]{margin-bottom:15px}.info .terminal[data-v-3ce94835]{border:1px solid #f90;border-radius:8px;padding:13px;font-size:20px;color:#f90}.info .terminal[data-v-3ce94835]:hover{color:#fff;background:#f90}.info .next[data-v-3ce94835]{position:absolute;color:#f90;bottom:20px;font-size:24px;text-decoration:underline}.info .icp[data-v-3ce94835]{display:none}} -------------------------------------------------------------------------------- /views/dist/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/dist/favicon.ico -------------------------------------------------------------------------------- /views/dist/finger.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/dist/finger.cur -------------------------------------------------------------------------------- /views/dist/fonts/element-icons.535877f5.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/dist/fonts/element-icons.535877f5.woff -------------------------------------------------------------------------------- /views/dist/fonts/element-icons.732389de.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/dist/fonts/element-icons.732389de.ttf -------------------------------------------------------------------------------- /views/dist/img/avatar.5c94d5d3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/dist/img/avatar.5c94d5d3.jpeg -------------------------------------------------------------------------------- /views/dist/index.html: -------------------------------------------------------------------------------- 1 | Free Technology Blog & Alpaca Bi Website
-------------------------------------------------------------------------------- /views/dist/js/app.e0b6bc08.js: -------------------------------------------------------------------------------- 1 | (function(e){function t(t){for(var n,o,c=t[0],s=t[1],l=t[2],u=0,p=[];u',position:"bottom-left"})}}]),t}(D["b"]);Object(R["a"])([I["c"]],B.prototype,"images",void 0),Object(R["a"])([I["b"]],B.prototype,"changeAiShow",void 0),Object(R["a"])([I["b"]],B.prototype,"openLoginDialogShow",void 0),B=Object(R["a"])([D["a"]],B);var E=B,$=E,z=(a("5d04"),a("2877")),N=Object(z["a"])($,P,L,!1,null,"2db4ef16",null),H=N.exports,q=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{on:{mousewheel:e.mouseWheel}},[a("div",{staticClass:"nav"},[e._l(this.$router.options.routes,(function(t,n){return[a("router-link",{key:n,attrs:{to:{name:t.name},exact:""}},[a("i",{staticClass:"nav-item",on:{click:e.clickRouteChange}})])]}))],2),a("div",{staticClass:"page"},[a("transition",{attrs:{mode:"out-in",duration:{enter:e.animateOptions.enterTime,leave:e.animateOptions.leaveTime},"leave-active-class":"animated "+e.animateOptions.leave,"enter-active-class":"animated "+e.animateOptions.enter}},[a("router-view")],1)],1)])},F=[],U=(a("77ed"),function(e){function t(){var e;return Object(S["a"])(this,t),e=Object(_["a"])(this,Object(C["a"])(t).apply(this,arguments)),e.lastScroll=0,e}return Object(T["a"])(t,e),Object(A["a"])(t,[{key:"mouseWheel",value:function(e){var t=this,a=e.timeStamp-this.lastScroll;if(a>1e3)if(this.lastScroll=e.timeStamp,e.deltaY>0){var n=this.$route.name;this.next(n).then((function(e){t.$router.push({name:e})}))}else{var o=this.$route.name;this.last(o).then((function(e){t.$router.push({name:e})}))}}}]),t}(D["b"]));Object(R["a"])([I["c"]],U.prototype,"animateOptions",void 0),Object(R["a"])([I["a"]],U.prototype,"next",void 0),Object(R["a"])([I["a"]],U.prototype,"last",void 0),Object(R["a"])([I["a"]],U.prototype,"clickRouteChange",void 0),U=Object(R["a"])([D["a"]],U);var M=U,G=M,W=(a("5dfa"),Object(z["a"])(G,q,F,!1,null,"5f6cfc3c",null)),J=W.exports,Q=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",[a("transition",{attrs:{"enter-active-class":"animated slideInDown","leave-active-class":"animated slideOutUp"}},[a("div",{directives:[{name:"show",rawName:"v-show",value:!e.aiShow,expression:"!aiShow"}],staticClass:"ai-button",on:{click:e.ping}},[a("div",{staticClass:"title"},[e._v("AI")])])]),a("transition",{attrs:{"enter-active-class":"animated slideInUp","leave-active-class":"animated slideOutDown"}},[a("div",{directives:[{name:"show",rawName:"v-show",value:e.aiShow,expression:"aiShow"}],staticClass:"ai"},[a("div",{staticClass:"title",on:{click:e.ping}},[e._v("\n Alpaca AI\n ")]),a("div",{directives:[{name:"show",rawName:"v-show",value:e.aiShow,expression:"aiShow"}],staticClass:"close",on:{click:e.closeAiShow}},[a("img",{attrs:{src:e.images.close,alt:""}})]),a("div",{staticClass:"content"},[e._l(e.chatlist,(function(t,n){return[a("div",{key:n},[0==t.type?a("div",[a("div",{staticClass:"left-bubble",domProps:{innerHTML:e._s(t.content)}})]):a("div",[a("div",{staticClass:"right-bubble",domProps:{innerHTML:e._s(t.content)}})])])]}))],2),a("div",{staticClass:"footer"},[a("input",{directives:[{name:"model",rawName:"v-model.trim",value:e.chatContent,expression:"chatContent",modifiers:{trim:!0}}],attrs:{placeholder:"输入文字即可和Alapca AI聊天!!!"},domProps:{value:e.chatContent},on:{keyup:function(t){return!t.type.indexOf("key")&&e._k(t.keyCode,"enter",13,t.key,"Enter")?null:e.sendText(t)},input:function(t){t.target.composing||(e.chatContent=t.target.value.trim())},blur:function(t){return e.$forceUpdate()}}}),a("el-tooltip",{attrs:{content:"发送文字",placement:"top"}},[a("img",{staticClass:"sendtext",attrs:{src:e.images.sendtext,alt:""},on:{click:e.sendText}})]),a("el-tooltip",{attrs:{content:"发送图片",placement:"top"}},[a("div",{staticClass:"file-upload"},[a("img",{staticClass:"sendimg",attrs:{src:e.images.sendimg,alt:""}}),a("input",{staticClass:"uploadimg",attrs:{type:"file"},on:{change:e.onFileChange}})])])],1)])])],1)},V=[],Y=(a("28a5"),a("4299")),K=function(e){function t(){var e;return Object(S["a"])(this,t),e=Object(_["a"])(this,Object(C["a"])(t).apply(this,arguments)),e.chatlist=[],e.chatContent="",e}return Object(T["a"])(t,e),Object(A["a"])(t,[{key:"ping",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.openAiShow(),e.next=3,this.$ajax.get("/ping");case 3:t=e.sent,console.log(t);case 5:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()},{key:"AlpacaAISaid",value:function(e){this.chatlist.push({type:0,content:e});var t=this.$el.querySelector(".content");t.scrollTop=t.scrollHeight}},{key:"VisitorSaid",value:function(e){this.chatlist.push({type:1,content:e});var t=this.$el.querySelector(".content");t.scrollTop=t.scrollHeight}},{key:"sendText",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){var t,a;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:if(this.$el.querySelector(".content"),""!==this.chatContent){e.next=6;break}return this.AlpacaAISaid("抱歉,我没听到"),e.abrupt("return");case 6:if(-1===this.chatContent.indexOf("微信")&&-1===this.chatContent.indexOf("wechat")){e.next=11;break}this.AlpacaAISaid("为您显示Alpaca Bi的微信二维码"),r()({title:"扫描二维码加好友",dangerouslyUseHTMLString:!0,message:'',position:"bottom-left"}),e.next=34;break;case 11:if(-1===this.chatContent.indexOf("毕国康")&&-1===this.chatContent.indexOf("Alpaca")&&-1===this.chatContent.indexOf("alpaca")){e.next=16;break}this.AlpacaAISaid("正在为您跳转到Alpaca Bi个人介绍"),this.$router.push({name:"info"}),e.next=34;break;case 16:return this.VisitorSaid(this.chatContent),e.next=19,this.$ajax.post("/ai/text",{text:this.chatContent});case 19:if(t=e.sent,this.chatContent="","ok"!==t.data.status){e.next=33;break}if(this.AlpacaAISaid(t.data.message),!t.data.isDirty){e.next=31;break}return a=document.getElementById("sound"),a.src="https://cdn.alpaca.run/zhexue/3.mp3",a.play(),document.title="f♂ck y♂u",e.next=30,Object(Y["a"])(3);case 30:document.title="Free Technology Blog & Alpaca Bi Website";case 31:e.next=34;break;case 33:this.AlpacaAISaid("抱歉,AI服务器网络错误");case 34:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()},{key:"sendImage",value:function(){this.AlpacaAISaid("图片识别功能开发中...")}},{key:"onFileChange",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(t){var a,n;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:a=this,n=new FileReader,n.readAsDataURL(t.target.files[0]),n.onload=function(e){var t=e.target.result,n=t.split(",")[1];a.$ajax.post("/ai/image",{imgBase64:n}).then((function(e){for(var n=e.data.message.result,o='
识别结果:
',i=0;i(').concat((100*n[i].score).toFixed(2),"%)").concat(n[i].keyword,"
"):"".concat(o,"(").concat((100*n[i].score).toFixed(2),"%)").concat(n[i].keyword,"
");"{}"!==JSON.stringify(n[0].baike_info)&&(o="".concat(o,"------------------------
").concat(n[0].baike_info.description)),a.AlpacaAISaid(o)}))};case 4:case"end":return e.stop()}}),e,this)})));function t(t){return e.apply(this,arguments)}return t}()},{key:"created",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,Object(Y["a"])(3.5);case 2:return this.AlpacaAISaid("你好啊,我是Alpaca AI,一个人工智能,你可以打字和我聊天!!!!"),e.next=5,Object(Y["a"])(2);case 5:return this.AlpacaAISaid("我同时也具备了图像识别功能,你可以在右下角发图给我识别!!!!"),e.next=8,Object(Y["a"])(2);case 8:this.AlpacaAISaid("我带有脏话检测功能,所以请文明发言哦!!!!");case 9:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()}]),t}(D["b"]);Object(R["a"])([I["c"]],K.prototype,"aiShow",void 0),Object(R["a"])([I["c"]],K.prototype,"images",void 0),Object(R["a"])([I["b"]],K.prototype,"closeAiShow",void 0),Object(R["a"])([I["b"]],K.prototype,"openAiShow",void 0),K=Object(R["a"])([D["a"]],K);var X=K,Z=X,ee=(a("bbfe"),Object(z["a"])(Z,Q,V,!1,null,"75dbc408",null)),te=ee.exports,ae=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("el-dialog",{attrs:{title:"登录",width:"500px","before-close":e.closeLoginDialogShow,visible:e.loginDialogShow},on:{"update:visible":function(t){e.loginDialogShow=t}}},[a("div",[a("span",{on:{click:function(t){return e.changeLoginState(0)}}},[e._v("登录")]),a("span",{on:{click:function(t){return e.changeLoginState(1)}}},[e._v("注册")])]),0==e.loginstate?a("div",[a("input",{directives:[{name:"model",rawName:"v-model",value:e.account,expression:"account"}],attrs:{type:"text"},domProps:{value:e.account},on:{input:function(t){t.target.composing||(e.account=t.target.value)}}}),a("input",{directives:[{name:"model",rawName:"v-model",value:e.password,expression:"password"}],attrs:{type:"password"},domProps:{value:e.password},on:{input:function(t){t.target.composing||(e.password=t.target.value)}}}),a("button",{on:{click:e.login}},[e._v("登录")])]):a("div",[a("input",{directives:[{name:"model",rawName:"v-model",value:e.account,expression:"account"}],attrs:{type:"text"},domProps:{value:e.account},on:{input:function(t){t.target.composing||(e.account=t.target.value)}}}),a("input",{directives:[{name:"model",rawName:"v-model",value:e.password,expression:"password"}],attrs:{type:"password"},domProps:{value:e.password},on:{input:function(t){t.target.composing||(e.password=t.target.value)}}}),a("input",{directives:[{name:"model",rawName:"v-model",value:e.repassword,expression:"repassword"}],attrs:{type:"password"},domProps:{value:e.repassword},on:{input:function(t){t.target.composing||(e.repassword=t.target.value)}}}),a("button",{on:{click:e.register}},[e._v("注册")])])])},ne=[],oe=function(e){function t(){var e;return Object(S["a"])(this,t),e=Object(_["a"])(this,Object(C["a"])(t).apply(this,arguments)),e.loginstate=0,e.account="",e.password="",e.repassword="",e}return Object(T["a"])(t,e),Object(A["a"])(t,[{key:"changeLoginState",value:function(e){this.loginstate=e}},{key:"login",value:function(){console.log("login")}},{key:"register",value:function(){console.log("register")}}]),t}(D["b"]);Object(R["a"])([I["c"]],oe.prototype,"loginDialogShow",void 0),Object(R["a"])([I["b"]],oe.prototype,"closeLoginDialogShow",void 0),oe=Object(R["a"])([D["a"]],oe);var ie=oe,re=ie,ce=(a("c419"),Object(z["a"])(re,ae,ne,!1,null,"3495f196",null)),se=ce.exports,le=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{attrs:{id:"header"}},[a("div",{attrs:{id:"headerWrapper"}},[a("div",{attrs:{id:"headerContainer"}},[a("div",{staticClass:"logo pornhub_logo",on:{click:e.changeAiShow}},[a("span",{staticClass:"text1"},[e._v("Alpaca")]),a("span",{staticClass:"text2"},[e._v("Run")])])])])])},ue=[],pe=function(e){function t(){return Object(S["a"])(this,t),Object(_["a"])(this,Object(C["a"])(t).apply(this,arguments))}return Object(T["a"])(t,e),Object(A["a"])(t,[{key:"handleOpen",value:function(e,t){console.log(e,t)}},{key:"handleClose",value:function(e,t){console.log(e,t)}},{key:"openWechatQRCode",value:function(){r()({title:"扫描二维码加好友",dangerouslyUseHTMLString:!0,message:'',position:"bottom-left"})}}]),t}(D["b"]);Object(R["a"])([I["c"]],pe.prototype,"images",void 0),Object(R["a"])([I["b"]],pe.prototype,"changeAiShow",void 0),Object(R["a"])([I["b"]],pe.prototype,"openLoginDialogShow",void 0),pe=Object(R["a"])([D["a"]],pe);var de=pe,he=de,me=(a("aae0"),Object(z["a"])(he,le,ue,!1,null,"53a2d0ed",null)),fe=me.exports,ge="https://cdn.alpaca.run/alpaca_blog%2Fimages%2F",ve={GitHub:ge+"GitHub.png",mail:ge+"mail.png",wechat:ge+"wechat.png",close:ge+"close.svg",sendtext:ge+"sendtext.svg",sendimg:ge+"sendimg.svg",location:ge+"location.svg",qualifications:ge+"qualifications.svg",marriage:ge+"marriage.svg",workstatus:ge+"workstatus.svg",cphone:ge+"cphone.svg",cwechat:ge+"cwechat.svg",cgithub:ge+"cgithub.svg",cmail:ge+"cmail.svg",wpQRCode:ge+"wpQRCode.jpg"},be=[{name:"live2d_ai",description:"基于live2d.js实现的动画小人ai,拥有聊天功能,还有图片识别功能,可以嵌入到网页里",stargazers_count:36,html_url:"https://github.com/AlpacaBi/live2d_ai",forks:13,language:"JavaScript"},{name:"bgk_weixin_bot",description:"基于python3的微信聊天机器人,增加了图片识别功能",stargazers_count:26,html_url:"https://github.com/AlpacaBi/bgk_weixin_bot",forks:13,language:"Python"},{name:"alpaca_run",description:"一个基于TypeScript+Golang+Vue+Graphql的个人网站",stargazers_count:24,html_url:"https://github.com/AlpacaBi/alpaca_run",forks:0,language:"TypeScript"},{name:"30-days-of-react-native-expo",description:"30 days of React Native Expo demos",stargazers_count:15,html_url:"https://github.com/AlpacaBi/30-days-of-react-native-expo",forks:2,language:"JavaScript"},{name:"qrcode_terminal",description:"QRCode Terminal For Deno",stargazers_count:7,html_url:"https://github.com/AlpacaBi/qrcode_terminal",forks:0,language:"JavaScript"},{name:"bgk-wechat-cleaner",description:"可以检测到微信好友、微信群的违规发言和违规图片,还微信交流良好环境",stargazers_count:7,html_url:"https://github.com/AlpacaBi/bgk-wechat-cleaner",forks:3,language:"Python"}],we=function(e){function t(){var e;return Object(S["a"])(this,t),e=Object(_["a"])(this,Object(C["a"])(t).apply(this,arguments)),e.dialogFormVisible=!1,e}return Object(T["a"])(t,e),Object(A["a"])(t,[{key:"created",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return this.getGithubRepo(),t=document.createElement("div"),Object.defineProperty(t,"id",{get:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){var t;return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:return t="\n ⣿⣿⣿⣿⣿⣿⢟⣡⣴⣶⣶⣦⣌⡛⠟⣋⣩⣬⣭⣭⡛⢿⣿⣿⣿⣿\n ⣿⣿⣿⣿⠋⢰⣿⣿⠿⣛⣛⣙⣛⠻⢆⢻⣿⠿⠿⠿⣿⡄⠻⣿⣿⣿\n ⣿⣿⣿⠃⢠⣿⣿⣶⣿⣿⡿⠿⢟⣛⣒⠐⠲⣶⡶⠿⠶⠶⠦⠄⠙⢿\n ⣿⠋⣠⠄⣿⣿⣿⠟⡛⢅⣠⡵⡐⠲⣶⣶⣥⡠⣤⣵⠆⠄⠰⣦⣤⡀\n ⠇⣰⣿⣼⣿⣿⣧⣤⡸ ⣿⡀⠂⠁⣸⣿⣿⣿⣿⣇⠄⠈⢀⣿⣿⠿\n ⣰⣿⣿⣿⣿⣿⣿⣿⣷⣤⣈⣙⠶⢾⠭⢉⣁⣴⢯⣭⣵⣶⠾⠓⢀⣴\n ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣉⣤⣴⣾⣿⣿⣦⣄⣤⣤⣄⠄⢿⣿\n ⣿⣿⣿⣿⣿⣿⣿⣿⠿⠿⠿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣇⠈⢿\n ⣿⣿⣿⣿⣿⣿⡟⣰⣞⣛⡒⢒⠤⠦⢬⣉⣉⣉⣉⣉⣉⣉⡥⠴⠂⢸\n ⠻⣿⣿⣿⣿⣏⠻⢌⣉⣉⣩⣉⡛⣛⠒⠶⠶⠶⠶⠶⠶⠶⠶⠂⣸⣿\n ⣥⣈⠙⡻⠿⠿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⠿⠛⢉⣠⣶⣶⣿⣿\n ⣿⣿⣿⣶⣬⣅⣒⣒⡂⠈⠭⠭⠭⠭⠭⢉⣁⣄⡀⢾⣿⣿⣿⣿⣿⣿\n ",console.log("%c检测到你打开了控制台","font-size:20px;color:white;background:black"),e.next=4,Object(Y["a"])(1.5);case 4:return console.log("%c5","font-size:20px;color:white;background:black"),e.next=7,Object(Y["a"])(1.5);case 7:return console.log("%c4","font-size:20px;color:white;background:black"),e.next=10,Object(Y["a"])(1.5);case 10:return console.log("%c3","font-size:20px;color:white;background:black"),e.next=13,Object(Y["a"])(1.5);case 13:return console.log("%c2","font-size:20px;color:white;background:black"),e.next=16,Object(Y["a"])(1.5);case 16:return console.log("%c1","font-size:20px;color:white;background:black"),e.next=19,Object(Y["a"])(1.5);case 19:return console.log("%c ","background: url(https://alpaca.cdn.bcebos.com/blackpeople.gif) no-repeat center;padding-left:640px;padding-bottom: 242px;"),console.log("%c棺材一抬,世间白来","font-size:20px;color:white;background:black"),console.log("%c脚一滑,人一叫,孟婆端汤阎王笑","font-size:20px;color:white;background:black"),console.log("%c眼一闭,布一盖,亲戚朋友等上菜","font-size:20px;color:white;background:black"),console.log("%c棺一抬,土一埋,一人一句古德拜","font-size:20px;color:white;background:black"),e.next=26,Object(Y["a"])(1.5);case 26:console.log(t);case 27:case"end":return e.stop()}}),e)})));function t(){return e.apply(this,arguments)}return t}()}),console.log(t),["帕秋莉~GO!","ASS WE CAN!!","boy next door","f♂ck y♂u","Oh!~YES,SIR♂","OH~卖箫的~","啊?乖♂乖♂站♂好","啊?幻想乡~","啊啊啊啊啊!!","奥义很爽","乖♂乖♂站♂好"],e.next=7,Object(Y["a"])(1);case 7:this.openAiShow();case 8:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()},{key:"getGithubRepo",value:function(){var e=Object(j["a"])(regeneratorRuntime.mark((function e(){return regeneratorRuntime.wrap((function(e){while(1)switch(e.prev=e.next){case 0:this.setRepos(be);case 1:case"end":return e.stop()}}),e,this)})));function t(){return e.apply(this,arguments)}return t}()}]),t}(D["b"]);Object(R["a"])([I["c"]],we.prototype,"aiShow",void 0),Object(R["a"])([I["b"]],we.prototype,"openAiShow",void 0),Object(R["a"])([I["a"]],we.prototype,"setRepos",void 0),we=Object(R["a"])([Object(D["a"])({components:{LeftMenu:H,AlpacaAI:te,LoginDialog:se,TopBar:fe,Home:J}})],we);var ye=we,ke=ye,Oe=(a("5c0b"),Object(z["a"])(ke,O,x,!1,null,null,null)),xe=Oe.exports,je=a("8c4f");k["default"].use(je["a"]);var Se=new je["a"]({mode:"hash",base:"/",routes:[{path:"/",name:"info",component:function(){return a.e("chunk-7ce5de4d").then(a.bind(null,"df06"))}},{path:"profile",name:"profile",component:function(){return a.e("chunk-2e1de229").then(a.bind(null,"c108"))}},{path:"contact",name:"contact",component:function(){return a.e("chunk-62af08d6").then(a.bind(null,"b7df"))}}]}),Ae=(a("20d6"),a("2f62"));k["default"].use(Ae["a"]);var _e={aiShow:!1,loginDialogShow:!1,num:0,routes:Se,animateOptions:{leave:"fadeOutDown",enter:"fadeInDown",leaveTime:1500,enterTime:1500},showArrow:!0,images:ve,reposData:[]},Ce=new Ae["a"].Store({state:_e,mutations:{add:function(e){e.num++},del:function(e){e.num--},changeAiShow:function(e){e.aiShow=!e.aiShow},openAiShow:function(e){e.aiShow=!0},closeAiShow:function(e){e.aiShow=!1},openLoginDialogShow:function(e){e.loginDialogShow=!0},closeLoginDialogShow:function(e){e.loginDialogShow=!1},changeAnimateDirection:function(e,t){e.animateOptions=t},changeShowArrow:function(e){e.showArrow=!e.showArrow},setReposData:function(e,t){e.reposData=t}},actions:{next:function(e,t){var a=e.commit,n=e.state;return new Promise((function(e){var o,i=n.routes.options.routes.findIndex((function(e){return e.name===t}));o=i+1===n.routes.options.routes.length?n.routes.options.routes[0].name:n.routes.options.routes[i+1].name;var r={leave:"slideOutUp",enter:"slideInUp",leaveTime:1e3,enterTime:1e3};a("changeAnimateDirection",r),a("changeShowArrow"),e(o),setTimeout((function(){a("changeShowArrow")}),n.animateOptions.leaveTime+n.animateOptions.enterTime);var c=document.getElementById("sound");c.src="https://cdn.alpaca.run/zhexue/2.mp3",c.play(),document.title="boy next door",setTimeout((function(){document.title="Free Technology Blog & Alpaca Bi Website"}),3e3)}))},last:function(e,t){var a=e.commit,n=e.state;return new Promise((function(e){var o,i=n.routes.options.routes.findIndex((function(e){return e.name===t}));if(0===i){var r=n.routes.options.routes.length;o=n.routes.options.routes[r-1].name}else o=n.routes.options.routes[i-1].name;var c={leave:"slideOutDown",enter:"slideInDown",leaveTime:1e3,enterTime:1e3};a("changeAnimateDirection",c),a("changeShowArrow"),e(o),setTimeout((function(){a("changeShowArrow")}),n.animateOptions.leaveTime+n.animateOptions.enterTime)}))},clickRouteChange:function(e){var t=e.commit,a=e.state,n={leave:"zoomOut",enter:"zoomIn",leaveTime:1e3,enterTime:1e3};t("changeAnimateDirection",n),t("changeShowArrow"),setTimeout((function(){t("changeShowArrow")}),a.animateOptions.leaveTime+a.animateOptions.enterTime)},setRepos:function(e,t){var a=e.commit;e.state;a("setReposData",t)}}}),Te=a("bc3a"),Re=a.n(Te),De=a("4328"),Ie=a.n(De),Pe={},Le={};Pe=Re.a.create({baseURL:"/apis",timeout:5e4,headers:{"Content-Type":"application/x-www-form-urlencoded"},withCredentials:!0}),Le=Re.a.create({baseURL:"/github",timeout:5e4,headers:{"Content-Type":"application/x-www-form-urlencoded"},withCredentials:!0}),Pe.interceptors.request.use((function(e){return e.data=Ie.a.stringify(e.data),e}),(function(e){console.error("error:",e),Promise.reject(e)})),Le.interceptors.request.use((function(e){return e.data=Ie.a.stringify(e.data),e}),(function(e){console.error("error:",e),Promise.reject(e)}));var Be={service:Pe,githubService:Le},Ee=Be;a("0fae");k["default"].component(y.a.name,y.a),k["default"].component(b.a.name,b.a),k["default"].component(g.a.name,g.a),k["default"].component(m.a.name,m.a),k["default"].component(d.a.name,d.a),k["default"].component(u.a.name,u.a),k["default"].component(s.a.name,s.a),k["default"].component(r.a.name,r.a),k["default"].component(o.a.name,o.a),k["default"].prototype.$ajax=Ee.service,k["default"].prototype.$github_ajax=Ee.githubService,k["default"].config.productionTip=!1,new k["default"]({router:Se,store:Ce,render:function(e){return e(xe)}}).$mount("#app")},e332:function(e,t,a){}}); -------------------------------------------------------------------------------- /views/dist/js/chunk-2e1de229.ec6496b8.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2e1de229"],{a08f:function(t,a,s){},ac49:function(t,a,s){"use strict";var i=s("a08f"),e=s.n(i);e.a},c108:function(t,a,s){"use strict";s.r(a);var i=function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("div",{staticClass:"page-item section"},[s("div",{staticClass:"profile-title"},[t._v("GitHub Status")]),t._m(0),s("div",{staticClass:"profile-title2"},[t._v("开源项目")]),s("div",{staticClass:"github-repo"},t._l(t.reposData,(function(a,i){return s("div",{key:i,staticClass:"item",on:{click:function(s){return t.skipTo(a.html_url)}}},[s("div",{staticClass:"title"},[t._v(t._s(a.name))]),s("div",{staticClass:"info"},[t._v(t._s(a.description))]),s("div",{staticClass:"data"},[s("div",{staticClass:"star",attrs:{title:"star"}},[s("span",{staticClass:"icon"},[t._v("⭐")]),t._v(t._s(a.stargazers_count))]),s("div",{staticClass:"fork",attrs:{title:"fork"}},[s("span",{staticClass:"icon"},[t._v("💾")]),t._v(t._s(a.forks))]),s("div",{staticClass:"language",attrs:{title:"language"}},[s("span",{staticClass:"icon"},[t._v("🔧")]),t._v(t._s(a.language))])])])})),0),s("div",{staticClass:"next",on:{click:t.nextPage}},[t._v("Next")])])},e=[function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("div",{staticClass:"github-status"},[s("div",{staticClass:"item"},[s("img",{attrs:{src:"https://github-stat.alpaca.run/api?username=alpacabi&show_icons=true&title_color=f90&bg_color=000000&icon_color=ffffff&text_color=f90&hide_border=true#gitstat",alt:"Github Stat"}})]),s("div",{staticClass:"item"},[s("img",{attrs:{src:"https://github-stat.alpaca.run/api/top-langs?username=alpacabi&layout=compact&title_color=f90&bg_color=000000&icon_color=ffffff&text_color=f90&hide_border=true&card_width=445#gitstat",alt:"Hot Lang"}})])])}],c=(s("7f7f"),s("d225")),o=s("b0b4"),n=s("308d"),r=s("6bb5"),l=s("4e2b"),u=s("9ab4"),f=s("60a3"),p=s("4bb5"),v=function(t){function a(){return Object(c["a"])(this,a),Object(n["a"])(this,Object(r["a"])(a).apply(this,arguments))}return Object(l["a"])(a,t),Object(o["a"])(a,[{key:"skipTo",value:function(t){window.open(t)}},{key:"nextPage",value:function(){var t=this,a=this.$route.name;this.next(a).then((function(a){t.$router.push({name:a})}))}}]),a}(f["b"]);Object(u["a"])([p["c"]],v.prototype,"profile",void 0),Object(u["a"])([p["c"]],v.prototype,"reposData",void 0),Object(u["a"])([p["a"]],v.prototype,"next",void 0),v=Object(u["a"])([f["a"]],v);var _=v,b=_,d=(s("ac49"),s("2877")),h=Object(d["a"])(b,i,e,!1,null,"377a5208",null);a["default"]=h.exports}}]); -------------------------------------------------------------------------------- /views/dist/js/chunk-62af08d6.46a79f12.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-62af08d6"],{"1a64":function(t,e,a){},b7df:function(t,e,a){"use strict";a.r(e);var s=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"page-item section"},[a("div",{directives:[{name:"show",rawName:"v-show",value:t.show0,expression:"show0"}],staticClass:"welcome"},[t._v("欢迎各位大佬前来交流学♂习心得,共同进步!!")]),a("div",{staticClass:"cards"},[a("div",{directives:[{name:"show",rawName:"v-show",value:t.show1,expression:"show1"}],staticClass:"card",on:{mouseenter:function(e){t.phone="打电话"},mouseleave:function(e){t.phone="17666503029"}}},[a("img",{attrs:{src:t.images.cphone,alt:""}}),a("div",{staticClass:"text"},[a("a",{staticClass:"text",attrs:{href:"tel:17666503029"}},[t._v(t._s(t.phone))])])]),a("div",{directives:[{name:"show",rawName:"v-show",value:t.show2,expression:"show2"}],staticClass:"card",on:{click:t.openWechatQRCode,mouseenter:function(e){t.wechat="弹出微信二维码"},mouseleave:function(e){t.wechat="workbiguokang"}}},[a("img",{attrs:{src:t.images.cwechat,alt:""}}),a("div",{staticClass:"text"},[t._v(t._s(t.wechat))])]),a("div",{directives:[{name:"show",rawName:"v-show",value:t.show3,expression:"show3"}],staticClass:"card",on:{mouseenter:function(e){t.github="进入AlpacaBi的GitHub"},mouseleave:function(e){t.github="AlpacaBi"}}},[a("img",{attrs:{src:t.images.cgithub,alt:""}}),a("div",{staticClass:"text"},[a("a",{staticClass:"text",attrs:{href:"https://github.com/AlpacaBi",target:"_blank"}},[t._v(t._s(t.github))])])]),a("div",{directives:[{name:"show",rawName:"v-show",value:t.show4,expression:"show4"}],staticClass:"card",on:{mouseenter:function(e){t.email="发邮件"},mouseleave:function(e){t.email="biguokang@outlook.com"}}},[a("img",{attrs:{src:t.images.cmail,alt:""}}),a("div",{staticClass:"text"},[a("a",{staticClass:"text",attrs:{href:"Mailto:biguokang@outlook.com"}},[t._v(t._s(t.email))])])])]),a("div",{staticClass:"next",on:{click:t.nextPage}},[t._v("Back To Home")])])},i=[],o=(a("7f7f"),a("46a1"),a("450d"),a("e5f2")),n=a.n(o),c=(a("96cf"),a("3b8d")),r=a("d225"),h=a("b0b4"),u=a("308d"),l=a("6bb5"),w=a("4e2b"),v=a("9ab4"),m=a("60a3"),d=a("4bb5"),p=a("4299"),b=function(t){function e(){var t;return Object(r["a"])(this,e),t=Object(u["a"])(this,Object(l["a"])(e).apply(this,arguments)),t.show0=!1,t.show1=!1,t.show2=!1,t.show3=!1,t.show4=!1,t.show5=!1,t.phone="17666503029",t.wechat="workbiguokang",t.github="AlpacaBi",t.email="biguokang",t}return Object(w["a"])(e,t),Object(h["a"])(e,[{key:"created",value:function(){this.showCard()}},{key:"showCard",value:function(){var t=Object(c["a"])(regeneratorRuntime.mark((function t(){return regeneratorRuntime.wrap((function(t){while(1)switch(t.prev=t.next){case 0:return t.next=2,Object(p["a"])(.2);case 2:this.show0=!0,this.show1=!0,this.show2=!0,this.show3=!0,this.show4=!0;case 7:case"end":return t.stop()}}),t,this)})));function e(){return t.apply(this,arguments)}return e}()},{key:"openWechatQRCode",value:function(){n()({title:"扫描二维码加好友",dangerouslyUseHTMLString:!0,message:'',position:"bottom-left"})}},{key:"nextPage",value:function(){var t=this,e=this.$route.name;this.next(e).then((function(e){t.$router.push({name:e})}))}}]),e}(m["b"]);Object(v["a"])([d["c"]],b.prototype,"contact",void 0),Object(v["a"])([d["c"]],b.prototype,"images",void 0),Object(v["a"])([d["a"]],b.prototype,"next",void 0),b=Object(v["a"])([m["a"]],b);var f=b,g=f,k=(a("d80f"),a("2877")),x=Object(k["a"])(g,s,i,!1,null,"b71281fe",null);e["default"]=x.exports},d80f:function(t,e,a){"use strict";var s=a("1a64"),i=a.n(s);i.a}}]); -------------------------------------------------------------------------------- /views/dist/js/chunk-7ce5de4d.fc1a92e8.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-7ce5de4d"],{af46:function(t,e,a){"use strict";var n=a("e932"),c=a.n(n);c.a},df06:function(t,e,a){"use strict";a.r(e);var n=function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"info"},[a("div",{staticClass:"name"},[t._v("Alpaca Bi")]),a("div",{staticClass:"intro"},[t._v("一个来自广州的95后全栈工程师")]),a("div",{staticClass:"more"},[t._v("想了解更多?请在终端输入以下命令")]),a("el-tooltip",{attrs:{content:"点击即可复制",placement:"right",effect:"dark"}},[a("div",{staticClass:"terminal",on:{click:t.copy}},[t._v("\n npx alpaca-bi\n ")])]),a("div",{staticClass:"next",on:{click:t.nextPage}},[t._v("Next")]),t._m(0)],1)},c=[function(){var t=this,e=t.$createElement,a=t._self._c||e;return a("div",{staticClass:"icp"},[a("div",{attrs:{id:"beian"}},[a("a",{staticStyle:{color:"white"},attrs:{href:"https://beian.miit.gov.cn/",target:"_blank"}},[t._v("备案号:粤ICP备17017545号")])])])}],i=(a("7f7f"),a("46a1"),a("450d"),a("e5f2")),s=a.n(i),o=a("d225"),r=a("b0b4"),l=a("308d"),u=a("6bb5"),d=a("4e2b"),p=a("9ab4"),b=a("60a3"),v=a("4bb5"),f=function(t){function e(){return Object(o["a"])(this,e),Object(l["a"])(this,Object(u["a"])(e).apply(this,arguments))}return Object(d["a"])(e,t),Object(r["a"])(e,[{key:"copy",value:function(){var t=document.createElement("input");document.body.appendChild(t),t.setAttribute("value","npx alpaca-bi"),t.select(),document.execCommand("copy")&&document.execCommand("copy"),document.body.removeChild(t),s()({title:"成功",message:"复制成功",type:"success",position:"top-left"})}},{key:"nextPage",value:function(){var t=this,e=this.$route.name;this.next(e).then((function(e){t.$router.push({name:e})}))}}]),e}(b["b"]);Object(p["a"])([v["a"]],f.prototype,"next",void 0),f=Object(p["a"])([b["a"]],f);var m=f,h=m,y=(a("af46"),a("2877")),C=Object(y["a"])(h,n,c,!1,null,"3ce94835",null);e["default"]=C.exports},e932:function(t,e,a){}}]); -------------------------------------------------------------------------------- /views/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "alpaca-blog", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build", 8 | "lint": "vue-cli-service lint" 9 | }, 10 | "dependencies": { 11 | "animate.css": "^3.7.2", 12 | "axios": "^0.21.1", 13 | "core-js": "^2.6.5", 14 | "element-ui": "^2.12.0", 15 | "vue": "^2.6.10", 16 | "vue-class-component": "^7.0.2", 17 | "vue-property-decorator": "^8.1.0", 18 | "vue-router": "^3.0.3", 19 | "vuex": "^3.0.1", 20 | "vuex-class": "^0.3.2" 21 | }, 22 | "devDependencies": { 23 | "@types/qs": "^6.9.5", 24 | "@vue/cli-plugin-babel": "^3.11.0", 25 | "@vue/cli-plugin-typescript": "^3.11.0", 26 | "@vue/cli-service": "^3.11.0", 27 | "babel-plugin-component": "^1.1.1", 28 | "sass": "^1.18.0", 29 | "sass-loader": "^7.1.0", 30 | "typescript": "^3.4.3", 31 | "vue-template-compiler": "^2.6.10" 32 | }, 33 | "postcss": { 34 | "plugins": { 35 | "autoprefixer": {} 36 | } 37 | }, 38 | "browserslist": [ 39 | "> 1%", 40 | "last 2 versions" 41 | ] 42 | } 43 | -------------------------------------------------------------------------------- /views/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/public/favicon.ico -------------------------------------------------------------------------------- /views/public/finger.cur: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/public/finger.cur -------------------------------------------------------------------------------- /views/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Free Technology Blog & Alpaca Bi Website 9 | 10 | 11 | 12 | 15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /views/src/App.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 119 | 120 | -------------------------------------------------------------------------------- /views/src/assets/images/avatar.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/src/assets/images/avatar.jpeg -------------------------------------------------------------------------------- /views/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlpacaBi/alpaca_run/251f2a70c860ffb658a33db0aae0bea6d05eda1c/views/src/assets/logo.png -------------------------------------------------------------------------------- /views/src/components/AboutSection/Contact.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 99 | 100 | 204 | -------------------------------------------------------------------------------- /views/src/components/AboutSection/Info.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 56 | 57 | 134 | 135 | 136 | -------------------------------------------------------------------------------- /views/src/components/AboutSection/Profile.vue: -------------------------------------------------------------------------------- 1 | 27 | 28 | 50 | 51 | 256 | -------------------------------------------------------------------------------- /views/src/components/AboutSection/Skills.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | 17 | 37 | -------------------------------------------------------------------------------- /views/src/components/AlpacaAI.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 162 | 163 | 164 | 506 | -------------------------------------------------------------------------------- /views/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /views/src/components/LeftMenu.vue: -------------------------------------------------------------------------------- 1 | 67 | 68 | 96 | 97 | 98 | 164 | -------------------------------------------------------------------------------- /views/src/components/LoginDialog.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 50 | 51 | 56 | -------------------------------------------------------------------------------- /views/src/components/TopBar.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 41 | 42 | 43 | 88 | -------------------------------------------------------------------------------- /views/src/data/data.ts: -------------------------------------------------------------------------------- 1 | import avatar from '@/assets/images/avatar.jpeg'; 2 | 3 | const cdnImageURL: string = 'https://cdn.alpaca.run/alpaca_blog%2Fimages%2F'; 4 | 5 | export const images = { 6 | // LeftMenu 7 | GitHub: cdnImageURL + 'GitHub.png', 8 | mail: cdnImageURL + 'mail.png', 9 | wechat: cdnImageURL + 'wechat.png', 10 | // AlpacaAI 11 | close: cdnImageURL + 'close.svg', 12 | sendtext: cdnImageURL + 'sendtext.svg', 13 | sendimg: cdnImageURL + 'sendimg.svg', 14 | // Info 15 | location: cdnImageURL + 'location.svg', 16 | qualifications: cdnImageURL + 'qualifications.svg', 17 | marriage: cdnImageURL + 'marriage.svg', 18 | workstatus: cdnImageURL + 'workstatus.svg', 19 | // Contant 20 | cphone: cdnImageURL + 'cphone.svg', 21 | cwechat: cdnImageURL + 'cwechat.svg', 22 | cgithub: cdnImageURL + 'cgithub.svg', 23 | cmail: cdnImageURL + 'cmail.svg', 24 | wpQRCode: cdnImageURL + 'wpQRCode.jpg', 25 | }; 26 | 27 | export const repoData = [ 28 | { 29 | name: 'live2d_ai', 30 | description: '基于live2d.js实现的动画小人ai,拥有聊天功能,还有图片识别功能,可以嵌入到网页里', 31 | stargazers_count: 36, 32 | html_url: 'https://github.com/AlpacaBi/live2d_ai', 33 | forks: 13, 34 | language: 'JavaScript', 35 | }, 36 | { 37 | name: 'bgk_weixin_bot', 38 | description: '基于python3的微信聊天机器人,增加了图片识别功能', 39 | stargazers_count: 26, 40 | html_url: 'https://github.com/AlpacaBi/bgk_weixin_bot', 41 | forks: 13, 42 | language: 'Python', 43 | }, 44 | { 45 | name: 'alpaca_run', 46 | description: '一个基于TypeScript+Golang+Vue+Graphql的个人网站', 47 | stargazers_count: 24, 48 | html_url: 'https://github.com/AlpacaBi/alpaca_run', 49 | forks: 0, 50 | language: 'TypeScript', 51 | }, 52 | { 53 | name: '30-days-of-react-native-expo', 54 | description: '30 days of React Native Expo demos', 55 | stargazers_count: 15, 56 | html_url: 'https://github.com/AlpacaBi/30-days-of-react-native-expo', 57 | forks: 2, 58 | language: 'JavaScript', 59 | }, 60 | { 61 | name: 'qrcode_terminal', 62 | description: 'QRCode Terminal For Deno', 63 | stargazers_count: 7, 64 | html_url: 'https://github.com/AlpacaBi/qrcode_terminal', 65 | forks: 0, 66 | language: 'JavaScript', 67 | }, 68 | { 69 | name: 'bgk-wechat-cleaner', 70 | description: '可以检测到微信好友、微信群的违规发言和违规图片,还微信交流良好环境', 71 | stargazers_count: 7, 72 | html_url: 'https://github.com/AlpacaBi/bgk-wechat-cleaner', 73 | forks: 3, 74 | language: 'Python', 75 | }, 76 | ]; 77 | -------------------------------------------------------------------------------- /views/src/image.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' 2 | declare module '*.png' 3 | declare module '*.jpg' 4 | declare module '*.jpeg' 5 | declare module '*.gif' 6 | declare module '*.bmp' 7 | declare module '*.tiff' 8 | -------------------------------------------------------------------------------- /views/src/main.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './App.vue'; 3 | import router from './router'; 4 | import store from './store'; 5 | import services from './utils/ajax'; 6 | import 'element-ui/lib/theme-chalk/index.css'; 7 | import { 8 | Button, 9 | Menu, 10 | MenuItem, 11 | MenuItemGroup, 12 | Carousel, 13 | CarouselItem, 14 | Tooltip, 15 | Notification, 16 | Dialog, 17 | } from 'element-ui'; 18 | 19 | Vue.component(Button.name, Button); 20 | Vue.component(Menu.name, Menu); 21 | Vue.component(MenuItem.name, MenuItem); 22 | Vue.component(MenuItemGroup.name, MenuItemGroup); 23 | Vue.component(Carousel.name, Carousel); 24 | Vue.component(CarouselItem.name, CarouselItem); 25 | Vue.component(Tooltip.name, Tooltip); 26 | Vue.component(Notification.name, Notification); 27 | Vue.component(Dialog.name, Dialog); 28 | 29 | // 封装好了axios,并接入Vue的原型链,从而在任何地方都能使用 30 | Vue.prototype.$ajax = services.service; 31 | Vue.prototype.$github_ajax = services.githubService; 32 | 33 | Vue.config.productionTip = false; 34 | 35 | new Vue({ 36 | router, 37 | store, 38 | render: (h) => h(App), 39 | }).$mount('#app'); 40 | -------------------------------------------------------------------------------- /views/src/router.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Router from 'vue-router'; 3 | import Home from '@/views/Home.vue'; 4 | 5 | Vue.use(Router); 6 | 7 | export default new Router({ 8 | mode: 'hash', 9 | base: process.env.BASE_URL, 10 | routes: [ 11 | { 12 | path: '/', 13 | name: 'info', 14 | component: () => import( './components/AboutSection/Info.vue'), 15 | }, 16 | // { 17 | // path: 'skills', 18 | // name: 'skills', 19 | // component: () => import('./components/AboutSection/Skills.vue'), 20 | // }, 21 | { 22 | path: 'profile', 23 | name: 'profile', 24 | component: () => import( './components/AboutSection/Profile.vue'), 25 | }, 26 | { 27 | path: 'contact', 28 | name: 'contact', 29 | component: () => import('./components/AboutSection/Contact.vue'), 30 | }, 31 | ], 32 | }); 33 | -------------------------------------------------------------------------------- /views/src/shime-global.d.ts: -------------------------------------------------------------------------------- 1 | declare module "element-ui"; -------------------------------------------------------------------------------- /views/src/shims-tsx.d.ts: -------------------------------------------------------------------------------- 1 | import Vue, { VNode } from 'vue'; 2 | 3 | declare global { 4 | namespace JSX { 5 | // tslint:disable no-empty-interface 6 | interface Element extends VNode {} 7 | // tslint:disable no-empty-interface 8 | interface ElementClass extends Vue {} 9 | interface IntrinsicElements { 10 | [elem: string]: any; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /views/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import qs from 'qs'; 3 | import VueRouter, { Route } from "vue-router"; 4 | declare module '*.vue' { 5 | export default Vue; 6 | } 7 | 8 | declare module 'qs' 9 | 10 | declare module "vue/types/vue" { 11 | interface Vue { 12 | $router: VueRouter; // 这表示this下有这个东西 13 | $route: Route; 14 | $ajax: any; 15 | $github_ajax: any; 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /views/src/store.ts: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import Vuex from 'vuex'; 3 | import router from './router'; 4 | import { images } from './data/data'; 5 | 6 | Vue.use(Vuex); 7 | 8 | interface IAnimateOptions { 9 | leave: string; 10 | enter: string; 11 | leaveTime: number; 12 | enterTime: number; 13 | } 14 | 15 | interface IState { 16 | aiShow: boolean; 17 | loginDialogShow: boolean; 18 | num: number; 19 | routes: any; 20 | animateOptions: IAnimateOptions; 21 | showArrow: boolean; 22 | images: any; 23 | reposData: any[]; 24 | } 25 | 26 | const State: IState = { 27 | aiShow: false, 28 | loginDialogShow: false, 29 | num: 0, 30 | routes: router, 31 | animateOptions: { 32 | leave: 'fadeOutDown', 33 | enter: 'fadeInDown', 34 | leaveTime: 1500, 35 | enterTime: 1500, 36 | }, 37 | showArrow: true, 38 | images, 39 | reposData: [], 40 | }; 41 | 42 | 43 | export default new Vuex.Store({ 44 | state: State, 45 | mutations: { 46 | add(state) { 47 | state.num++; 48 | }, 49 | del(state) { 50 | state.num--; 51 | }, 52 | changeAiShow(state) { 53 | state.aiShow = !state.aiShow; 54 | }, 55 | openAiShow(state) { 56 | state.aiShow = true; 57 | }, 58 | closeAiShow(state) { 59 | state.aiShow = false; 60 | }, 61 | openLoginDialogShow(state) { 62 | state.loginDialogShow = true; 63 | }, 64 | closeLoginDialogShow(state) { 65 | state.loginDialogShow = false; 66 | }, 67 | // 改变切换路由页面的过度动画 68 | changeAnimateDirection(state, data) { 69 | state.animateOptions = data; 70 | }, 71 | // 控制是否显示下一页的箭头 72 | changeShowArrow(state) { 73 | state.showArrow = !state.showArrow; 74 | }, 75 | setReposData(state, data) { 76 | state.reposData = data; 77 | }, 78 | }, 79 | actions: { 80 | // 下一页 =====> 鼠标滚轮向下滚动 或 向下滑动(移动端) 81 | next({ commit, state }, presentName) { 82 | return new Promise((resolve) => { 83 | // console.log(presentPath) 84 | // 获取当前页面路径在整体路由的位置 85 | const index = state.routes.options.routes.findIndex((route: any) => route.name === presentName); 86 | // 获取当前路由的下一个路由路径 87 | let nextPageName; 88 | if (index + 1 === state.routes.options.routes.length) { 89 | nextPageName = state.routes.options.routes[0].name; 90 | } else { 91 | nextPageName = state.routes.options.routes[index + 1].name; 92 | } 93 | const animateDirection = { 94 | leave: 'slideOutUp', 95 | enter: 'slideInUp', 96 | leaveTime: 1000, 97 | enterTime: 1000, 98 | }; 99 | commit('changeAnimateDirection', animateDirection); 100 | // commit('nextPage', nextPagePath) 101 | commit('changeShowArrow'); 102 | resolve(nextPageName); 103 | setTimeout(() => { 104 | commit('changeShowArrow'); 105 | }, state.animateOptions.leaveTime + state.animateOptions.enterTime); 106 | const sound: any = document.getElementById('sound'); 107 | sound.src = `https://cdn.alpaca.run/zhexue/2.mp3`; 108 | sound.play(); 109 | document.title = 'boy next door'; 110 | setTimeout(() => { 111 | document.title = 'Free Technology Blog & Alpaca Bi Website'; 112 | }, 3000); 113 | }); 114 | }, 115 | // 上一页 鼠标滚轮向上滚动 或 向上滑动(移动端) 116 | last({ commit, state }, presentName) { 117 | return new Promise((resolve) => { 118 | // console.log(presentPath) 119 | // 获取当前页面路径在整体路由的位置 120 | const index = state.routes.options.routes.findIndex((route: any) => route.name === presentName); 121 | // 获取当前路由的上一个路由路径 122 | let lastPageName; 123 | if (index === 0) { 124 | const routesLength = state.routes.options.routes.length; 125 | lastPageName = state.routes.options.routes[routesLength - 1].name; 126 | } else { 127 | lastPageName = state.routes.options.routes[index - 1].name; 128 | } 129 | // console.log(lastPagePath) 130 | const animateDirection = { 131 | leave: 'slideOutDown', 132 | enter: 'slideInDown', 133 | leaveTime: 1000, 134 | enterTime: 1000, 135 | }; 136 | commit('changeAnimateDirection', animateDirection); 137 | // commit('lastPage', lastPagePath) 138 | commit('changeShowArrow'); 139 | resolve(lastPageName); 140 | setTimeout(() => { 141 | commit('changeShowArrow'); 142 | }, state.animateOptions.leaveTime + state.animateOptions.enterTime); 143 | }); 144 | }, 145 | // 点击小圆点切换页面 146 | clickRouteChange({ commit, state }) { 147 | const animateDirection = { 148 | leave: 'zoomOut', 149 | enter: 'zoomIn', 150 | leaveTime: 1000, 151 | enterTime: 1000, 152 | }; 153 | commit('changeAnimateDirection', animateDirection); 154 | commit('changeShowArrow'); 155 | setTimeout(() => { 156 | commit('changeShowArrow'); 157 | }, state.animateOptions.leaveTime + state.animateOptions.enterTime); 158 | }, 159 | setRepos({ commit, state }, repos) { 160 | commit('setReposData', repos); 161 | }, 162 | }, 163 | }); 164 | -------------------------------------------------------------------------------- /views/src/utils/ajax.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import qs from 'qs'; 3 | 4 | // 创建axios实例 5 | let service: any = {}; 6 | let githubService: any = {}; 7 | if (process.env.NODE_ENV === 'development') { 8 | service = axios.create({ 9 | baseURL: '/apis', // api的base_url 10 | timeout: 50000, // 请求超时时间 11 | headers: { 12 | 'Content-Type': 'application/x-www-form-urlencoded', 13 | }, 14 | withCredentials: true, // 允许携带cookie 15 | }); 16 | githubService = axios.create({ 17 | baseURL: '/github', // api的base_url 18 | timeout: 50000, // 请求超时时间 19 | headers: { 20 | 'Content-Type': 'application/x-www-form-urlencoded', 21 | }, 22 | withCredentials: true, // 允许携带cookie 23 | }); 24 | } else { 25 | // 生产环境下 26 | service = axios.create({ 27 | baseURL: '/apis', // api的base_url 28 | timeout: 50000, // 请求超时时间 29 | headers: { 30 | 'Content-Type': 'application/x-www-form-urlencoded', 31 | }, 32 | withCredentials: true, // 允许携带cookie 33 | }); 34 | githubService = axios.create({ 35 | baseURL: '/github', // api的base_url 36 | timeout: 50000, // 请求超时时间 37 | headers: { 38 | 'Content-Type': 'application/x-www-form-urlencoded', 39 | }, 40 | withCredentials: true, // 允许携带cookie 41 | }); 42 | } 43 | 44 | // console.log('process.env.BASE_URL',process.env.BASE_URL) 45 | // request拦截器 axios的一些配置 46 | service.interceptors.request.use( 47 | (config: any) => { 48 | config.data = qs.stringify(config.data); 49 | return config; 50 | }, 51 | (error: any) => { 52 | // Do something with request error 53 | console.error('error:', error); // for debug 54 | Promise.reject(error); 55 | }, 56 | ); 57 | 58 | githubService.interceptors.request.use( 59 | (config: any) => { 60 | config.data = qs.stringify(config.data); 61 | return config; 62 | }, 63 | (error: any) => { 64 | // Do something with request error 65 | console.error('error:', error); // for debug 66 | Promise.reject(error); 67 | }, 68 | ); 69 | 70 | const services = { service, githubService }; 71 | 72 | export default services; 73 | -------------------------------------------------------------------------------- /views/src/utils/sleep.ts: -------------------------------------------------------------------------------- 1 | const sleep: any = (second: number) => new Promise( (resolve: any) => setTimeout(resolve, second * 1000)); 2 | 3 | export default sleep; 4 | -------------------------------------------------------------------------------- /views/src/views/Home.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 61 | 62 | -------------------------------------------------------------------------------- /views/src/views/Home1.vue: -------------------------------------------------------------------------------- 1 | 13 | 14 | 31 | 32 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /views/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "strict": true, 6 | "jsx": "preserve", 7 | "importHelpers": true, 8 | "moduleResolution": "node", 9 | "experimentalDecorators": true, 10 | "esModuleInterop": true, 11 | "allowSyntheticDefaultImports": true, 12 | "sourceMap": true, 13 | "baseUrl": ".", 14 | "types": [ 15 | "webpack-env" 16 | ], 17 | "paths": { 18 | "@/*": [ 19 | "src/*" 20 | ] 21 | }, 22 | "lib": [ 23 | "esnext", 24 | "dom", 25 | "dom.iterable", 26 | "scripthost" 27 | ] 28 | }, 29 | "include": [ 30 | "src/**/*.ts", 31 | "src/**/*.tsx", 32 | "src/**/*.vue", 33 | "tests/**/*.ts", 34 | "tests/**/*.tsx" 35 | ], 36 | "exclude": [ 37 | "node_modules" 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /views/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "warning", 3 | "extends": [ 4 | "tslint:recommended" 5 | ], 6 | "linterOptions": { 7 | "exclude": [ 8 | "node_modules/**" 9 | ] 10 | }, 11 | "rules": { 12 | "indent": [true, "spaces", 2], 13 | "interface-name": false, 14 | "no-consecutive-blank-lines": false, 15 | "object-literal-sort-keys": false, 16 | "ordered-imports": false, 17 | "quotemark": [true, "single"], 18 | "no-console": false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /views/vue.config.js: -------------------------------------------------------------------------------- 1 | const path = require("path"); 2 | const sourceMap = process.env.NODE_ENV === "development"; 3 | 4 | module.exports = { 5 | productionSourceMap: false, 6 | //这里配置代理服务器,因为开发环境中会发生跨域问题 7 | devServer: { 8 | proxy: { 9 | '/apis': { 10 | target: 'http://127.0.0.1:9527', 11 | changeOrigin: true, 12 | ws: true, 13 | pathRewrite: { 14 | '^/apis': '' 15 | } 16 | }, 17 | '/github': { 18 | target: 'https://api.github.com', 19 | changeOrigin: true, 20 | ws: true, 21 | pathRewrite: { 22 | '^/github': '' 23 | } 24 | } 25 | } 26 | } 27 | }; 28 | --------------------------------------------------------------------------------