我们经常会看到有些软件,我们点击栏目,就会进入栏目下的文章,点击文章就会进入文章下的内容,这样看似简单的一个功能,其实也是比较难实现的,接下来,我就以cms项目为例,给大家分享我实现此功能的全过程。
所需软件:IDEA、HbuilderX、火狐浏览器。
接下来,我就来实现此功能。
一、在IDEA中完成后台代码(之前的博文里有,可以自行下载),在这里就不多说了。
二、创建一个手机端的项目,我的名字叫cms_moble,在pages下新建一个页面,名字为main,代码如下:
<template>
<view>
<uni-nav-bar fixed="true" statusBar="true" backgroundColor="#d3233b" color="#ffffff" class="title-bar"
title="律行法务"></uni-nav-bar>
<view>
<view>
<uni-swiper-dot mode="round" :info="info" :current="current" field="content" :mode="mode">
<swiper autoplay="true" interval="2000" style="height: 370rpx;" class="swiper-box" @change="change">
<swiper-item v-for="(item ,index) in info" :key="index">
<image :src="item.url" style="height: 370rpx; width: 100%"></image>
</swiper-item>
</swiper>
</uni-swiper-dot>
</view>
<view class="uni-flex uni-row"
style="-webkit-justify-content: center;justify-content: center; margin-top: 28rpx;">
<view @click="diagnoseCompany" style="margin-right: 20rpx;">
<image style="width:350rpx; height: 240rpx;"
src="../../static/main_qyzd01.jpg"></image>
</view>
<view @click="hotEvent" class="btn_big">
<image style="width:350rpx; height: 240rpx;"
src="../../static/main_rdsj01.jpg"></image>
</view>
</view>
<view
style="height: 1px; margin-top: 20rpx; margin-left: 15rpx; margin-right: 15rpx; background-color: #d4d4d4;">
</view>
<view class="uni-flex uni-row"
style="-webkit-justify-content: center;justify-content: center; margin-top: 35rpx;">
<view @click="doAsk" class="uni-flex uni-column" style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;" src="../../static/main_flzx.jpg"></image>
<text class="btn_text">法律咨询</text>
</view>
<view @click="news" class="uni-flex uni-column" style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;"
src="../../static/main_xwzx01.jpg"></image>
<text class="btn_text">新闻资讯</text>
</view>
<view @click="usualContract" class="uni-flex uni-column"
style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;" src="../../static/main_cyht.jpg"></image>
<text class="btn_text">常用合同</text>
</view>
<view @click="indictment" class="uni-flex uni-column" style="text-align: center;">
<image style="width:140rpx; height: 140rpx;"
src="../../static/main_dxsz01.jpg"></image>
<text class="btn_text">代写诉状</text>
</view>
</view>
<view class="uni-flex uni-row"
style="-webkit-justify-content: center;justify-content: center; margin-top: 50rpx;">
<view @click="documentDownload" class="uni-flex uni-column"
style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;"
src="../../static/main_wdxz01.jpg"></image>
<text class="btn_text">文档查看</text>
</view>
<view @click="askAndAnswer" class="uni-flex uni-column" style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;"
src="../../static/main_rmwd01.jpg"></image>
<text class="btn_text">热门问答</text>
</view>
<view @click="myOrder" class="uni-flex uni-column" style="text-align: center;margin-right: 40rpx;">
<image style="width:140rpx; height: 140rpx;" src="../../static/main_wddd.jpg"></image>
<text class="btn_text">我的订单</text>
</view>
<view @click="doMe" class="uni-flex uni-column" style="text-align: center;">
<image style="width:140rpx; height: 140rpx;" src="../../static/main_wdxx.jpg"></image>
<text class="btn_text">我的信息</text>
</view>
</view>
</view>
<!-- 警告对话框-->
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog mode="base" title="通知" :content="msg" :duration="2000" :before-close="true" @close="close"
@confirm="confirm"></uni-popup-dialog>
</uni-popup>
</view>
</template>
<script>
export default {
data() {
return {
themeColor: '#d3233b',
themeIndex: 0,
info: [{
content: '',
url: '../../static/banner1.jpg'
}, {
content: '',
url: '../../static/banner2.jpg'
}, {
content: '',
url: '../../static/banner3_1.jpg'
}, {
content: '',
url: '../../static/banner4_1.jpg'
}, {
content: '',
url: '../../static/banner5.jpg'
}],
current: 0,
mode: 'round',
msg: '该功能正在建设中,敬请期待',
resList: null
}
},
onLoad(options) {
try {
this.themeColor = uni.getStorageSync('themeColor');
this.themeIndex = uni.getStorageSync('themeIndex'); //1=企业版主题,2=个人版主题
} catch (e) {}
var state = options.state;
if(state == 'main'){
this.requestToken();
} else if(state == 'login') {
this.requestAppPermissions();
}
},
methods: {
open() {
this.$refs.popup.open()
},
/**
* 点击取消按钮触发
* @param {Object} done
*/
close() {
// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
/**
* 点击确认按钮触发
* @param {Object} done
* @param {Object} value
*/
confirm(value) {
// 输入框的值
// console.log(value)
// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
change(e) { //表格页码监听
this.current = e.detail.current;
},
doAsk() { //热门问答
var isOk = false;
for (var i = 0; i < this.resList.length; i++) {
if (this.resList[i].resUrl == 'app /im') {
isOk = true;
}
}
if (isOk) {
try {
const uid = uni.getStorageSync('uid');
const nickName = uni.getStorageSync('nickName');
//是否是会员
const isVip = uni.getStorageSync('roleName').indexOf('VIP') != -1;
//是否是企业用户
const isCompany = uni.getStorageSync('roleType') == '%Company%';
//企业名称(根据是否为企业用户)
const orgName = uni.getStorageSync('orgName');
uni.navigateTo({
url: '../webview/webview?uid=' + uid + "&nickName=" + nickName + "&isVip=" + isVip +
"&isCompany=" + isCompany + "&orgName=" + orgName
});
} catch (e) {
// error
}
} else {
this.msg = '该功能需要购买VIP后使用';
this.open();
}
},
doMe() { //我的信息
uni.navigateTo({
url: '../me/me'
});
},
diagnoseCompany() { //企业诊断
this.msg = '该功能正在建设中,敬请期待';
this.open();
},
hotEvent() { //热点事件
uni.navigateTo({
url: '../cms/news_list?cid=1&title=热点事件'
});
},
usualContract() { //常用合同
uni.navigateTo({
url: '../cms/news_list?cid=3&title=常用合同'
});
},
indictment() { //代写诉状
this.doAsk();
},
documentDownload() { //文档下载
uni.navigateTo({
url: '../cms/news_list?cid=4&title=文档查看'
});
},
askAndAnswer() { //热门问答
uni.navigateTo({
url: '../cms/news_list?cid=5&title=热门问答'
});
},
myOrder() { //我的订单
this.msg = '该功能正在建设中,敬请期待';
this.open();
},
news() { //新闻资讯
uni.navigateTo({
url: '../cms/news_list?cid=2&title=新闻资讯'
});
},
requestToken() { //刷新token
try {
const phoneLocal = uni.getStorageSync('phone');
const pwdLocal = uni.getStorageSync('pwd');
uni.showLoading({
title: '加载功能列表...'
})
uni.request({
url: getApp().globalData.serverUrl + '/user/login',
data: {
phone: phoneLocal,
pwd: pwdLocal
},
method: "GET",
success: (res) => {
uni.hideLoading();
// console.log(res.data);
console.log("已登入")
if (res.data.code == 200) {
try {
//存储用户token
uni.setStorageSync('token', res.data.data.token);
} catch (e) {
// console.log(e);
}
this.requestAppPermissions();
}
},
fail: (msg) => {
uni.hideLoading();
console.log(msg);
if (msg.errMsg == 'request:fail') {
console.log('服务器异常');
}
}
});
} catch (e) {
// console.log(e);
}
},
requestAppPermissions() { //获取APP权限
try {
const uid = uni.getStorageSync('uid');
const token = uni.getStorageSync('token');
if (uid && token) {
// uni.showLoading({
// title: '加载功能列表...'
// })
uni.request({
url: getApp().globalData.serverUrl + '/user/app_permissions',
method: "GET",
data: {
uid: uid
},
header: {
'Authorization': token
},
success: (res) => {
// uni.hideLoading();
console.log("权限:", res.data);
if (res.data.code == 200) {
this.resList = res.data.data;
try {
uni.setStorageSync('resList', this.resList);
} catch (e) {}
//#ifdef APP-PLUS
this.validateVersion(res.data.data.versionCode, res.data.data.appUrl);
//#endif
}
},
fail: (e) => {
// uni.hideLoading();
console.log(e)
if (e.errMsg == 'request:fail') { //请求被拒
this.msg = getApp().globalData.msg_no_promisson;
this.open();
}
}
});
}
} catch (e) {
// error
}
},
validateVersion(lastestVersion, appUrl) { //版本校验
appUrl = getApp().globalData.serverFileUrl + appUrl;
console.log('最新版本:' + lastestVersion);
var _this = this;
plus.runtime.getProperty(plus.runtime.appid, function(inf) {
var reg = new RegExp(/\./g);
var localVersion = inf.version.replace(reg, '');
console.log('本地版本:' + localVersion)
if (localVersion < lastestVersion) {
uni.showModal({
title: "发现新版本",
content: "确认下载更新",
success: (res) => {
if (res.confirm == true) { //当用户确定更新,执行更新
_this.doUpData(appUrl);
}
}
})
}
});
},
doUpData(appUrl) { //下载app
console.log('app下载地址:' + appUrl)
uni.showLoading({
title: '更新中……'
})
uni.downloadFile({ //执行下载
url: appUrl, //下载地址
success: downloadResult => { //下载成功
uni.hideLoading();
if (downloadResult.statusCode == 200) {
uni.showModal({
title: '',
content: '更新成功,确定现在重启吗?',
confirmText: '重启',
confirmColor: '#EE8F57',
success: function(res) {
if (res.confirm == true) {
plus.runtime.install( //安装
downloadResult.tempFilePath, {
force: true
},
function(res) {
utils.showToast('更新成功,重启中');
plus.runtime.restart();
}
);
}
}
});
}
}
});
}
}
}
</script>
<style>
.btn_text {
margin-top: 28rpx;
width: auto;
font-size: 28rpx;
color: #616161;
}
</style>
二、在pages下面创建一个目录,我的名字叫cms,在cms下创建一个vue文件,我的叫news_list.vue,代码如下:
<template>
<view>
<uni-nav-bar :title="title" backgroundColor="#d3233b" color="#ffffff" fixed="true"></uni-nav-bar>
<view v-for="art in articleList">
<view style="height: 240rpx;">
<image :src="imgPath+art.logo" style="border-radius: 3px; float: left;width: 200rpx;height: 200rpx;margin-left: 20rpx;margin-right: 20rpx;margin-top: 20rpx;"></image>
<view style="padding-top: 20rpx;padding-right: 20rpx;font-size: 30rpx;color: black;">
<button @click="doContent(art.id)" type="primary" size="mini" style="margin-right: 10rpx;">{{art.name}}</button></view>
</view>
<view style="height: 1px;margin-top: 20rpx;margin-left: 15rpx;margin-right: 15rpx;background-color: #d4d4d4;"></view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
imgPath: 'http://localhost:8060',
articleList: null,
cid: null,//栏目id
title: null//显示栏目名称
}
},
onLoad(options) {
this.cid = options.cid;
this.title = options.title;
console.log("栏目id:"+this.cid);
},
onShow() {
this.requestArticles();
},
methods: {
/*请求文章列表*/
requestArticles(){
uni.request({
url: 'http://localhost:8082/article/list?cid='+this.cid,
success: (res) => {
this.articleList = res.data.data;
console.log(this.articleList);
}
})
},
/*点击内容按钮时触发*/
doContent(id){
uni.navigateTo({
url: "../article/article_content?aid="+id
})
}
}
}
</script>
<style>
</style>
三、把上午写的article_content.vue文件复制到此项目中,稍作修改,把右边的文本框、图片等去掉,只留下展示图片,代码如下:
<template>
<view>
<!-- 导入导航栏-->
<uni-nav-bar backgroundColor="#d3233b" color="#ffffff" title="律行法务后台管理系统"></uni-nav-bar>
<uni-nav-bar @clickLeft="back()" fixed="true" leftIcon="back" leftText="返回" title="文章内容"></uni-nav-bar>
<view class="uni-flex uni-row" style="-webkit-justify-content: center;justify-content: center; margin-top: 30rpx; margin-left: auto; margin-right: auto; width: 60rpx;">
<view
style="width: 640rpx; height: 960rpx; margin-right: 10rpx; padding: 20rpx; border: 1px solid #000000; border-radius: 10rpx;">
<scroll-view scroll-y="true" style="height: 960rpx;">
<view v-for="content in contentList">
<view v-if="content.type == 'txt'">
{{content.value}}
</view>
<view v-if="content.type == 'img'">
<image :src="imgPath+content.value"></image>
</view>
</view>
</scroll-view>
</view>
</view>
<!-- 提示框 -->
<uni-popup ref="popup" type="dialog">
<uni-popup-dialog mode="base" title="通知" :content="msg" :duration="2000" :before-close="true" @close="close"
@confirm="confirm"></uni-popup-dialog>
</uni-popup>
</view>
</template>
<script>
var _self;
export default {
data() {
return {
imgPath: "http://localhost:8060",
msg: '',
aid: null,
articleValue: null,
contentList:null
}
},
onLoad(options) {
this.aid = options.aid;
},
onShow() {
this.requestContentList();
},
methods: {
open() {
this.$refs.popup.open()
},
/**
* 点击取消按钮触发
* @param {Object} done
*/
close() {
// TODO 做一些其他的事情,before-close 为true的情况下,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
/**
* 点击确认按钮触发
* @param {Object} done
* @param {Object} value
*/
confirm(value) {
// 输入框的值
// console.log(value)
// TODO 做一些其他的事情,手动执行 close 才会关闭对话框
// ...
this.$refs.popup.close()
},
back() {
uni.navigateBack();
},
doTxt(){ //点击上传文本
this.requestSave('txt',this.articleValue);
},
doImg(){ //点击上传图片
_self = this;
//选择图片
uni.chooseImage({
count: 1,//图片数量
sizeType:['original'],//原图
sourceType:['album'],//从相册选择
success: (res) => {
const tempFilePaths = res.tempFilePaths;//获取选择好的图片路径
//上传选择好的图片
uni.uploadFile({
url: 'http://localhost:8082/upload/file',
filePath: tempFilePaths[0],//上传图片第几个
name: 'file',//上传的图片名字
success: (res) => {
var relativePath = res.data;//获取问阿金图片上传后的相对路径
_self.requestSave('img',relativePath);
}
})
}
})
},
/*获取文章内容列表*/
requestContentList(){
uni.request({
url: "http://localhost:8082/content/list?aid="+this.aid,
success: (res) => {
this.contentList=res.data.data;
console.log(this.contentList);
}
})
},
/*保存内容*/
requestSave(type,value){
uni.request({
url: 'http://localhost:8082/content/add',
data: {
aid: this.aid,
type: type,
value: value
},
success: (res) => {
if(res.data.code == 200){//保存成功
this.msg = res.data.data;
this.requestContentList();
}else{//保存失败
this.msg = res.data.msg;
}
this.open();//弹出警告对话框
}
})
}
}
}
</script>
<style>
</style>
四、检查pages.json文件下的路径,因为我把article和content整个文件夹都复制过来了,所以路径有点多,我的代码如下:
{
"pages": [{
"path": "pages/main/main",
"style": {
"navigationBarTitleText": "uni-app"
}
},{
"path" : "pages/cms/news_list",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/content/content",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/content/content_add",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/content/content_update",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/article/article",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/article/article_add",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/article/article_update",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
},{
"path" : "pages/article/article_content",
"style" :
{
"navigationBarTitleText": "",
"enablePullDownRefresh": false
}
}
],
"globalStyle": {
"navigationStyle": "custom",
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8",
"app-plus": {
"background": "#efeff4"
}
}
}
五、进行测试。
1、在main页面运行到火狐浏览器,如下图:
2、点击热点事件,如下图:
3、点击第四篇文章,名字是新添加的文章,如下图:
如此,我们就实现嵌套查询的功能了。