优秀的编程知识分享平台

网站首页 > 技术文章 正文

golang+gin+gorm实现一个短链服务(下)

nanyue 2024-08-11 20:40:09 技术文章 13 ℃

前端

后端部分我们基本上已经完成了,接下来我们需要编写前端,前端我们采用vue,如果没有vue基础的可以去看看基础教程,后期我有时间也会写一个vue的教程

创建vue项目

vue create short_chain_web


看到这样的内容代表vue创建成功

我们尝试运行它

看到如下的内容代表我们运行成功



我们访问一下浏览器

接下来我们要添加一些东西

 vue add router

添加vue自由的router

添加elementUI

vue add element

接着我们删除原有的home和about页面,写一个elementUI的按钮试试

修改app.vue的代码

删除views下面的home和about 在views下面新建一个Index.vue

<template>
  <div>
    <el-button type="primary">这是一个按钮</el-button>
  </div>
</template>

<script>
export default {
  name: "Index"
}
</script>

<style scoped>

</style>

修改router下的index.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "../views/Index"

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'Index',
        component: Index
    },
  
]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

接着我们尝试再次运行访问浏览器

可以看到我们的elementUI已经集成好了

接下来我们就开始写前端页面

首先写一个添加短链的页面

在views下面添加一个Add.vue

代码如下:

<template>
  <el-form ref="form" :model="add_form" label-width="80px">
    <el-form-item label="原始短链">
      <el-input v-model="add_form.original_link"></el-input>
    </el-form-item>
    <el-form-item label="映射短链">
      <el-input v-model="add_form.mapping_links"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">立即创建</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
export default {
  name: "Add",
  data(){
    return{
      add_form:{
        original_link:"",
        mapping_links:""
      }
    }
  },
  methods:{
    onSubmit(){

    }
  }
}
</script>

<style scoped>

</style>

在router下的index.js加上add的路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "../views/Index"
import Add from "@/views/Add";

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'Index',
        component: Index
    },
    {
        path: '/add',
        name: 'Add',
        component: Add
    }

]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

我们运行一下看看

接着当我们点击创建按钮的时候需要请求我们后端的添加接口

这里我们需要集成一个axios

yarn add axios

我们对axios进行一个简单的封装

src目录下新建一个request文件夹

在request下新建一个http.js

import axios from 'axios';

axios.defaults.timeout = 100000;
axios.defaults.headers.post['Content-Type'] = 'application/json; charset=UTF-8';
export function post(url, params) {
    return new Promise((resolve, reject) => {
        axios.post(url, params)
            .then(res => {
                resolve(res.data);
            })
            .catch(err => {
                console.log("进入err")
                reject(err.data)
            })
    });
}

继续新建一个api.js

import {post} from "@/request/http"

export const Add = obj => post("/api/add", obj)//添加短链

接下来我们需要设置请求代理

在根目录新建vue.config.js

module.exports = {
    devServer: {
        open: true,  //设置自动打开
        port: 8080,  // 这个是默认端口
        proxy: {
            '/api': {
                target: 'http://localhost:8000',  //设置反向代理链接
                changeOrigin: true,  //  是否跨域
                pathRewrite: {
                    '^/api': ''  //  重定向
                }
            }
        }
    }
}

我们返回继续修改index把接口接上

<template>
  <el-form ref="form" :model="add_form" label-width="80px">
    <el-form-item label="原始短链">
      <el-input v-model="add_form.original_link"></el-input>
    </el-form-item>
    <el-form-item label="映射短链">
      <el-input v-model="add_form.mapping_links"></el-input>
    </el-form-item>
    <el-form-item>
      <el-button type="primary" @click="onSubmit">立即创建</el-button>
    </el-form-item>
  </el-form>
</template>

<script>
import {Add} from "@/request/api"

export default {
  name: "Add",
  data() {
    return {
      add_form: {
        original_link: "",
        mapping_links: ""
      }
    }
  },
  methods: {
    onSubmit() {
      let data = this.add_form;
      Add(data).then(res => {
        if (res.code === 200) {
          this.$message.success("添加成功")
        } else {
          this.$message.error(res.msg)
        }
      })
    }
  }
}
</script>

<style scoped>

</style>

我们把我们之前写的后端运行起来,在运行前端

我们尝试添加数据

可以看到数据已经添加成功了,然后我们查一下数据库有没有生效

可以看到我们已经添加了一条数据

我们在多添加几条

好的 我们先添加三条

接着我们编写列表页面

在views下面新建一个List.vue

<template>

</template>

<script>
export default {
name: "List"
}
</script>

<style scoped>

</style>

增加路由

import Vue from 'vue'
import VueRouter from 'vue-router'
import Index from "../views/Index"
import Add from "@/views/Add";
import List from "@/views/List";

Vue.use(VueRouter)

const routes = [
    {
        path: '/',
        name: 'Index',
        component: Index
    },
    {
        path: '/add',
        name: 'Add',
        component: Add
    },
    {
        path: '/list',
        name: 'List',
        component: List
    }

]

const router = new VueRouter({
    mode: 'history',
    base: process.env.BASE_URL,
    routes
})

export default router

增加列表api接口

import {post} from "@/request/http"

export const Add = obj => post("/api/add", obj)//添加短链
export const List = obj => post("/api/list", obj)//查询短列表

回到list页面编写

<template>
  <el-table
      :data="tableData"
      style="width: 100%">
    <el-table-column
        prop="short_id"
        label="短链id"
        width="180">
    </el-table-column>
    <el-table-column
        prop="original_link"
        label="原始短链"
        width="180">
    </el-table-column>
    <el-table-column
        prop="mapping_links"
        label="映射网址">
    </el-table-column>
  </el-table>
</template>

<script>
import {List} from "@/request/api"

export default {
  name: "List",
  created() {
    this.get_short_list();
  },
  data() {
    return {
      tableData: []
    }
  },
  methods: {
    get_short_list() {
      List({}).then(res => {
        if (res.code === 200) {
          this.tableData = res.data.list;
        } else {
          this.$message.error(res.msg)
        }
      })
    }
  }
}
</script>

<style scoped>

</style>

我们运行试试看

除了这两个功能以外其实我们还有一个删除的功能

那么同样的我们先增加删除接口

import {post} from "@/request/http"

export const Add = obj => post("/api/add", obj)//添加短链
export const List = obj => post("/api/list", obj)//查询短链列表
export const Delete= obj => post("/api/delete", obj)//删除短链

我们继续返回修改list页面

<template>
  <el-table
      :data="tableData"
      style="width: 100%">
    <el-table-column
        prop="short_id"
        label="短链id"
        width="180">
    </el-table-column>
    <el-table-column
        prop="original_link"
        label="原始短链"
        width="180">
    </el-table-column>
    <el-table-column
        prop="mapping_links"
        label="映射网址">
    </el-table-column>
    <el-table-column
        fixed="right"
        label="操作"
        width="100">
      <template slot-scope="scope">
        <el-button type="danger" @click="delete_short(scope.row)">删除</el-button>
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
import {Delete, List} from "@/request/api"

export default {
  name: "List",
  created() {
    this.get_short_list();
  },
  data() {
    return {
      tableData: []
    }
  },
  methods: {
    get_short_list() {
      List({}).then(res => {
        if (res.code === 200) {
          this.tableData = res.data.list;
        } else {
          this.$message.error(res.msg)
        }
      })
    },
    delete_short(row) {
      let data = {
        short_id: row.short_id
      }
      Delete(data).then(res => {
        if (res.code == 200) {
          this.$message.success("删除成功")
          this.get_short_list()
        } else {
          this.$message.error(res.msg)
        }
      })
    }
  }
}
</script>

<style scoped>

</style>

我们运行看效果

我们尝试删除 q这条短链

可以看到我们的q已经删除成功了

最后呢我们的短链映射还没有实现 这里我们回到后端

找到之前我们的业务层 就是service

这里我们需要使用到重定向

package services

import (
	"github.com/gin-gonic/gin"
	"net/http"
	"short_chain/global"
	"short_chain/models/table"
	"short_chain/msg"
	"short_chain/utils"
)

type Service struct {
	table.ShortChainData
	Page int `json:"page"`
	Size int `json:"size"`
}

//添加短链
func (c *Service) Add(g *gin.Context) {
	c.ShortId = utils.GetUuid()
	err := c.ShortChainData.Add(&c.ShortChainData)
	if err != nil {
		msg.Error(g, "添加短链失败")
		return
	}
	msg.Success(g, "添加短链成功")
	return
}

//编辑短链短链
func (c *Service) Update(g *gin.Context) {
	shortQuery := table.ShortChainData{
		ShortId: c.ShortId,
	}
	err := shortQuery.QueryOne(&shortQuery)
	if err != nil {
		msg.Error(g, "编辑失败,短链不存在")
		return
	}
	shortQuery.MappingLinks = c.MappingLinks
	shortQuery.OriginalLink = c.OriginalLink
	db := global.Db
	err = db.Save(&shortQuery).Error
	if err != nil {
		msg.Error(g, "编辑短链失败")
		return
	}
	msg.Success(g, "编辑短链成功")
	return
}

//查询短链列表
func (c *Service) List(g *gin.Context) {
	list := new([]table.ShortChainData)
	var count int64
	db := global.Db
	db.Find(&list).Count(&count)
	db.Limit(c.Size).Offset((c.Page - 1) * c.Size).Order("created_at desc").Find(&list)
	data := make([]map[string]interface{}, len(*list))
	for k, v := range *list {
		item, _ := utils.ToMap(v, nil)
		data[k] = item
	}
	res := make(map[string]interface{})
	res["count"] = count
	res["list"] = data
	msg.Success(g, "查询成功", res)
	return
}

//删除短链
func (c *Service) Delete(g *gin.Context) {
	shortQuery := table.ShortChainData{
		ShortId: c.ShortId,
	}
	err := shortQuery.QueryOne(&shortQuery)
	if err != nil {
		msg.Error(g, "删除失败,短链不存在")
		return
	}
	db := global.Db
	err = db.Delete(&shortQuery).Error
	if err != nil {
		msg.Error(g, "删除短链失败")
		return
	}
	msg.Success(g, "删除成功")
	return
}

//短链映射
func (c *Service) Mapping(g *gin.Context) {
	shortQuery := table.ShortChainData{
		OriginalLink: c.OriginalLink,
	}
	err := shortQuery.QueryOne(&shortQuery)
	if err != nil {
		msg.Error(g, "短链不存在")
		return
	}
	g.Redirect(http.StatusMovedPermanently, shortQuery.MappingLinks)
}

在回到控制层修改控制层代码

package controllers

import (
	"github.com/gin-gonic/gin"
	"short_chain/msg"
	"short_chain/services"
)

//添加短链
func Add(g *gin.Context) {
	var dataService services.Service
	err := g.ShouldBindJSON(&dataService)
	if err != nil {
		msg.Error(g, "请求参数错误:"+err.Error())
		return
	}
	if dataService.MappingLinks == "" {
		msg.Error(g, "原始链接不能为空")
		return
	}
	if dataService.OriginalLink == "" {
		msg.Error(g, "隐射链接不能为空")
		return
	}
	dataService.Add(g)
	return
}

//编辑短链
func Update(g *gin.Context) {
	var dataService services.Service
	err := g.ShouldBindJSON(&dataService)
	if err != nil {
		msg.Error(g, "请求参数错误:"+err.Error())
		return
	}
	if dataService.MappingLinks == "" {
		msg.Error(g, "原始链接不能为空")
		return
	}
	if dataService.OriginalLink == "" {
		msg.Error(g, "隐射链接不能为空")
		return
	}
	if dataService.ShortId == "" {
		msg.Error(g, "短链id不能为空")
		return
	}
	dataService.Update(g)
	return
}

//查询短链列表
func List(g *gin.Context) {
	var dataService services.Service
	err := g.ShouldBindJSON(&dataService)
	if err != nil {
		msg.Error(g, "请求参数错误:"+err.Error())
		return
	}
	if dataService.Page == 0 {
		dataService.Page = 1
	}
	if dataService.Size == 0 {
		dataService.Size = 10
	}
	dataService.List(g)
	return
}

//删除短链
func Delete(g *gin.Context) {
	var dataService services.Service
	err := g.ShouldBindJSON(&dataService)
	if err != nil {
		msg.Error(g, "请求参数错误:"+err.Error())
		return
	}
	if dataService.ShortId == "" {
		msg.Error(g, "短链id不能为空")
		return
	}
	dataService.Delete(g)
	return
}
//映射短链
func Mapping(g *gin.Context)  {
	originalLink := g.Param("original_link")
	var dataService services.Service
	dataService.OriginalLink=originalLink
	dataService.Mapping(g)
}

修改router路由

package router

import (
	"github.com/gin-gonic/gin"
	"short_chain/controllers"
)

func ShortRouter(r *gin.Engine) {
	r.POST("/add", controllers.Add)
	r.POST("/list", controllers.List)
	r.POST("/update", controllers.Update)
	r.POST("/delete", controllers.Delete)
	r.GET("/short/:original_link",controllers.Mapping)
}

我们访问浏览器:http://localhost:8000/short/qwe

就会发现链接被重定向到gitee.com

Tags:

最近发表
标签列表