前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用go+vue快速开发一个web系统

利用go+vue快速开发一个web系统

作者头像
IT不难
发布2024-06-01 09:12:02
1040
发布2024-06-01 09:12:02
举报
文章被收录于专栏:IT不难技术家园IT不难技术家园

前言

为什么选择go+vue,博主一直没有接触过java开发。上学时学的东西忘的差不多了。系统功能很简单,但是要部署在客户的服务器上。go的一功能是将代码和静态资源打包成一个二进制执行文件,比较符合我的胃口。心心念一直想入坑go开发。

总体设计

系统很简单,只有两个页面。一个登录页面,登录后到达主页面。主页面包括一个文件上传组件,一个table组件。table组件,记录上传处理记录,下载处理结果。采用vue开发。后端接口采用go语言开发。

前端

登录页面
登录页面
功能页面
功能页面

后端

采用go语言开发后端接口,接口包含如下四个。同时还有其他一些细节,如将数据库连接,用户密码,程序监听端口等设置成可配置,配置在运行文件同目录的.env文件内

  • 文件下载接口
  • 文件上传接口
  • 任务信息列表
  • 登录接口

开发过程

大部分是chatgpt的功劳,在chatgpt回复的基础上修改。一开始一个main.go到底。后续将不同功能拆成多个文件。

和chatgpt交流
和chatgpt交流

功能代码

main函数

实现所有路由,加载静态资源,监听端口可配置,记录日志,中断程序保存日志

代码语言:javascript
复制
func main() {
    // 日志记录
    initLogger()

    // 捕获 SIGINT 信号(Ctrl+C)
    c := make(chan os.Signal, 1)
    signal.Notify(c, os.Interrupt, syscall.SIGINT)

    go func() {
        <-c
        logger.Println("Received SIGINT. Flushing logs and exiting.")
        closeLogger()
        os.Exit(0)
    }()

    // 路由
    r := mux.NewRouter()

    // 处理文件下载路由
    r.HandleFunc("/api/download", downloadHandler)

    // 处理文件上传路由
    r.HandleFunc("/api/upload", uploadHandler)

    // 新增处理读取任务信息的路由
    r.HandleFunc("/api/readtasks", readTasksHandler)

    // 添加处理登录请求的路由
    r.HandleFunc("/api/login", loginHandler).Methods("POST")

    // 设置静态文件服务
    statikFS, err := fs.New()
    if err != nil {
        log.Fatal(err)
    }
    r.PathPrefix("/").Handler(http.StripPrefix("/", http.FileServer(statikFS)))

     // 加载 .env 文件中的环境变量
        if err := godotenv.Load(); err != nil {
            logger.Fatal("加载.env失败")
            return
        }
    lport := os.Getenv("LISTEN_PORT")
    logger.Printf("Server is listening on port %s...", lport)
    log.Fatal(http.ListenAndServe(":"+lport, r))
}

日志函数

日志同时记录到文件

代码语言:javascript
复制
func initLogger() {
    var err error
    logFile, err = os.OpenFile("smsman.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
    if err != nil {
        log.Fatal(err)
    }

    logger = log.New(io.MultiWriter(os.Stdout, logFile), "LOG: ", log.Ldate|log.Ltime|log.Lshortfile)
}

func closeLogger() {
    if logFile != nil {
        logFile.Close()
    }
}

下载函数

实现处理结果下载功能

代码语言:javascript
复制
func downloadHandler(w http.ResponseWriter, r *http.Request) {
    filename := r.URL.Query().Get("filename") // 获取请求中的文件名参数

    filePath := "./result/" + filename // 构建文件路径

    // 打开文件
    file, err := os.Open(filePath)
    if err != nil {
        http.Error(w, "文件未找到", http.StatusNotFound)
        return
    }
    defer file.Close()

    // 设置响应头
    w.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(filePath))
    w.Header().Set("Content-Type", "application/octet-stream")
    fileInfo, _ := file.Stat()
    w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))

    // 传输文件内容到 ResponseWriter
    _, err = io.Copy(w, file)
    if err != nil {
        http.Error(w, "文件传输失败", http.StatusInternalServerError)
        return
    }
}

登录认证函数

实现简单的登录认证

代码语言:javascript
复制
func loginHandler(w http.ResponseWriter, r *http.Request) {
    // 解析请求中的用户名和密码
    r.ParseForm()
    username := r.Form.Get("username")
    passwd := r.Form.Get("password")

    // 加载 .env 文件中的环境变量
    if err := godotenv.Load(); err != nil {
        logger.Fatal("加载.env失败")
        http.Error(w, err.Error(), http.StatusInternalServerError)
    return
    }
    user := os.Getenv("SMSUSER")
    password := os.Getenv("SMSPWD")

    // 验证用户名和密码
    if username == user && passwd == password {
        response := LoginResponse{
            Success: true,
            Username: username,
        }

        jsonResponse, err := json.Marshal(response)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusOK)
        w.Write(jsonResponse)

    } else {
        response := LoginResponse{
            Success: false,
            Username: username,
        }

        jsonResponse, err := json.Marshal(response)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }

        w.Header().Set("Content-Type", "application/json")
        w.WriteHeader(http.StatusOK)
        w.Write(jsonResponse)
    }
}

前端页面开发

前端页面开发采用vue,这里用到了 viewui, 下载他们的demo,然后改造。

主要代码文件
主要代码文件

Home.vue

Home.vue中加载了两个组件,一个是文件上传组件Fupload.vue,另一个是Mtable.vue。记录一下加载方法。

代码语言:javascript
复制
    import Fupload from '@/components/Fupload.vue'
    import Mtable from '@/components/Mtable.vue'
    export default {
        name: 'HomeView',
        components: {
          Fupload,
          Mtable
        },
        data () {
            return {
                split: 0.4
            }
        },
    }

Mtable.vue

Mtable.vue 主要注意每个2s刷新数据操作

代码语言:javascript
复制
      created() {
            this.fetchData();

            // 每2秒刷新数据
            setInterval(() => {
                this.fetchData();
            }, 2000);
        },
        methods: {
            async fetchData() {
                try {
                    const response = await axios.get('/api/readtasks');
                    this.data = response
                        .data; // Assuming the response directly contains the array of task objects
                } catch (error) {
                    console.error('Error fetching data:', error);
                }
            },
            getStatusColor(status) {
                return {
                    'color-green': status === '进行中',
                    'color-red': status === '已完成'
                };
            }
        }

登录检测

默认访问Home.vue,同时检测是否登录。如果没有登录的话,跳转到Login.vue

代码语言:javascript
复制
// router/index.js
router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // 检查用户是否已登录,这里假设 isAuthenticated 是存储登录状态的变量
    const isAuthenticated = store.state.isAuthenticated;
    if (!isAuthenticated) {
      next('/login'); // 如果未登录,则重定向到登录页面
    } else {
      next();
    }
  } else {
    next(); // 不需要登录认证的页面直接放行
  }
})

// store/index.js
// 存储登录状态
export default createStore({
  state: {
      isAuthenticated: false // 初始登录状态为未认证
  },
  getters: {
  },
  mutations: {
      setAuthentication(state, isAuthenticated) {
          state.isAuthenticated = isAuthenticated;
      }
  },
  actions: {
      login({ commit }) {
          // 模拟登录成功,设置登录状态为 true
          commit('setAuthentication', true);
          
          localStorage.setItem('isAuthenticated', true);
        },
        logout({ commit }) {
          // 登出操作,设置登录状态为 false
          commit('setAuthentication', false);
        }
  },
  modules: {
  }
})
  • Login.vue,登录功能的实现
代码语言:javascript
复制
    import axios from 'axios';
    import { mapActions } from 'vuex';
    import router from '../router'; // 引入 Vue Router
    export default {
        data() {
            return {
                username:'',
                password:''
            }
        },
        methods: {
            ...mapActions(['login']),
            
            async handleSubmit(valid, {
                username,
                password
            }) {
                if (valid) {
                    try {
                        const params = new URLSearchParams();
                        params.append('username', username);
                        params.append('password', password);
                        
                        const config = {
                            headers: {
                                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
                            }
                        };
                        const response = await axios.post('/api/login', params, config);
                
                        //console.log(response)
                        if (response.data.success) {
                            this.$Modal.success({
                                title: '登录成功',
                                content: '欢迎回来,' + username
                            });
                            this.login();
                            router.push('/'); // 登录成功后跳转到 /home 页面
                        } else {
                            this.$Modal.error({
                                title: '登录失败',
                                content: '用户名或密码错误,请重试'
                            });
                        }
                    } catch (error) {
                        console.error(error);
                        this.$Modal.error({
                            title: '登录失败',
                            content: '出现意外错误,请稍后再试'
                        });
                    }
                }
            }
        }
    }

程序打包

mac安装go-statik, 然后打包

代码语言:javascript
复制
brew install go-statik
statik -src=./dist/

#man - centos
GOOS=linux GOARCH=amd64 go build -o smsman_linux_amd64 main.go
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024年05月31日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 总体设计
    • 前端
      • 后端
      • 开发过程
        • 功能代码
          • main函数
          • 日志函数
          • 下载函数
          • 登录认证函数
        • 前端页面开发
          • Home.vue
          • Mtable.vue
          • 登录检测
      • 程序打包
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档