欢迎来到 WebGIS 入门系列的第十四篇文章!在本文中,我们将介绍如何利用 Node.js 来实现 WebGIS 系统开发时后台接口的开发知识,其中包括数据库初始化、数据表创建、后端接口程序初始化、Vue 项目中路由配置等。
调整 Vue 项目路由配置
调整 src 目录下 App.vue 组件中的代码,配置菜单跳转地址及 router-view 信息:
<template><header><h1>我的 WebGIS 应用</h1><nav><ul><li><a href="/">首页</a></li><li><a href="/map">地图</a></li><li><a href="/data">数据管理</a></li></ul></nav></header><main><router-view></router-view></main></template><script setup lang="ts"></script><style>// ......</style>
在 src/views 目录下分别新建 MapView.vue 和 DataManageView.vue 组件:
// MapView.vue<template><main class="map-main"><MapView /></main></template><script setup lang="ts">import MapView from '@/components/MapView.vue'</script><style>.map-main {width: 100%;height: 100%;}</style>// DataManageView.vue<template><main class="data-main"><DataManage /></main></template><script setup lang="ts">import DataManage from '@/components/DataManage.vue'</script><style>.data-main {width: 100%;height: 100%;}</style>
在 src/components 目录下新建 DataManage.vue 组件:
<template><div class="data-manage">data manage</div></template><script setup lang="ts"></script><style scoped>.data-manage {width: 100%;height: 100%;}</style>
优化调整 src/router 目录下的路由配置信息:
import { createRouter, createWebHistory } from 'vue-router'import HomeView from '../views/HomeView.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: HomeView},{path: '/map',name: 'map',component: () => import('../views/MapView.vue')},{path: '/data',name: 'data',component: () => import('../views/DataManageView.vue')}]})export default router
界面预览如下所示:
![图片[1]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_1.gif)
优化 DataManage 组件
在 src/components 目录下的 DataManage.vue 组件中拷贝下面代码,完善数据管理界面:
<template><div class="data-manage"><div class="data-manage-form"><div class="data-manage-header"><el-alert title="填入以下信息后进行数据入库" type="info" show-icon /></div><el-form :model="form" label-width="auto" style="max-width: 600px"><el-form-item label="名称"><el-input v-model="form.name" /></el-form-item><el-form-item label="区域"><el-select v-model="form.region" placeholder="请选择"><el-optionv-for="item in regionData":key="item.value":label="item.label":value="item.value"/></el-select></el-form-item><el-form-item label="日期"><el-date-picker v-model="form.date" type="date" placeholder="请选择" style="width: 50%" /></el-form-item><el-form-item label="已激活"><el-switch v-model="form.delivery" /></el-form-item><el-form-item label="激活类型"><el-checkbox-group v-model="form.type"><el-checkboxv-for="item in typeData":key="item.value":label="item.value":name="item.value">{{ item.label }}</el-checkbox></el-checkbox-group></el-form-item><el-form-item label="资源"><el-radio-group v-model="form.resource"><el-radio v-for="item in resourceData" :key="item.value" :label="item.value">{{item.label}}</el-radio></el-radio-group></el-form-item><el-form-item label="备注"><el-input v-model="form.desc" type="textarea" /></el-form-item><el-form-item><el-button type="primary" @click="onSubmit">提交</el-button><el-button>取消</el-button></el-form-item></el-form></div><div class="data-manage-table"><div class="data-manage-header"><el-alert title="入库数据反显" type="info" show-icon /></div><el-table :data="tableData" height="400" style="width: 100%" empty-text="暂无数据"><el-table-columnv-for="item in tableColumn":key="item.prop":prop="item.prop":label="item.label"/></el-table></div></div></template><script setup lang="ts">import { reactive, ref } from 'vue'const regionData = ref([{value: 'beijing',label: '北京'},{value: 'shanghai',label: '上海'},{value: 'chengdu',label: '成都'}])const typeData = ref([{value: 'type-1',label: '类型一'},{value: 'type-2',label: '类型二'},{value: 'type-3',label: '类型三'},{value: 'type-4',label: '类型四'}])const resourceData = ref([{value: 'resource-1',label: '资源一'},{value: 'resource-2',label: '资源二'}])const tableColumn = ref([{prop: 'name',label: '名称'},{prop: 'region',label: '区域'},{prop: 'date',label: '日期'},{prop: 'delivery',label: '已激活'},{prop: 'type',label: '激活类型'},{prop: 'resource',label: '资源'},{prop: 'desc',label: '备注'}])const tableData = ref([])const form = reactive({name: '',region: '',date: '',delivery: false,type: [],resource: '',desc: ''})const onSubmit = () => {console.log('submit!', JSON.parse(JSON.stringify(form)))}</script><style scoped>.data-manage {width: 100%;height: 100%;display: flex;padding: 16px;box-sizing: border-box;}.data-manage-header {margin-bottom: 16px;}.data-manage-form {width: 480px;border: 1px solid #dcdfe6;border-radius: 4px;margin-right: 8px;padding: 16px;box-sizing: border-box;}.data-manage-table {flex: 1;border: 1px solid #dcdfe6;border-radius: 4px;padding: 16px;box-sizing: border-box;}</style>
界面预览如下:
![图片[2]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_4.png)
上述界面操作逻辑:左侧数据入库面板中依次填入相关信息后点击下方“提交”按钮,用户输入的信息数据会被提交到后台数据库中,此时右侧数据预览面板会更新,显示最新数据库中的数据。
数据库初始化
数据在前端界面被用户输入后,会经过后端接口程序,最终保存在数据库中,数据库可以安装部署在本地开发环境或远端服务器环境中。
此系列文章中为了简化操作,在腾讯云租了一个 PostgreSQL 云数据库,所以省去了安装部署流程,如果想安装部署在本机或服务器的话,建议大家通过搜索引擎去寻找一些相关教程,无脑安装即可。
数据库安装部署之后,接下来进行库表初始化。
首先在 PostgreSQL 数据库管理面板中选择新建数据库,名称为“webgis”:
![图片[3]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_7.png)
然后选择新建的“webgis”数据库进入该数据库,在 public 模式下选择操作中的“新建表”,新建一份数据表,其结构如下:
![图片[4]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_10.png)
![图片[5]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_13.png)
![图片[6]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_16.png)
至此,一个名为“webgis”的数据库创建成功,里面又新建了一份名为“webgis_project_bilibili”的数据表,我们后续入库的数据就存放在此。
后端接口程序初始化
为了降低后端接口开发门槛,避免短时间内又学习一门新的开发语言,此系列的后端接口开发我们使用 Node.js,它是一个类似于浏览器的 JavaScript 运行环境,允许 JavaScript 语言编写的程序在浏览器环境之外可以运行,简单理解就是:Node.js 让 JavaScript 可以在浏览器之外运行成为了可能!
Node.js 在使用之前必须要在本机安装部署,不过不用担心,我们已经安装部署过了,详见《6、快速上手:使用 Vue 3 创建您的第一个 WebGIS 地图》。
在现有的项目根目录下新建 node 目录,然后通过 npm init 命令初始化一个后端接口程序目录,此时该目录下会出现一个 package.json 文件,里面包含当前后端程序的项目名称、版本号、作者信息等,以及后续我们安装的依赖包信息。
运行命令 npm install express 安装 express 框架。
新建 index.js 文件,将下述代码拷贝至此:
// eslint-disable-next-line no-undefvar express = require('express')var app = express()app.get('/', function (req, res) {res.send('hello world')})app.listen(3001)
通过上述操作,我们已经初始化了一个基础的后端接口程序,其中已经新建了一个路径为“/”的 get 类型接口,通过 node index 命令将其启动后,在浏览器地址栏中输入“:3001/”,可以访问该接口:
![图片[7]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_19.png)
GET 和 POST 接口开发
GET 和 POST 接口逻辑中都涉及到从 PostgreSQL 数据库中获取数据和插入数据,所以后端接口程序中需要安装 pg 模块,通过命令 npm install pg 安装。
在 node 目录下新建 routers 目录,然后该目录下新建 user.js 文件,在此文件中分别完成用户数据获取和插入接口:
// eslint-disable-next-line no-undefvar express = require('express')var pg = require('pg')var router = express.Router()// postgres://[数据库用户名]:[数据库密码]@[数据库地址及端口]/[数据库名称]var pgConfig = "postgres://postgres:webgis@localhost:5432/webgis";// 获取全部用户数据router.get('/all-data', function (req, res) {var client = new pg.Client(pgConfig)client.connect(function (isErr) {if (isErr) {console.log('connect error:' + isErr.message)client.end()return}client.query('SELECT * FROM "webgis_project_bilibili"', function (isErr, rst) {if (isErr) {console.log('query error:' + isErr.message)res.send({status: 'fail',msg: 'query error'})} else {console.log('query success, data is: ' + rst)res.send({status: 'success',data: rst.rows})}client.end()})})})// 插入数据router.post('/insert-data', function (req, res) {var id = Number(req.body.id)var name = req.body.namevar region = req.body.regionvar date = req.body.datevar delivery = Boolean(req.body.delivery)var type = req.body.typevar resource = req.body.resourcevar desc = req.body.descvar client = new pg.Client(pgConfig)client.connect(function (isErr) {if (isErr) {console.log('connect error:' + isErr.message)client.end()return}client.query('INSERT INTO "webgis_project_bilibili" ("id", "name", "region", "date", "delivery", "type", "resource", "desc") VALUES ($1, $2, $3, $4, $5, $6, $7, $8);',[id, name, region, date, delivery, type, resource, desc],function (isErr, rst) {if (isErr) {console.log('query error:' + isErr.message)res.send({status: 'fail',msg: 'insert error'})} else {console.log('insert success, data is: ' + rst)res.send({status: 'success',data: []})}client.end()})})})// eslint-disable-next-line no-undefmodule.exports = router
优化 node 目录下的 index.js 文件,在其中配置接口跨域、body数据解析、接口地址等信息:
/* eslint-disable no-undef */// eslint-disable-next-line no-undefvar express = require('express')var app = express()var bodyParser = require('body-parser')var user = require('./routers/user')//设置跨域访问app.all('*', function (req, res, next) {res.header('Access-Control-Allow-Origin', '*')res.header('Access-Control-Allow-Headers','Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With')res.header('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')res.header('X-Powered-By', ' 3.2.1')res.header('Content-Type', 'application/json;charset=utf-8')next()})app.use(bodyParser.urlencoded({extended: true}))app.use(bodyParser.json())app.use('/user', user)app.get('/', function (req, res) {res.send('hello world')})app.listen(3001)
至此,接口开发工作已完成。
DataManage 中数据插入和获取
在 DataManage.vue 组件中,优化完善 onSubmit 方法:
const onSubmit = () => {const formData = JSON.parse(JSON.stringify(form))axios.post('http://localhost:3001/user/insert-data',qs.stringify({...formData,type: formData.type.join(','),id: new Date().getTime()})).then((res) => {openMessage('数据入库成功', 'success')fetchData()}).catch((err) => {console.error('err', err)openMessage('数据入库失败', 'error')})}
每次入库成功后,都需要重新获取一遍数据库中的最新数据,所以需要定义获取数据的方法 fetchData:
function fetchData() {axios.get('http://localhost:3001/user/all-data').then((res) => {console.log('res', res)tableData.value = lodash.map(res?.data?.data, (item) => {return {...item,region: lodash.find(regionData.value, { value: item.region })?.label,date: new Date(item.date).toLocaleDateString(),delivery: item.delivery ? '是' : '否',type: item.type.split(',').map((type) => {return lodash.find(typeData.value, { value: type })?.label}),resource: lodash.find(resourceData.value, { value: item.resource })?.label}})}).catch((err) => {console.error('err', err)})}onMounted(() => {fetchData()})
界面预览如下:
![图片[8]-14、WebGIS 从前端到后端:后台接口开发-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2025/01/1735758310267_22.gif)
小作业:数据管理支持检索数据
对于 WebGIS 系统中前端和后端开发流程全部介绍完毕,数据管理界面完成了数据插入和获取,但是在数据获取时并没有按条件去筛选,接下来继续优化 GET 接口,使其按接口传参来获取相应的数据,并在界面中增加条件筛选模块。
结语
通过本文的介绍,应该对如何使用 Node.js 开发 WebGIS 系统的后台接口有了基本的了解。从数据库的初始化到后端接口的创建,再到 Vue 项目中的路由配置,每一步都是构建一个高效、可靠的 WebGIS 系统不可或缺的部分。完成小作业可以帮助巩固所学知识,并将其应用到实际的项目开发中。








