This commit is contained in:
w-mj 2023-02-13 23:34:22 +08:00
parent 21401650f1
commit 3fbff92ed8
No known key found for this signature in database
GPG Key ID: 3A2CB5BE2F835897
5 changed files with 117 additions and 9 deletions

View File

@ -31,6 +31,9 @@ func main() {
r.StaticFS("/static", http.FS(fp))
r.GET("/app", m.JWTAuthMiddleware, m.AppPage)
r.POST("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.PUT("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.DELETE("/app", m.JWTAuthMiddleware, m.CreateUpdateDeleteApp)
r.GET("/login/:username", Test)
err := r.Run()
if err != nil {

View File

@ -11,7 +11,7 @@ type AppModel struct {
SvcName string
}
func (AppModel) TableName() string {
func (*AppModel) TableName() string {
return "app"
}
@ -21,3 +21,21 @@ func GetApps(username string) []AppModel {
db.Where("user_name = ?", username).Find(&ans)
return ans
}
func (a *AppModel) Update() error {
db := DB()
db.Save(a)
return nil
}
func (a *AppModel) Create() error {
db := DB()
db.Create(a)
return nil
}
func (a *AppModel) Delete() error {
db := DB()
db.Delete(a, a.Id)
return nil
}

View File

@ -2,6 +2,7 @@ package k8s_manager
import (
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"net/http"
)
@ -18,3 +19,31 @@ func AppPage(c *gin.Context) {
}
c.HTML(http.StatusOK, "app_view.html", vm)
}
func CreateUpdateDeleteApp(c *gin.Context) {
app := &AppModel{}
err := c.BindJSON(app)
if err != nil {
log.WithError(err).Error("AddApp")
c.JSON(http.StatusBadRequest, gin.H{"msg": "Cannot get data."})
} else {
username := c.MustGet("username").(string)
if username != app.UserName {
c.JSON(http.StatusUnauthorized, gin.H{"msg": "user error."})
return
}
if c.Request.Method == http.MethodPost {
err = app.Create()
} else if c.Request.Method == http.MethodPut {
err = app.Update()
} else if c.Request.Method == http.MethodDelete {
err = app.Delete()
}
if err != nil {
log.WithError(err).Error("CreateUpdateDeleteApp", c.Request.Method)
c.JSON(http.StatusInternalServerError, gin.H{"msg": "DB error."})
} else {
c.JSON(http.StatusOK, gin.H{"msg": "ok"})
}
}
}

2
static/js/axios.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -3,6 +3,7 @@
<head>
<link href="static/css/bootstrap.min.css" rel="stylesheet">
<script src="static/js/bootstrap.bundle.min.js"></script>
<script src="static/js/axios.min.js"></script>
<meta charset="UTF-8">
<title>应用管理</title>
</head>
@ -39,6 +40,7 @@
{{ range $i, $v := .Apps }}
<tr id="app-list-{{ $v.Id }}">
<td> {{ inc $i }}</td>
<td class="app-field-id" style="display: none;"> {{ $v.Id }}</td>
<td class="app-field-name"> {{ $v.AppName }}</td>
<td class="app-field-comment"> {{ $v.Comment }}</td>
<td class="app-field-image"> {{ $v.Image }}</td>
@ -47,7 +49,7 @@
<td>
<div class="btn-group">
<button class="btn btn-primary" onclick="showModal('app-list-{{ $v.Id }}')">修改</button>
<button class="btn btn-danger">删除</button>
<button class="btn btn-danger" onclick="deleteApp('{{ $v.Id }}')">删除</button>
</div>
</td>
</tr>
@ -70,26 +72,31 @@
</div>
<div class="modal-body">
<input type="text" id="app-id" class="form-control" style="display: none;" disabled/>
<input type="text" id="app-username" class="form-control" style="display: none;" disabled
value="{{ .Username }}"/>
<div class="row">
<div class="col-auto">
<label for="app-name" class="form-label">应用名</label>
<input type="text" id="app-name" class="form-control" placeholder="只能为字母、数字和下划线" />
<input type="text" id="app-name" class="form-control"
placeholder="只能为字母、数字和下划线"/>
</div>
<div class="col-auto">
<label for="app-image" class="form-label">镜像</label>
<input type="text" id="app-image" class="form-control" placeholder="Docker镜像名" />
<input type="text" id="app-image" class="form-control" placeholder="Docker镜像名"/>
</div>
</div>
<div class="row">
<label for="app-cmd" class="form-label">启动命令</label>
<input type="text" id="app-cmd" class="form-control" placeholder="启动命令,可选" />
<input type="text" id="app-cmd" class="form-control" placeholder="启动命令,可选"/>
</div>
<div class="row">
<label for="app-env" class="form-label">环境变量</label>
<input type="text" id="app-env" class="form-control" placeholder="环境变量,可选" />
<input type="text" id="app-env" class="form-control" placeholder="环境变量,可选"/>
</div>
<div class="row">
@ -100,11 +107,20 @@
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary">保存</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="updateApp()">保存
</button>
</div>
</div>
</div>
</div>
<div class="toast d-flex align-items-center top-0 end-0" id="success-toast">
<div class="toast-body">
<p id="toast-content"></p>
</div>
<button type="button" class="btn-close ms-auto me-2" data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</body>
@ -126,7 +142,7 @@
}
function clearModalField() {
const id_list = ["app-name", "app-image", "app-cmd", "app-env", "app-comment"]
const id_list = ["app-id", "app-name", "app-image", "app-cmd", "app-env", "app-comment"]
for (const k of id_list) {
document.getElementById(k).value = ""
}
@ -146,5 +162,45 @@
(new bootstrap.Modal("#edit-modal")).show()
}
function showToast(e) {
document.getElementById("toast-content").innerHTML = e.msg
t = new bootstrap.Toast(document.getElementById("success-toast"))
console.log(t)
t.show()
}
function updateApp() {
const id_list = ["app-id", "app-name", "app-username", "app-image", "app-cmd", "app-env", "app-comment"]
const json_key_list = ["Id", "AppName", "UserName", "Image", "Command", "Env", "Comment"]
let appData = {}
for (let k in id_list) {
appData[json_key_list[k]] = document.getElementById(id_list[k]).value
}
if (appData['Id']) {
appData['Id'] = parseInt(appData['Id'])
axios.put("app", appData).then(e => {
showToast(e.data)
})
} else {
appData['Id'] = null
axios.post("app", appData).then(e => {
console.log(e)
showToast(e.data)
});
}
}
function deleteApp(id) {
axios.delete("app", {
"data": {
Id: parseInt(id),
Username: document.getElementById("app-username").value
}
}).then(e => {
console.log(e.data)
showToast(e.data)
})
}
</script>
</html>