首页
美图
服务
付费
树洞
云主机
推荐
邻居
支付
开发
书单
更多
我的足迹
罗盘时钟
圈小猫
工作打分
给我留言
本站统计
推荐
M商城
欣悦云店
txt阅读器
VPS监控
证书监控
网址导航
在线工具
Search
1
docker和docker-compose一键安装脚本
5,138 阅读
2
采用Prometheus+Grafana 监控H3C交换机状态
4,614 阅读
3
WooCommerce对接第三方支付插件开发
4,229 阅读
4
grafana的Dashboard面板添加阈值报警
2,881 阅读
5
服务器(vps)性能测试脚本汇总
2,831 阅读
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
Search
标签搜索
django
python
运维工具
支付对接
电商平台
Joe主题
docker
wordpress
woocommerce
支付通道
zabbix
蓝鲸智云
运维
grafana
监控
运维知识
typecho
php
mysql
nginx
行云流水
累计撰写
324
篇文章
累计收到
363
条评论
首页
栏目
虚拟化
数据库
运维
基础知识
监控预警
数据展示
运维工具
web安全
系统服务
开发
python
php
java
shell
go
项目
博客
电商
工具
娱乐
综合
VPS相关
规范文档
知识总结
经验分享
读书笔记
关于
页面
美图
服务
树洞
云主机
邻居
支付
书单
给我留言
本站统计
推荐
M商城
txt阅读器
网址导航
搜索到
2
篇与
的结果
2024-05-31
利用go+vue快速开发一个web系统
前言为什么选择go+vue,博主一直没有接触过java开发。上学时学的东西忘的差不多了。系统功能很简单,但是要部署在客户的服务器上。go的一功能是将代码和静态资源打包成一个二进制执行文件,比较符合我的胃口。心心念一直想入坑go开发。总体设计系统很简单,只有两个页面。一个登录页面,登录后到达主页面。主页面包括一个文件上传组件,一个table组件。table组件,记录上传处理记录,下载处理结果。采用vue开发。后端接口采用go语言开发。前端{card-default label="登录页面" width="75%"}{/card-default}{card-default label="功能页面" width="75%"}{/card-default}后端采用go语言开发后端接口,接口包含如下四个。同时还有其他一些细节,如将数据库连接,用户密码,程序监听端口等设置成可配置,配置在运行文件同目录的.env文件内文件下载接口文件上传接口任务信息列表登录接口开发过程大部分是chatgpt的功劳,在chatgpt回复的基础上修改。一开始一个main.go到底。后续将不同功能拆成多个文件。{card-default label="和chatgpt交流" width="75%"}{/card-default}功能代码main函数实现所有路由,加载静态资源,监听端口可配置,记录日志,中断程序保存日志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)) }日志函数日志同时记录到文件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() } }下载函数实现处理结果下载功能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 } }登录认证函数实现简单的登录认证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,然后改造。{card-default label="目录结构" width="75%"}{/card-default}Home.vueHome.vue中加载了两个组件,一个是文件上传组件Fupload.vue,另一个是Mtable.vue。记录一下加载方法。<template> <div class="layout-base"> <Layout> <Header class="layout-header">短信签名处理后台</Header> <Content class="layout-content"> <Card style="width:100%"> <template #title> <p style="text-align: left; margin: 0;">文件上传</p> </template> <Fupload/> </Card> <Divider>---</Divider> <Card style="width:100%;"> <template #title> <p style="text-align: left; margin: 0;">上传记录</p> </template> <Mtable/> </Card> </Content> </Layout> </div> </template> <script> import Fupload from '@/components/Fupload.vue' import Mtable from '@/components/Mtable.vue' export default { name: 'HomeView', components: { Fupload, Mtable }, data () { return { split: 0.4 } }, } </script>Mtable.vueMtable.vue 主要注意每个2s刷新数据操作 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// 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,登录功能的实现 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, 然后打包brew install go-statik statik -src=./dist/ #man - centos GOOS=linux GOARCH=amd64 go build -o smsman_linux_amd64 main.go
2024年05月31日
252 阅读
0 评论
0 点赞
2022-07-11
软件开发5条核心原则
软件=程序+数据+文档+(服务);程序=数据结构+算法
2022年07月11日
201 阅读
0 评论
1 点赞