378 lines
9.3 KiB
Go
378 lines
9.3 KiB
Go
package controller
|
||
|
||
import (
|
||
"backend/middleware/alibaba"
|
||
"backend/model"
|
||
"backend/util"
|
||
"fmt"
|
||
"os/exec"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"github.com/xuri/excelize/v2"
|
||
)
|
||
|
||
func Copywriting(c *gin.Context) {
|
||
request := struct {
|
||
Step int `json:"step"`
|
||
}{}
|
||
if err := c.BindJSON(&request); err != nil {
|
||
failed(c, "参数绑定失败: "+err.Error())
|
||
return
|
||
}
|
||
switch request.Step {
|
||
case 0:
|
||
success(c, map[string]interface{}{
|
||
"step": 1,
|
||
"label": "下载文案文件",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
case 1:
|
||
CopywritingStep1(c)
|
||
case 2:
|
||
CopywritingStep2(c)
|
||
case 3:
|
||
CopywritingStep3(c)
|
||
default:
|
||
failed(c, "无效的步骤")
|
||
}
|
||
util.AddAdminLog(c, "文案自动化脚本", request)
|
||
}
|
||
func CopywritingStep1(c *gin.Context) {
|
||
repoDir := `/data/docs`
|
||
// git fetch all
|
||
if out, err := exec.Command("git", "-C", repoDir, "fetch", "--all").CombinedOutput(); err != nil {
|
||
scritp_fail(c, "git fetch all 失败: "+err.Error()+": "+string(out))
|
||
return
|
||
}
|
||
// git reset --hard origin/main
|
||
if out, err := exec.Command("git", "-C", repoDir, "reset", "--hard", "origin/main").CombinedOutput(); err != nil {
|
||
scritp_fail(c, "git reset 失败: "+err.Error()+": "+string(out))
|
||
return
|
||
}
|
||
// git pull
|
||
if out, err := exec.Command("git", "-C", repoDir, "pull").CombinedOutput(); err != nil {
|
||
scritp_fail(c, "git pull 失败: "+err.Error()+": "+string(out))
|
||
return
|
||
}
|
||
err := alibaba.DownloadFile()
|
||
if err != nil {
|
||
success(c, map[string]interface{}{
|
||
"step": 2,
|
||
"label": "提交git",
|
||
"tips": []string{
|
||
err.Error(),
|
||
},
|
||
"code": 1,
|
||
})
|
||
return
|
||
}
|
||
// 执行脚本的逻辑
|
||
success(c, map[string]interface{}{
|
||
"step": 2,
|
||
"label": "提交git",
|
||
"tips": []string{
|
||
"下载文案文件DialogueData.xlsx成功",
|
||
},
|
||
"code": 0,
|
||
})
|
||
}
|
||
func CopywritingStep2(c *gin.Context) {
|
||
time.Sleep(time.Second)
|
||
code := 0
|
||
repoDir := `/data/docs`
|
||
file := `config/DialogueData.xlsx`
|
||
// git add
|
||
if out, err := exec.Command("git", "-C", repoDir, "add", file).CombinedOutput(); err != nil {
|
||
scritp_fail(c, "git add 失败: "+err.Error()+": "+string(out))
|
||
return
|
||
}
|
||
|
||
// git commit (ignore non-fatal commit output/errors like "nothing to commit")
|
||
exec.Command("git", "-C", repoDir, "commit", "-m", "Update DialogueData.xlsx").Run()
|
||
|
||
// git push
|
||
if out, err := exec.Command("git", "-C", repoDir, "push").CombinedOutput(); err != nil {
|
||
scritp_fail(c, "git push 失败: "+err.Error()+": "+string(out))
|
||
return
|
||
}
|
||
|
||
_ = code
|
||
// 执行脚本的逻辑
|
||
success(c, map[string]interface{}{
|
||
"step": 3,
|
||
"label": "修改翻译表",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
}
|
||
|
||
func CopywritingStep3(c *gin.Context) {
|
||
file := `/data/docs/config/DialogueData.xlsx`
|
||
f, err := excelize.OpenFile(file)
|
||
if err != nil {
|
||
failed(c, "打开文件失败: "+err.Error())
|
||
return
|
||
}
|
||
defer f.Close()
|
||
|
||
rows, err := f.GetRows("DialogueData")
|
||
if err != nil {
|
||
failed(c, "读取sheet失败: "+err.Error())
|
||
return
|
||
}
|
||
type Dialogue struct {
|
||
Id int
|
||
Key string
|
||
Dialogue string
|
||
}
|
||
dialogueMap := make(map[string]Dialogue)
|
||
for i, row := range rows {
|
||
// 跳过标题行(如果有)
|
||
if i < 2 {
|
||
continue
|
||
}
|
||
var dVal, iVal string
|
||
if len(row) > 3 {
|
||
dVal = row[3] // D列,0-based 索引 3
|
||
}
|
||
if len(row) > 8 {
|
||
iVal = row[8] // I列,0-based 索引 8
|
||
}
|
||
var lVal string
|
||
if len(row) > 11 {
|
||
lVal = row[11] // L列,0-based 索引 11
|
||
}
|
||
if lVal != "" {
|
||
continue
|
||
}
|
||
if dVal == "" || iVal == "" {
|
||
continue
|
||
}
|
||
dialogueMap[dVal] = Dialogue{
|
||
Key: dVal,
|
||
Dialogue: iVal,
|
||
Id: i - 2, // 减去标题行
|
||
}
|
||
}
|
||
type db_data struct {
|
||
Id int `db:"Id"`
|
||
Key string `db:"key"`
|
||
EnUs string `db:"en_us"`
|
||
OldValue string
|
||
}
|
||
var dbDatas []db_data
|
||
db := util.MPool.GetGameDB()
|
||
defer db.Close()
|
||
if db == nil {
|
||
scritp_fail(c, "获取数据库连接失败")
|
||
return
|
||
}
|
||
err = db.Select(&dbDatas, "SELECT `Id`, `key`, `en_us` FROM `language`")
|
||
if err != nil {
|
||
scritp_fail(c, "查询语言表失败: "+err.Error())
|
||
return
|
||
}
|
||
updateData := []db_data{}
|
||
for _, item := range dbDatas {
|
||
if val, ok := dialogueMap[item.Key]; ok {
|
||
if val.Dialogue != item.EnUs {
|
||
item.OldValue = item.EnUs
|
||
item.EnUs = val.Dialogue
|
||
updateData = append(updateData, item)
|
||
}
|
||
delete(dialogueMap, item.Key)
|
||
}
|
||
}
|
||
for _, item := range updateData {
|
||
_, err := db.Exec("UPDATE `language` SET `en_us` = ? WHERE `key` = ?", item.EnUs, item.Key)
|
||
if err != nil {
|
||
scritp_fail(c, "更新语言表失败: "+err.Error())
|
||
return
|
||
}
|
||
_, err = db.Exec("insert into language_op (`LanguageId`, `Field`, `OldValue`, `NewValue`, `Type`, `Update`, `Role`) values (?, ?, ?, ?, ?,?,?)", item.Id, "en_us", item.OldValue, item.EnUs, "Edit", util.Now(), "scripts")
|
||
}
|
||
|
||
for _, v := range dialogueMap {
|
||
result, err := db.Exec("INSERT INTO `language` (`key`, `en_us`) VALUES (?, ?)", v.Key, v.Dialogue)
|
||
if err != nil {
|
||
scritp_fail(c, "插入语言表失败: "+err.Error())
|
||
return
|
||
}
|
||
id, _ := result.LastInsertId()
|
||
_, err = db.Exec("insert into language_op (`LanguageId`, `Field`, `OldValue`, `NewValue`, `Type`, `Update`, `Role`) values (?, ?, ?, ?, ?,?,?)", id, "All", "", v.Dialogue, "Add", util.Now(), "scripts")
|
||
}
|
||
|
||
// 将结果放到 gin 上下文,供后续使用
|
||
c.Set("DialogueMap", dialogueMap)
|
||
tips := []string{}
|
||
if len(updateData) > 0 {
|
||
tips = append(tips, fmt.Sprintf("更新了 %d 条翻译内容", len(updateData)))
|
||
for _, v := range updateData {
|
||
tips = append(tips, fmt.Sprintf("Key: %s", v.Key))
|
||
}
|
||
}
|
||
if len(dialogueMap) > 0 {
|
||
tips = append(tips, fmt.Sprintf("新增了 %d 条翻译内容", len(dialogueMap)))
|
||
for _, v := range dialogueMap {
|
||
tips = append(tips, fmt.Sprintf("Key: %s", v.Key))
|
||
}
|
||
}
|
||
languageMod := &model.LanguageMod{}
|
||
go languageMod.LanguageListAll()
|
||
// 执行脚本的逻辑
|
||
success(c, map[string]interface{}{
|
||
"step": -1,
|
||
"label": "脚本执行成功",
|
||
"tips": tips,
|
||
"code": 0,
|
||
})
|
||
}
|
||
|
||
func scritp_fail(c *gin.Context, err string) {
|
||
success(c, map[string]interface{}{
|
||
"step": -1,
|
||
"label": "",
|
||
"tips": []string{
|
||
err,
|
||
},
|
||
"code": 1,
|
||
})
|
||
}
|
||
|
||
func CopyOnline(c *gin.Context) {
|
||
request := struct {
|
||
Step int `json:"step"`
|
||
}{}
|
||
if err := c.BindJSON(&request); err != nil {
|
||
failed(c, "参数绑定失败: "+err.Error())
|
||
return
|
||
}
|
||
switch request.Step {
|
||
case 0:
|
||
success(c, map[string]interface{}{
|
||
"step": 1,
|
||
"label": "复制数据库",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
case 1:
|
||
CopyOnlineStep1(c)
|
||
case 2:
|
||
CopyOnlineStep2(c)
|
||
case 3:
|
||
CopyOnlineStep3(c)
|
||
case 4:
|
||
CopyOnlineStep4(c)
|
||
default:
|
||
failed(c, "无效的步骤")
|
||
}
|
||
util.AddAdminLog(c, "文案自动化脚本", request)
|
||
}
|
||
|
||
func CopyOnlineStep2(c *gin.Context) {
|
||
// 关闭QA环境服务
|
||
time.Sleep(time.Second)
|
||
servers := util.GetAllServersByAppId(2) // AppId=2 QA环境
|
||
for _, server := range servers {
|
||
if server.Status != 1 {
|
||
continue
|
||
}
|
||
s := &model.Server{AppId: 2, ServerId: server.ServerId}
|
||
output, err := s.StopServer()
|
||
if err != nil {
|
||
// 如果错误信息包含"未启动",则忽略该错误
|
||
if !strings.Contains(output, "未启动") {
|
||
scritp_fail(c, "停止QA环境服务失败: "+err.Error())
|
||
return
|
||
}
|
||
}
|
||
}
|
||
success(c, map[string]interface{}{
|
||
"step": 3,
|
||
"label": "写入数据到QA环境",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
}
|
||
|
||
func CopyOnlineStep1(c *gin.Context) {
|
||
// mysqldump 复制数据库
|
||
// nodeInfo := util.GetNodeByName("devops")
|
||
// SshClient, err := util.NewSshClient(nodeInfo)
|
||
// if err != nil {
|
||
// scritp_fail(c, "连接devops节点失败: "+err.Error())
|
||
// return
|
||
// }
|
||
// defer SshClient.Close()
|
||
// cmd := "ansible-playbook /data/devops/playbook/script_copy_us_step_1.yml -i /data/devops/playbook/hosts"
|
||
// output, err := SshClient.RunCommand(cmd)
|
||
// if err != nil {
|
||
// scritp_fail(c, "执行复制数据库脚本step1失败: "+err.Error()+": "+output)
|
||
// return
|
||
// }
|
||
|
||
time.Sleep(time.Second)
|
||
success(c, map[string]interface{}{
|
||
"step": 2,
|
||
"label": "关闭QA环境服务",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
}
|
||
|
||
func CopyOnlineStep3(c *gin.Context) {
|
||
// 写入数据到QA环境
|
||
nodeInfo := util.GetNodeByName("devops")
|
||
SshClient, err := util.NewSshClient(nodeInfo)
|
||
if err != nil {
|
||
scritp_fail(c, "连接devops节点失败: "+err.Error())
|
||
return
|
||
}
|
||
defer SshClient.Close()
|
||
cmd := "ansible-playbook /data/devops/playbook/script_copy_us_step_2.yml -i /data/devops/playbook/hosts"
|
||
output, err := SshClient.RunCommand(cmd)
|
||
if err != nil {
|
||
scritp_fail(c, "执行复制数据库脚本step1失败: "+err.Error()+": "+output)
|
||
return
|
||
}
|
||
time.Sleep(time.Second)
|
||
success(c, map[string]interface{}{
|
||
"step": 4,
|
||
"label": "启动QA环境服务",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
|
||
}
|
||
|
||
func CopyOnlineStep4(c *gin.Context) {
|
||
// 启动QA环境服务
|
||
servers := util.GetAllServersByAppId(2) // AppId=2 QA环境
|
||
for _, server := range servers {
|
||
if server.Status == 1 {
|
||
continue
|
||
}
|
||
s := &model.Server{AppId: 2, ServerId: server.ServerId}
|
||
_, err := s.StartServer()
|
||
if err != nil {
|
||
scritp_fail(c, "启动QA环境服务失败: "+err.Error())
|
||
return
|
||
}
|
||
}
|
||
str := `
|
||
# US环境同步自动化脚本完成
|
||
<a>所有人</a>
|
||
`
|
||
alibaba.SendStandardMsg("US环境同步自动化脚本完成", str, "green")
|
||
time.Sleep(time.Second)
|
||
success(c, map[string]interface{}{
|
||
"step": -1,
|
||
"label": "脚本执行成功",
|
||
"tips": []string{},
|
||
"code": 0,
|
||
})
|
||
}
|