说明:
我们上一章【章节7.后端api开发(选修课)】为选修课,再上一章开头已经说明了,主要讲了api接口的开发和最后将网站上线到服务器的内容,同学们根据自己的实际情况选择性观看。
关于整个网站代码(包括后来新开发的api接口代码)的整个代码,大家可以群里下载,然后照着视频上线。
没有学习上一章的同学,老师给大家提供了线上api接口进行使用
# 一、首页接口
# ① 接口URL
http://lesson06.51yrc.com/api/wap/index/index (opens new window)
# ② 请求方式
GET请求
# ③ 成功响应示例
[
{
"type": "swiper",
"data": [
{
"timestamp": 1716347848000,
"create_time": "2024-05-22 11:17:28",
"id": 4,
"category_id": 13,
"name": "规划设计",
"enname": "",
"status": 1,
"order": 1,
"description": "供电工程前期现场勘察、供电方案设计",
"keywords": "",
"maincontent": "",
"attachment": "/public/uploads/Diy/adminImg/20240522/1716347846723_46195408.png",
"lookcount": 0,
"manager_id": 5,
"update_time": "2024-05-23T04:41:35.000Z",
"categoryId": 13,
"managerId": 5,
"category": {
"id": 13,
"name": "主营业务首页板块展示",
"enname": ""
}
},
...
]
},
{
"type": "notices",
"data": [
{
"timestamp": 1735190017000,
"create_time": "2024-12-26 13:13:37",
"id": 24,
"category_id": 6,
"name": "水电站如何做到精准防汛?请看黄河、长江骨干水库如何做到的",
"enname": "",
"status": 1,
"order": 50,
"description": "为确保骨干水库持续高水位运用期间的防汛安全,水利部等相关各级部门密切关注汛情,做好防汛会商、精准调度等工作,充分发挥水库防洪和经济效益。",
"keywords": "",
"maincontent": "\u003Cp\u003E为确保骨干水库持续高水位运用期间的防汛安全,水利部等相关各级部门密切关注汛情,做好防汛会商、精准调度等工作,充分发挥水库防洪和经济效益。\u003C/p\u003E\r\n\u003Cp\u003E\u003Cimg style=\"display: block; margin-left: auto; margin-right: auto;\" src=\"/public/uploads/Diy/adminImg/20241211/1733907139668_76380519.jpg\"\u003E\u003C/p\u003E\r\n\u003Cp\u003E01\u003C/p\u003E\r\n\u003Cp\u003E秋汛来水较往年偏多,摸清5省坝型分布\u003C/p\u003E\r\n\u003Cp\u003E今年黄河、长江秋汛累计来水量较常年同期偏多。采访中,记者听到最多的是“水量级大”“延续时间长”“水库快速上涨”“防汛形势严峻”“调度难度大”“用绣花功夫算'水账'”。\u003C/p\u003E\r\n\u003Cp\u003E数据显示,8月下旬以来,黄河中下游累积面雨量389毫米,较常年同期118毫米偏多2.3倍;长江支流汉江上游降水量520毫米,较常年偏多1.5倍;丹江口水库秋汛累计来水量约340亿立方米,较常年同期偏多约4倍。\u003C/p\u003E\r\n\u003Cp\u003E“受华西秋雨持续影响,黄河中下游干支流发生严重秋汛,洪水场次之多、过程之长、量级之大极为罕见。伊洛河来水为多年均值5.7倍,沁河为多年均值5.9倍,渭河为多年均值2倍,受降雨影响,支流渭河、伊洛河、沁河均发生有实测资料以来同期最大洪水。”黄委水文局副局长袁东良向记者介绍。\u003C/p\u003E\r\n\u003Cp\u003E小浪底管理中心水量调度处处长李鹏对记者表示:“小浪底水库持续拦洪,拦截第1号洪水的同时还要拦截第3号洪水,防汛形势十分严峻。不过,截至目前,小浪底水库运行平稳,库周无大的地质灾害发生。”\u003C/p\u003E\r\n\u003Cp\u003E目前,水利部已全面摸清晋、陕、甘、宁、豫5省区降雨区135个县区1.3万座的大中型淤地坝分布,其中大型坝4300座,中型坝8924座;包括下游有人的淤地坝211座。水利部黄河水利委员会已督促各地全面摸清摸准病险水库分布及数量以及山洪沟分布、危险区村庄和人员情况,逐库逐沟落实防御措施。\u003C/p\u003E\r\n\u003Cp\u003E记者采访获悉,河南、山西省防指已做好小浪底水库274米以下、故县水库544.2米以下、河口村水库280米以下高水位运用准备。“目前,黄河下游河南、山东段约有3.3万人投入防洪工程巡查观测。在黄河下游,各地全面落实以行政首长负责制为核心的各项防汛抗旱责任制,并按照防御大洪水运行工作机制到岗到位,按专业人员和群防队伍1:3的比例落实人员。”黄河水利委员会防御局副局长张希玉介绍。\u003C/p\u003E\r\n\u003Cp\u003E02\u003C/p\u003E\r\n\u003Cp\u003E调度下足“绣花”功夫,联合调度统筹“水账”\u003C/p\u003E\r\n\u003Cp\u003E采访中,业内人士均提到,防秋汛中下足“绣花”功夫,“水账”按照厘米计算,充分挖掘水库库容。\u003C/p\u003E\r\n\u003Cp\u003E河南郑州花园口水文站,是黄河下游汛情“晴雨表”。花园口水文站流量一旦超过4800立方米每秒,下游堤防、滩区防守压力就会徒增。为此,上下游同时“做减法”。小浪底水库拦洪削峰,支流上的陆浑、故县水库压减下泄流量。此外,济平干渠、南水北调穿黄工程等实施分泄。“实施长河段、干支流水库群联合调度,最大限度减轻下游漫滩和防守压力。黄委组织工作专班,下足绣花功夫,以每半小时50立方米每秒为调度单元,滚动修订水库调度方案,精准调控花园口站流量。”张希玉表示。\u003C/p\u003E\r\n\u003Cp\u003E小浪底管理中心开发公司运行部副部长鲁锋向记者直言,“以往调度均是几百流量调度,今年精准到50立方米每秒调度,水电机组运行管理难度加大,机组随时需要按照指令下泄流量。”\u003C/p\u003E\r\n\u003Cp\u003E除了细微级别精确调度外,联合统筹“水账”也是今年防秋汛的重要抓手之一。据悉,由黄河水利委员会直接调度参与调控的水库共7座,其中对黄河下游防洪控制断面-花园口水文断面通过流量起决定作用的5座水库,分别是干流的三门峡水库、小浪底水库,支流伊洛河右支伊河上的陆浑水库和左支洛河上的故县水库、沁河上的河口村水库。支流的三个水库管好自己一亩三分地的同时,实行错峰调度,尽量为小浪底水库尽可能泄放流量留出空间。\u003C/p\u003E\r\n\u003Cp\u003E长江委防御局副局长郑静向记者介绍,科学调度汉江流域水库群,有效应对了汉江7次10000立方米每秒以上的丹江口水库入库洪水过程,极大减轻了汉江中下游地区的防洪压力。“若没有水库群拦蓄,汉江中下游将全线超保,部分河段洪峰水位将超堤顶高程。通过水库群拦洪、削峰、错峰,有效控制汉江中下游水位,防洪效益十分显著。”\u003C/p\u003E\r\n\u003Cp\u003E03\u003C/p\u003E\r\n\u003Cp\u003E改善供电质量,提升经济效益\u003C/p\u003E\r\n\u003Cp\u003E丰富来水使水库产生显著的发电效益。汉江集团公司总经理何晓东对记者表示,丹江口水电站是湖北电网的主力调频电站,承担了湖北电网重要的调峰、调相和事故备用的任务,对保证电网的安全运行、改善供电质量和提高电网的经济效益起到重要作用。\u003C/p\u003E\r\n\u003Cp\u003E记者从丹江口水电站获悉,丹江电厂利用来水较多时机多发满发,截至10月7日,丹江电厂累计发电量41.85亿千瓦时。\u003C/p\u003E\r\n\u003Cp\u003E预计2021年发电量约49.5亿千瓦时,超多年平均发电量15.7亿千瓦时,为南水北调中线一期工程通水以来最大年发电量,相当于替代标准煤153万吨,减排二氧化碳400万吨、二氧化硫1.3万吨、氮氧化物1.13万吨。\u003C/p\u003E\r\n\u003Cp\u003E \u003C/p\u003E",
"attachment": "/public/uploads/Diy/adminImg/20241211/1733907151973_44561582.jpg",
"lookcount": 0,
"manager_id": 5,
"update_time": "2024-12-26T05:13:37.000Z",
"categoryId": 6,
"managerId": 5,
"category": {
"id": 6,
"name": "资讯中心",
"enname": "NEWS CNETER"
}
},
...
]
},
{
"type": "items",
"data": [
{
"create_time": "2024-05-22 10:57:38",
"id": 5,
"pid": 0,
"name": "关于我们",
"enname": "ABOUT US",
"status": 1,
"description": "",
"order": 50,
"isnav": 1,
"categoryurl": "/api/template/01/id/1/cid/5?pageType=detail&ortherType=aboutus",
"wap_icon": "tags-fill",
"wap_url": "",
"wap_isnav": 1,
"update_time": "2025-01-07T07:44:47.000Z"
},
...
]
},
{
"type": "uScrollList",
"name": "合作单位",
"data": [
{
"timestamp": 1716348528000,
"create_time": "2024-05-22 11:28:48",
"id": 10,
"category_id": 10,
"name": "国家电网",
"enname": "",
"status": 1,
"order": 1,
"description": "国家电网",
"keywords": "",
"maincontent": "",
"attachment": "/public/uploads/Diy/adminImg/20240522/1716348525825_58461494.jpg",
"lookcount": 10,
"manager_id": 5,
"update_time": "2025-01-07T07:22:38.000Z",
"categoryId": 10,
"managerId": 5,
"category": {
"id": 10,
"name": "合作单位",
"enname": "COOPERATION UNIT"
}
},
...
]
},
{
"type": "uniCard",
"name": "资讯中心",
"data": [
{
"timestamp": 1716429551000,
"create_time": "2024-05-23 09:59:11",
"id": 14,
"category_id": 6,
"name": "2022年8月2日到3日中电联(北京)认证中心委派2位审核专家对我司质量、安全及职业健康安全管理体系进行审",
"enname": "",
"status": 1,
"order": 50,
"description": "我司质量、安全及职业健康安全管中心委派2位审核专家对我司质量、安全及职理体系进行审核 并顺利通过我司质量、安全及职业健康安全管理体系进行审核 并顺利通过",
"keywords": "",
"maincontent": "\u003Cp\u003E中心委派2位审核专家对我司质量、安全及职中心委派2位审核专家对我司质量、安全及职中心委派2位审核专家对我司质量、安全及职中心委派2位审核专家对我司质量、安全及职中心委派2位审核专家对我司质量、安全及职中心委派2位审核专家对我司质量、安全及职\u003C/p\u003E",
"attachment": "/public/uploads/Diy/adminImg/20240523/1716429548390_39356937.jpg",
"lookcount": 3,
"manager_id": 5,
"update_time": "2025-01-07T10:55:59.000Z",
"categoryId": 6,
"managerId": 5,
"category": {
"id": 6,
"name": "资讯中心",
"enname": "NEWS CNETER"
}
},
...
]
},
{
"type": "uTabbar",
"data": [
{
"text": "首页",
"icon": "home",
"openurl": "/pages/index/index",
"badge": 0,
"dot": false,
"id": 1
},
...
]
}
]
# ④ 首页数据请求及数据处理
index.vue页面
...
onLoad() {
uni.$u.http.get('http://lesson06.51yrc.com/api/wap/index/index').then(res => {
console.log('请求结果',res.data);
this.pagedata = res.data.map(item=>{
switch(item.type){
case 'swiper':
return {
type: item.type,
data: item.data.map(e=>{
return {
...e,
src: 'http://lesson06.51yrc.com'+ e.attachment,
title: e.name,
type: 'image'
}
})
}
break;
case 'notices':
return {
type:item.type,
data:item.data.map(e=>{
return {
...e,
titles: e.name,
url:'',
}
})
}
break;
case 'items':
return {
type:item.type,
data:item.data.map(e=>{
return {
...e,
name: e.name,
en_name:e.enname,
icon_name:e.wap_icon
}
})
}
break;
case 'uScrollList':
return {
type:item.type,
name:item.name,
data:item.data.map(e=>{
return {
...e,
src:'http://lesson06.51yrc.com' + e.attachment,
title: e.name,
type: 'image'
}
})
}
break;
case 'uniCard':
return {
type:item.type,
name:item.name,
data:item.data.map(e=>{
return {
...e,
cardTitle:'发布时间:' + e.create_time,
cardExtra:'浏览:' + e.lookcount,
imgSrc:'http://lesson06.51yrc.com' + e.attachment,
title:e.name,
desc:e.description,
}
})
}
break;
case 'uTabbar':
return {
type:item.type,
data:item.data.map(e=>{
return {
...e,
}
})
}
break;
default:
break;
}
});
console.log('渲染页面的数据',this.pagedata);
});
},
...
# 二、网络不好情况下骨架屏提示页面加载中
index.vue页面
<!-- 没有数据或者网络差 -->
<template v-if="!pagedata.length">
<view>
<!-- banner -->
<view class="p-2">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['180px']"
loading animate :title="false"></u-skeleton>
</view>
<!-- 滚动消息 -->
<view class="px-2">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['30px']"
loading animate :title="false"></u-skeleton>
</view>
<!-- 主要栏目 -->
<view class="p-2">
<view class="flex justify-between mb-2" v-for="i in 3" :key="i">
<view class="flex-1 pr-1">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['60px']"
loading animate :title="false"></u-skeleton>
</view>
<view class="flex-1 pl-1">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['60px']"
loading animate :title="false"></u-skeleton>
</view>
</view>
</view>
<!-- 卡片 -->
<view class="p-2" v-for="i in 3" :key="i">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['140px']"
loading animate :title="false"></u-skeleton>
<view class="mt-3">
<u-skeleton rows="3" loading animate title></u-skeleton>
</view>
</view>
</view>
</template>
<!-- 有数据 -->
<template v-if="pagedata.length">
...
</template>
# 三、工程案例接口 (piclist.vue)
# ① 接口URL
http://lesson06.51yrc.com/api/wap/cid/8 (opens new window)
最后数字8,表示的是分类id,根据数据库的数据,如果换成10,就是合作单位
# ② 请求方式
GET请求
# ③ 数据请求及处理
<template>
<view>
<!-- 没有数据或者请求数据 -->
<view v-if="!pagedata || (pagedata && !pagedata.data.length)">
<!-- 导航栏 -->
<view>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<u-navbar title="加载中..." bgColor="#1989fa"
autoBack placeholder leftIconColor="#ffffff"
titleStyle="color:#ffffff;"></u-navbar>
<!-- #endif -->
</view>
<!-- 卡片 -->
<view class="p-2" v-for="i in 3" :key="i">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['120px']"
loading animate :title="false"></u-skeleton>
<view class="mt-3">
<u-skeleton rows="3" title loading></u-skeleton>
</view>
</view>
</view>
<!-- 有数据 -->
<view v-if="pagedata">
...
</view>
</view>
</template>
<script>
export default {
data() {
return {
// pagedata:pagedata,
pagedata:null,
tabbarValue:2,
}
},
onLoad(e) {
console.log('看一个e',e);
let cid = parseInt(e.cid) ? parseInt(e.cid) : 8;
uni.$u.http.get('http://lesson06.51yrc.com/api/wap/cid/' + cid).then(res => {
console.log('请求结果',res.data);
this.pagedata = {
uNavbarTitle: res.data.length ? res.data[0].category.name : '没有数据',
data:res.data.map(item=>{
console.log('每一个结果',item);
return {
...item,
openurl:'/pages/detail/detail',
title:item.name,
desc:item.description,
timeago:item.create_time,
readcount: item.lookcount + ' 阅读',
imgsrc:'http://lesson06.51yrc.com' + item.attachment,
}
})
}
console.log('渲染到页面的数据',this.pagedata);
// #ifdef H5
uni.setNavigationBarTitle({
title:this.pagedata.uNavbarTitle
})
// #endif
});
},
...
}
</script>
# 四、底部导航栏处理及混入代码
① 混入文件:/common/mixins/common.js
export default{
data() {
return {
uTabbarData:[],
site:'http://lesson06.51yrc.com',
}
},
methods:{
//底部tabbar切换
changeTabbar(index){
console.log(index);
// #ifdef H5
this.tabbarValue = index;
// #endif
},
//点击底部tabbar某一项
openurl(url){
console.log(url);
uni.navigateTo({
url:url
})
},
}
}
② 数据缓存
import commonJS from '@/common/mixins/common.js';
...
mixins:[commonJS],
...
// 1.首页得到底部导航栏进行缓存
uni.setStorageSync('uTabbarData',JSON.stringify(item.data)); //同步缓存
// 2.在其它页面读取缓存
//底部导航栏
this.uTabbarData = JSON.parse(uni.getStorageSync('uTabbarData'));
//3.this.site替换网址
# 五、资讯中心(list.vue)、联系我们(contact.vue)接口
资讯中心(list.vue)http://lesson06.51yrc.com/api/wap/cid/6 (opens new window)
联系我们(contact.vue)http://lesson06.51yrc.com/api/wap/contact/contact (opens new window)
具体操作看课程视频。
抽离相同方法到 /common/mixins/common.js
export default {
data() {
return {
site:'http://lesson06.51yrc.com',
uTabbarData:[]
}
},
methods: {
//底部tabbar切换
changeTabbar(index){
console.log(index);
// #ifdef H5
this.tabbarValue = index;
// #endif
},
//点击底部tabbar某一项
openurl(url){
console.log(url);
uni.navigateTo({
url:url
})
},
//列表数据
listData(e){
console.log('看一下e',e);
let cid = parseInt(e.cid) ? parseInt(e.cid) : 8;
uni.$u.http.get(this.site + '/api/wap/cid/'+ cid).then(res => {
console.log('请求结果',res.data);
this.pagedata = {
uNavbarTitle: res.data.length ? res.data[0].category.name :'没有数据',
data: res.data.map(item=>{
console.log('每一个结果',item);
return {
...item,
openurl:'/pages/detail/detail',
title:item.name,
desc:item.description,
timeago:item.create_time,
readcount:item.lookcount + ' 阅读',
imgsrc:this.site + item.attachment,
}
}),
}
// console.log('渲染到页面的数据',this.pagedata);
this.getUtabbar()
});
},
//获取底部导航栏
getUtabbar(){
// #ifdef H5
if(this.pagedata.uNavbarTitle){
uni.setNavigationBarTitle({
title:this.pagedata.uNavbarTitle
})
}
// 获取底部导航栏数据
console.log('看一下底部导航栏数据',JSON.parse(uni.getStorageSync('uTabbarData')));
this.uTabbarData = JSON.parse(uni.getStorageSync('uTabbarData'));
// #endif
}
},
}
# 六、详情页(detail.vue)接口
# ① 接口
http://lesson06.51yrc.com/api/wap/id/信息id,例如 http://lesson06.51yrc.com/api/wap/id/24 (opens new window)
# ② 请求方式
GET请求
# ③ 数据请求及处理
<template>
<view>
<!-- 没有数据或者请求数据 -->
<template v-if="!pagedata">
<view>
<!-- 导航栏 -->
<view>
<!-- #ifdef MP-WEIXIN || APP-PLUS -->
<u-navbar title="请求中..." bgColor="#1989fa"
autoBack placeholder leftIconColor="#ffffff"
titleStyle="color:#ffffff;"></u-navbar>
<!-- #endif -->
</view>
<!-- 卡片 -->
<view class="p-2" v-for="i in 3" :key="i">
<u-skeleton rows="1" :rowsWidth="['100%']" :rowsHeight="['120px']"
loading animate :title="false"></u-skeleton>
<view class="mt-3">
<u-skeleton rows="3" title loading></u-skeleton>
</view>
</view>
</view>
</template>
<!-- 有数据 -->
<template v-if="pagedata">
<!-- 页面详情内容 -->
<view class="p-3">
<text class="text font-weight-bolder font-lg"
style="line-height: 1.4;text-align: justify;">{{pagedata.title}}</text>
<view class="flex align-center justify-between mt-2">
<text class="text-muted font-sm">{{pagedata.timeago}}</text>
<text class="text-muted font-sm">{{pagedata.readcount}}</text>
</view>
<!-- 页面内容 -->
<view class="py-3" style="line-height: 1.8;text-align: justify;">
<!--{{pagedata.content}}-->
<!-- <rich-text :nodes="pagedata.content"></rich-text> -->
<u-parse :content="pagedata.content" :domain="pagedata.domain"></u-parse>
</view>
</view>
<!-- #ifdef H5 -->
<!-- 底部tabbar -->
<u-tabbar :value="-1" :safeAreaInsetBottom="true" :border="true"
:zIndex="1" activeColor="#1989fa" inactiveColor="#7d7e80"
:fixed="true" :placeholder="true"
@change="changeTabbar">
<u-tabbar-item v-for="(d,i) in uTabbarData" :key="i"
:text="d.text" :icon="d.icon" :badge="d.badge"
@click="openurl(`${d.openurl}`)" :dot="d.dot"></u-tabbar-item>
</u-tabbar>
<!-- #endif -->
</template>
</view>
</template>
<script>
let pagedata = {
title:'能源局:2022年乡村振兴定点帮扶和对口支援工作要点 持续推进农村电网薄弱地区建设',
timeago:'5个小时前',
readcount:'15万+ 阅读',
domain:'http://lesson06.51yrc.com',
content:`
<p>近日国家能源局印发2022年乡村振兴定点帮扶和对口支援工作要点的通知。文件提出,持续推进农村电网薄弱地区建设,优化城乡网架结构,提升农村电网供电保障水平,增强农村分布式可再生能源接入能力。加快推进通渭县平襄110千伏变电站等重点工程建设。推动通渭、清水县配电网建设示范县、“获得电力”服务水平样板工程建设,巩固提升信丰县全国小康用电示范县成果。</p>
`,
};
import commonJs from '@/common/mixins/common.js';
export default {
mixins:[commonJs],
data() {
return {
// pagedata:pagedata
pagedata:null
}
},
onLoad(e) {
console.log('看一下e',e);
let id = parseInt(e.id) ? parseInt(e.id) : 0;
uni.$u.http.get(this.site + '/api/wap/id/' + id).then(res => {
console.log('请求结果',res.data);
let item = res.data;
if(typeof item === 'object' && Object.keys(item).length > 0){
this.pagedata = {
...item,
title:item.name,
timeago:item.create_time,
readcount:item.lookcount + ' 阅读',
domain:this.site,
content:item.maincontent,
}
}
// console.log('渲染到页面的数据',this.pagedata);
this.getUtabbar();
});
}
}
</script>
<style>
</style>
# ④ 其它页面改一下详情页连接地址
看课程视频。
# 七、在线留言接口
# ① 接口
http://lesson06.51yrc.com/api/wap/onlineMessage (opens new window)
# ② 请求方式
POST请求
# ③ 页面提交处理
contact.vue页面
...
methods: {
submit(){
this.$refs.uForm1.validate().then(res => {
// uni.$u.toast('校验通过')
console.log('校验通过的数据',this.form);
uni.$u.http.post(this.site + '/api/wap/onlineMessage', this.form ).then(res => {
console.log('留言反馈',res);
uni.$u.toast(res.data.data);
}).catch(err => {
// console.log(err);
uni.$u.toast(err.data.data);
}).finally(() => {
// 清空表单内容
setTimeout(()=>{
this.form = {
username:'',
telnumber:'',
message:'',
};
},3000);
});
})
},
},
...
# ④ 服务器端代码(选修课)
- 控制器代码
app/controller/api/template01/wap.js
...
let crypto = require('crypto');
//自定义IV(16位)、key(密钥(32位的'aes-256-cbc')(24位的'aes-192-cbc'))
const secret = {
iv: 'IloveYOU@520520!',// 初始化向量(iv)16位
key: 'a123456789@!*&%bcdef@123456789&&', // 32 位秘钥密钥
}
...
const Controller = require('egg').Controller;
class WapController extends Controller {
...
//在线留言
async onlineMessage() {
//一般处理流程
//1.参数验证
this.ctx.validate({
username: {
type: 'string', //参数类型
required: true, //是否必须
// defValue: '',
desc: '您的称呼' //字段含义
},
telnumber: {
type: 'phone',
required: true,
// defValue: '',
desc: '您的电话'
},
message: {
type: 'string',
required: false,
// defValue: '',
desc: '您的留言'
},
});
let { username, telnumber, message } = this.ctx.request.body;
// 如果一个用户只能提交一次留言,那么可以通过电话判断,多次则拒绝
if (await this.app.model.Message.findOne({ where: { telnumber } })) {
return this.ctx.apiFail('您已经提交过留言了,我们会尽快联系您');
}
//为了满足数据库设计需要,对电话做一个加密
let tel = await this.aesEncrypt(telnumber, secret.key, secret.iv);
//否则不存在则写入数据库
await this.app.model.Message.create({
username,
telnumber,
tel,
message
});
this.ctx.apiSuccess('留言成功');
}
//对称加密
async aesEncrypt(data, key, iv) {
// 给定的算法,密钥和初始化向量(iv)创建并返回Cipher对象
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv)
// 指定要摘要的原始内容,可以在摘要被输出之前使用多次update方法来添加摘要内容
// 数据的编码 utf8 返回值的编码 hex
var crypted = cipher.update(data, 'utf8', 'hex')
crypted += cipher.final('hex')
return crypted
}
//对称解密
async aesDecrypt(data, key, iv) {
// 给定的算法,密钥和初始化向量(iv)创建并返回Cipher对象
const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv)
// 数据的编码 hex 返回值的编码 utf8
var decrypted = decipher.update(data, 'hex', 'utf8')
decrypted += decipher.final('utf8')
return decrypted
}
}
module.exports = WapController;
- 路由
app/router/api/template01/router.js
...
//在线留言
router.post('/api/wap/onlineMessage', controller.api.template01.wap.onlineMessage);
...
# 部署说明
我们以:H5端发行部署为例,给大家讲一下如何发布项目。
# ① 配置
- 页面标题:
睿晨电网建设 - index.html模版路径:
自行配置或者不填 - 路由模式:
hash - 运行的基础路径:如:
/wap/,可不填 发行时启用摇树优化
# ② 发行
发行前,先配置一个域名,用于访问移动端
- 网站标题:
睿晨电网建设 - 网站域名:
lesson06wap.51yrc.com
# ③ 访问官网域名,根据设备自动跳转到移动端
文档搜索 设备
<script>
var machine={
the_machine:function(){
var system = {win: false,mac: false,xll: false};
var p = navigator.platform;
var oMeta = document.createElement('meta');
oMeta.charset = 'utf-8';
document.getElementsByTagName('head')[0].appendChild(oMeta);
oMeta.setAttribute('name','Currentmachine');
system.win = p.indexOf("Win") == 0;
system.mac = p.indexOf("Mac") == 0;
system.x11 = (p == "X11") || (p.indexOf("Linux") == 0);
var device="";
if (system.win || system.mac || system.xll) {
oMeta.setAttribute('machine','pc');
let w = window.innerWidth;
if(w<768){
window.location.href="http://lesson06wap.51yrc.com";
oMeta.setAttribute('machine','phone');
}
} else {
oMeta.setAttribute('machine','phone');
window.location.href="http://lesson06wap.51yrc.com";
}
machine.the_ie(oMeta);
},
the_ie:function(oMeta){
//var ie;
if (/msie [6|7|8]/i.test(navigator.userAgent)){
oMeta.setAttribute('ie','8');
}else if(/msie [9]/i.test(navigator.userAgent)){
oMeta.setAttribute('ie','9');//alert(oMeta.getAttribute('ie'));
}else if(/msie [10]/i.test(navigator.userAgent)){
oMeta.setAttribute('ie','10');
}else if(/msie [11]/i.test(navigator.userAgent)){
oMeta.setAttribute('ie','11');
}else{
oMeta.setAttribute('ie','false');
}
}
}
machine.the_machine();
</script>
# ④ 关于小程序、APP的发布说明
关于小程序的发布:关于微信小程序的发布和支付宝小程序的发布,都是需要先申请微信小程序和支付宝小程序的appId,关于它们的具体申请和发布,我们会在后面的课程给大家开一个专题进行讲解。
关于APP的发布:关于APP发布到安卓应用市场和苹果应用商店,首先需要申请安卓和苹果证书,申请软件著作权,然后申请各个应用市场账号,然后打包发布,进行审核等等,较为复杂,这个也是在后面的课程给大家开专题进行讲解。
# ⑤ 总结
本季度课程为uni-app多端兼容开发入门课程,作为移动端的入门课程,大家学完之后需要掌握:
- 各个平台如何调试;
- 学会使用UI框架的组件创建页面;
- 基本事件的使用;
- 如何请求数据并渲染页面;
- vue2的基础语法和使用等等
学完本季度课程后,如果你的客户需要你开发一个官方网站,小程序,APP, 这些开发对你而言已经不是问题了。我们会在后面的课程,随着知识点的讲解的深入,会教大家开发更多功能更全,更实用的实战项目,欢迎大家的学习!