golang web页面动态加载实现

  

           Go 的web页面动态加载实现。

   1. 在MySQL中添加表项 users,构造多条数据。

         CREATE TABLE IF NOT EXISTS users(
               id INT UNSIGNED AUTO_INCREMENT,
               username VARCHAR(255) NOT NULL,
               password VARCHAR(255) NOT NULL,
               create_at INT(10) UNSIGNED NOT NULL,
               PRIMARY KEY (id)
            )ENGINE=INNODB DEFAULT CHARSET=UTF8;

    main.go  如下

package main

import (
    "bytes"
    _ "crypto/tls"
    "database/sql"
    "encoding/json"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
    "github.com/gorilla/mux"
    "html/template"
    "log"
    "net/http"
    "strconv"
    "time"
)

const (
    DB_ADDR_PORT  = "localhost:3307"
    DB_LOGIN_USER = "root"
    DB_LOGIN_PASS = "usbw"
    DB_TAB        = "test"
    PAGE_SIZE     = 2
)

var DBObj *sql.DB

type UserList struct {
    UsersList []User
    Ajax      bool
    Total     int
    Index     int
    PageSize  int
}

type User struct {
    Id       int
    Username string
    Password string
    CreateAt uint
}

func dbInit() {
    dsn := fmt.Sprintf("%s:%s@(%s)/%s", DB_LOGIN_USER, DB_LOGIN_PASS, DB_ADDR_PORT, DB_TAB)
    db, err := sql.Open("mysql", dsn)

    if err != nil {
        log.Fatalf("connect db failed %v", err)
        return
    }

    if err := db.Ping(); err != nil {
        log.Fatalf("ping db failed %v", err)
        return
    }

    DBObj = db

    //fmt.Printf("db reachable, %T\n", db)
}

func dbFetch(id int) (*User, bool) {
    user := new(User)

    query := `SELECT id, username, password, create_at FROM users WHERE id=?`
    err := DBObj.QueryRow(query, id).Scan(&user.Id, &user.Username, &user.Password, &user.CreateAt)

    if err != nil {

        return &User{}, false
    }

    return user, true
}

func dbFetchallPerpage(index int) (*UserList, int, bool) {

    total := 0
    query := `SELECT COUNT(*) FROM users WHERE 1=1`
    err := DBObj.QueryRow(query).Scan(&total)

    if err != nil {
        return &UserList{}, total, false
    }

    if total == 0 {
        return &UserList{}, total, false
    }

    query = `SELECT id, username, password, create_at FROM users WHERE id < ? LIMIT ?, ?`
    rows, err := DBObj.Query(query, 20, (index-1)*PAGE_SIZE, PAGE_SIZE)
    if err != nil {
        return &UserList{}, total, false
    }

    defer rows.Close()

    var userlist UserList
    for rows.Next() {
        u := User{}
        err := rows.Scan(&u.Id, &u.Username, &u.Password, &u.CreateAt)
        if err != nil {
            continue
        }

        userlist.UsersList = append(userlist.UsersList, u)
    }

    err = rows.Err()

    if err != nil {

        return &UserList{}, total, false
    }

    return &userlist, total, true
}

func (user *User) Print(s string) string {
    timeObj := time.Unix(int64(user.CreateAt), 10)

    var buffer bytes.Buffer

    buffer.WriteString(s)

    buffer.WriteString(strconv.Itoa(user.Id))

    buffer.WriteString("  ")

    buffer.WriteString(timeObj.Format("2006-01-02 15:04:05"))

    //fmt.Printf("<%s>\n", buffer.String())

    return buffer.String()
}

func GetUserById(idStr string) string {

    id, _ := strconv.Atoi(idStr)

    respFields := make(map[string]string)
    respFields["rv"] = "0"

    fmt.Println("after fetch ", idStr)
    if user, rv := dbFetch(id); rv {
        respFields["rv"] = "1"
        respFields["username"] = user.Username
        respFields["id"] = strconv.Itoa(user.Id)
    }

    jsonResp, _ := json.Marshal(respFields)

    return string(jsonResp)
}

func AllUserScroll(w http.ResponseWriter, r *http.Request) {

    fmt.Println("AllUsersScroll")

    r.ParseForm()

    page, _ := strconv.Atoi(r.FormValue("page"))
    ajax := (r.FormValue("ajax") == "1")

    //fmt.Printf("r %v %v\n", page, ajax)

    page = func(p int) int {
        if p > 1 {
            return p
        }
        return 1
    }(page)

    t := template.Must(template.ParseFiles("templates/scroll_load.html"))

    fmt.Println("after fetch")
    if Users, total, rv := dbFetchallPerpage(page); rv {
        Users.Ajax = ajax
        Users.Total = total
        Users.PageSize = PAGE_SIZE
        Users.Index = page

        t.Execute(w, Users)
        return
    }

    t.Execute(w, []byte("failed to get user"))
}

func EditUser(w http.ResponseWriter, r *http.Request) {

    fmt.Println("in edit")

    err := r.ParseForm()
    if err != nil {
        fmt.Println(err.Error)
    }

    vars := mux.Vars(r)
    id := vars["idStr"]

    name := r.FormValue("name")

    fmt.Println(name, id)

    res, err := DBObj.Exec("UPDATE users SET username=? WHERE id=?", name, id)

    fmt.Println(res)

    if err != nil {
        fmt.Println(err.Error)
    }

    respFields := make(map[string]string)

    respFields["rv"] = "1"
    respFields["msg"] = "success"

    jsonResp, _ := json.Marshal(respFields)

    w.Header().Set("Content-Type", "application/json")

    fmt.Fprintf(w, "%s", string(jsonResp))
}

func GetUser(w http.ResponseWriter, r *http.Request) {

    vars := mux.Vars(r)
    idStr := vars["idStr"]

    t := template.Must(template.ParseFiles("templates/detail.html"))

    id, _ := strconv.Atoi(idStr)

    fmt.Println("after fetch")
    if user, rv := dbFetch(id); rv {

        t.Execute(w, user)
        return
    }

    t.Execute(w, []byte("failed to get user"))
}

func RedireIndex(w http.ResponseWriter, r *http.Request) {

    http.Redirect(w, r, "/users", 301)
}

func APIUser(w http.ResponseWriter, r *http.Request) {

    vars := mux.Vars(r)
    idStr := vars["idStr"]

    id, err := strconv.Atoi(idStr)
    if err != nil {
        http.Error(w, http.StatusText(404), http.StatusNotFound)
        return
    }

    fmt.Println("after fetch")
    if user, rv := dbFetch(id); rv {
        APIOutput, err := json.Marshal(user)
        fmt.Println(string(APIOutput))
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        fmt.Fprintf(w, string(APIOutput))

        return
    }

    http.Error(w, http.StatusText(401), http.StatusForbidden)
}

func main() {

    dbInit()

    r := mux.NewRouter()

    r.HandleFunc("/", RedireIndex)

    userrouter := r.PathPrefix("/users").Subrouter()

    userrouter.HandleFunc("", AllUserScroll).Methods("GET")

    userrouter.HandleFunc("/{idStr:[0-9]+}", GetUser).Methods("GET")

    apirouter := r.PathPrefix("/api").Subrouter()

    apirouter.HandleFunc("/{idStr:[0-9]+}", APIUser).Methods("GET")

    apirouter.HandleFunc("/editUser/{idStr:[0-9]+}", EditUser).Methods("POST")

    http.ListenAndServe(":8080", r)

}

 

  2. 页面 scroll_load.html  内容如下:

{{if not .Ajax}}
<!DOCTYPE html>
<html lang="en">
    <head>    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="format-detection" content="telephone=no, address=no">
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <meta name="apple-touch-fullscreen" content="yes" />
    <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />                
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />        
    <title>scrollable loading</title>
    <style>
        html,
        body {
            margin: 0px 3px;
        }

        html {
            background: #EDF0F3;
            height: 100%;
        }
        /* 浏览更多 */
        .show-more {
            text-align: center;
            margin: 10px 0 65px 0px;
        }

        .show-more a {
            display: inline-block;
            color: #008000;
            font-size: 13px;
            text-shadow: 0 1px 1px #fff;
            box-shadow: 0 1px 1px 0 rgba(0,0,0,0.2) inset;
            padding: 8px 50px;
            background: #ebebeb;
            text-decoration: none;
            border-radius: 5px;
        }        

    </style>

    </head>
    <body>
        <script src="https://code.jquery.com/jquery-3.6.0.min.js"
         integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
         crossorigin="anonymous">
        </script>
<h1>User list</h1>
<div id="list">
{{end}}

{{range $k, $v := .UsersList}}
    <div>
        <div>{{$k}}  => {{$v}}</div>
        <div>{{.Print "--->"}}</div>
            <div class="edit">
                <form onsubmit="return edit(this, {{.Id}})">
                    <input type="text" class="name_{{.Id}}" name="name" value="{{.Username}}" />
                    <input type="submit" value="Edit"/>
                </form>
            </div>
    </div>    
{{end}}

{{if not .Ajax}}
</div>

<div id="result"></div>
   {{if gt .Total .PageSize}}
   <div style="margin: 40px 0px; text-align: center;">
    <div class="show-more"><a href="javascript:void(0);" style="color: #000;" onclick="loadPage('{{.Index}}', 'list')" class="img-rounded" id="pager">浏览更多</a>
    </div>
   </div>
   {{end}}
</body>

<script type="text/javascript">
var all_done = false

function edit(that, id){
    var name = $(".name_" + id).val()

    var url = '/api/editUser/' + id
    var param = {}
    param.name = name

    $.post(url, param, function(res){
         if (res.rv == '1'){

             $('#result').html('success')
         } else {
            console.log(res)
        }
    }, "json")
    return false;        
}

function loadPage(pindex, container) {
    if (all_done){
        return;
    }
    pindex = parseInt(pindex) + 1;

    $('#pager').html('加载中...');

    $.get(location.href, {'page' : pindex, 'ajax' : "1"}, function(html){
        
        if (html.indexOf('name_') > -1) {

            $('#'+container).append(html);
            $('#pager').get(0).onclick = function(){
                loadPage(pindex, container);
            }
            $('#pager').html("浏览更多");
        } else {
            all_done = true;            
            $('#pager').html('已经显示全部');
        }
    });
}            
</script>
</html>
{{end}}

 

     3.     显示如下,在点击 “浏览更多” 之后,List 动态添加载到页面。 

 

posted on 2023-05-12 12:42  wallywl  阅读(145)  评论(0)    收藏  举报