前端
后端部分我们基本上已经完成了,接下来我们需要编写前端,前端我们采用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