由于“织梦接入百度小程序demo”没有一个官方的、现成的、一键可用的Demo包,我们将分步创建一个从零到一的完整Demo示例,包括织梦端的数据接口改造和小程序端的调用。

整体思路
-
织梦端(后端):
- 创建一个API接口文件(
api.php),用于接收小程序的请求。 - 在接口文件中,编写PHP代码,从织梦数据库中获取所需数据(如文章列表、文章详情)。
- 将获取到的数据转换成JSON格式并返回给小程序。
- 创建一个API接口文件(
-
百度小程序端(前端):
- 使用百度小程序开发者工具创建一个新项目。
- 在项目中,使用
swan.request()方法来调用织梦端创建的API接口。 - 接收并解析返回的JSON数据,然后渲染到页面上,展示给用户。
第一步:织梦端改造 - 创建API接口
织梦本身是一个内容发布系统,它的前端页面是使用PHP模板引擎渲染的,不适合小程序直接调用,我们需要为小程序专门提供数据接口。
创建API目录和入口文件
为了不干扰织梦原有的文件结构,我们建议在网站根目录下创建一个专门的API目录,baidu_api。

你的网站根目录/
├── dede/ (织梦后台核心目录)
├── templets/ (织梦模板目录)
├── uploads/ (附件目录)
└── baidu_api/ <-- 新建这个目录
├── index.php <-- API统一入口文件
└── article/ <-- 存放不同模块的API文件
├── list.php <-- 获取文章列表
└── detail.php <-- 获取文章详情
编写API统一入口文件 baidu_api/index.php
这个文件的作用是接收请求,并根据参数调用不同的API处理文件,这是一种常见的路由模式。
<?php
/**
* 百度小程序API统一入口
*/
// 设置响应头为JSON格式
header('Content-Type: application/json; charset=utf-8');
// 引入织梦的核心文件,以便使用其数据库等全局变量
// 注意:根据你的织梦安装路径调整 '../dede' 的值
require_once '../dede/config.php';
require_once '../dede/common.inc.php';
// 获取小程序传来的参数
$action = isset($_GET['action']) ? trim($_GET['action']) : '';
// 根据action参数,分发到不同的处理文件
switch ($action) {
case 'article_list':
// 引入文章列表处理文件
include 'article/list.php';
break;
case 'article_detail':
// 引入文章详情处理文件
include 'article/detail.php';
break;
default:
// 如果没有匹配的action,返回错误信息
$response = [
'code' => -1,
'msg' => '无效的请求参数',
'data' => null
];
echo json_encode($response, JSON_UNESCAPED_UNICODE);
break;
}
?>
编写获取文章列表的API baidu_api/article/list.php
这个文件负责从织梦数据库中查询文章列表,并返回JSON数据。
<?php
/**
* 获取文章列表API
*/
// 定义返回数据结构
$response = [
'code' => 0,
'msg' => 'success',
'data' => []
];
// 获取分页参数
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$pageSize = isset($_GET['pageSize']) ? intval($_GET['pageSize']) : 10; // 每页显示10条
// 计算偏移量
$offset = ($page - 1) * $pageSize;
// 从织梦的 `dede_archives` 表中查询文章
// 这里只查询推荐文章,你可以根据需要修改条件
$sql = "SELECT a.id, a.title, a.pubdate, a.click, c.typename
FROM dede_archives a
LEFT JOIN dede_arctype c ON a.typeid = c.id
WHERE a.ismake = 1 AND a.arcrank > -1
ORDER BY a.id DESC
LIMIT {$offset}, {$pageSize}";
$dsql = new DedeSQL(false);
$dsql->SetQuery($sql);
$dsql->Execute('list');
$articles = [];
while ($row = $dsql->GetArray('list')) {
// 处理数据,使其符合小程序前端的需求
$articles[] = [
'id' => $row['id'],
'title' => $row['title'],
'pubdate' => date('Y-m-d H:i:s', $row['pubdate']), // 格式化时间
'click' => $row['click'],
'typename' => $row['typename'],
'url' => 'https://你的域名.com/article.php?id=' . $row['id'] // 原PC文章链接
];
}
$response['data']['list'] = $articles;
$response['data']['page'] = $page;
$response['data']['pageSize'] = $pageSize;
// 输出JSON数据
echo json_encode($response, JSON_UNESCAPED_UNICODE);
?>
编写获取文章详情的API baidu_api/article/detail.php
这个文件负责根据文章ID查询文章详情。
<?php
/**
* 获取文章详情API
*/
$response = [
'code' => 0,
'msg' => 'success',
'data' => null
];
// 获取文章ID
$id = isset($_GET['id']) ? intval($_GET['id']) : 0;
if (empty($id)) {
$response['code'] = -1;
$response['msg'] = '文章ID不能为空';
echo json_encode($response, JSON_UNESCAPED_UNICODE);
exit;
}
// 从织梦数据库查询文章详情
$sql = "SELECT * FROM dede_archives WHERE id = {$id}";
$dsql = new DedeSQL(false);
$dsql->SetQuery($sql);
$dsql->Execute('detail');
if ($row = $dsql->GetArray('detail')) {
// 获取文章正文内容
// 注意:织梦的文章内容在 `dede_addonarticle` 表中
$aid = $row['id'];
$bodySql = "SELECT body FROM dede_addonarticle WHERE aid = {$aid}";
$dsql->SetQuery($bodySql);
$dsql->Execute('body');
$bodyRow = $dsql->GetArray('body');
// 处理数据
$response['data'] = [
'id' => $row['id'],
'title' => $row['title'],
'pubdate' => date('Y-m-d H:i:s', $row['pubdate']),
'content' => $bodyRow['body'] // 返回文章内容
];
} else {
$response['code'] = -2;
$response['msg'] = '文章不存在';
}
echo json_encode($response, JSON_UNESCAPED_UNICODE);
?>
至此,织梦端的API接口已经准备完毕。 你可以通过浏览器访问 https://你的域名.com/baidu_api/index.php?action=article_list 来测试接口是否正常返回JSON数据。

第二步:百度小程序端开发
现在我们开始创建百度小程序,并调用上面创建的API。
创建小程序项目
使用百度智能小程序开发者工具,创建一个新的小程序项目。
配置域名
在小项目的 app.json 文件中,需要在 networkRequest 域名白名单中添加你的织梦网站域名。
{
"pages": [
"pages/index/index",
"pages/detail/detail"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "织梦Demo",
"navigationBarTextStyle": "black"
},
"debug": true,
"networkRequest": {
"domains": [
"你的域名.com" <!-- 添加你的域名 -->
]
}
}
创建首页并调用文章列表API
文件结构:
pages/
└── index/
├── index.js (逻辑层)
├── index.json (配置层)
├── index.swan (视图层)
└── index.css (样式层)
pages/index/index.js (逻辑层)
// 获取应用实例
const app = getApp()
Page({
data: {
articleList: [], // 存储文章列表
page: 1,
pageSize: 10,
hasMore: true // 是否有更多数据
},
onLoad: function () {
this.fetchArticleList();
},
// 上拉加载更多
onReachBottom: function () {
if (this.data.hasMore) {
this.setData({
page: this.data.page + 1
});
this.fetchArticleList(true); // 传入true表示追加数据
}
},
// 获取文章列表的方法
fetchArticleList: function (isAppend = false) {
const that = this;
swan.request({
url: 'https://你的域名.com/baidu_api/index.php', // 你的API地址
data: {
action: 'article_list',
page: this.data.page,
pageSize: this.data.pageSize
},
method: 'GET',
success: (res) => {
console.log('获取文章列表成功', res);
if (res.data.code === 0) {
const newList = res.data.data.list;
// 如果是新的一页且没有数据,则说明没有更多了
if (newList.length === 0 && !isAppend) {
that.setData({
hasMore: false
});
return;
}
// 追加或替换数据
const finalList = isAppend ? [...this.data.articleList, ...newList] : newList;
that.setData({
articleList: finalList,
hasMore: newList.length === this.data.pageSize // 如果返回数量小于请求数量,说明没有更多了
});
} else {
swan.showToast({
title: res.data.msg || '获取失败',
icon: 'none'
});
}
},
fail: (err) => {
console.error('获取文章列表失败', err);
swan.showToast({
title: '网络请求失败',
icon: 'none'
});
}
});
},
// 跳转到文章详情页
goToDetail: function (e) {
const articleId = e.currentTarget.dataset.id;
swan.navigateTo({
url: `/pages/detail/detail?id=${articleId}`
});
}
});
pages/index/index.swan (视图层)
<view class="container">
<view class="article-list">
<block s-for="item in articleList" key="item.id">
<view class="article-item" bindtap="goToDetail" data-id="{{item.id}}">
<view class="article-title">{{item.title}}</view>
<view class="article-info">
<text class="article-type">{{item.typename}}</text>
<text class="article-date">{{item.pubdate}}</text>
</view>
</view>
</block>
</view>
<!-- 没有更多数据时的提示 -->
<view s-if="!hasMore && articleList.length > 0" class="no-more">
没有更多了
</view>
</view>
pages/index/index.css (样式层)
.container {
padding: 20rpx;
}
.article-item {
padding: 30rpx 0;
border-bottom: 1rpx solid #eee;
}
.article-title {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 10rpx;
}
.article-info {
font-size: 24rpx;
color: #888;
}
.article-type, .article-date {
margin-right: 20rpx;
}
.no-more {
text-align: center;
color: #999;
padding: 20rpx 0;
}
创建文章详情页
文件结构:
pages/
└── detail/
├── detail.js
├── detail.json
├── detail.swan
└── detail.css
pages/detail/detail.js (逻辑层)
Page({
data: {
article: null
},
onLoad: function (options) {
const id = options.id;
if (id) {
this.fetchArticleDetail(id);
}
},
fetchArticleDetail: function (id) {
const that = this;
swan.request({
url: 'https://你的域名.com/baidu_api/index.php',
data: {
action: 'article_detail',
id: id
},
method: 'GET',
success: (res) => {
console.log('获取文章详情成功', res);
if (res.data.code === 0) {
that.setData({
article: res.data.data
});
} else {
swan.showToast({
title: res.data.msg || '获取详情失败',
icon: 'none'
});
}
},
fail: (err) => {
console.error('获取文章详情失败', err);
swan.showToast({
title: '网络请求失败',
icon: 'none'
});
}
});
}
});
pages/detail/detail.swan (视图层)
<view class="container" s-if="{{article}}">
<view class="article-title">{{article.title}}</view>
<view class="article-info">
<text>{{article.pubdate}}</text>
</view>
<view class="article-content">
<rich-text nodes="{{article.content}}"></rich-text>
</view>
</view>
<view s-else class="loading">
加载中...
</view>
pages/detail/detail.css (样式层)
.container {
padding: 20rpx;
}
.article-title {
font-size: 36rpx;
font-weight: bold;
text-align: center;
padding: 30rpx 0;
}
.article-info {
text-align: center;
color: #888;
font-size: 24rpx;
margin-bottom: 20rpx;
}
.article-content {
font-size: 30rpx;
line-height: 1.8;
}
/* rich-text 样式可能需要额外处理,取决于织梦返回的HTML内容 */
.article-content >>> img {
max-width: 100%;
height: auto;
}
.loading {
text-align: center;
padding-top: 200rpx;
}
总结与注意事项
-
安全性:上面的API接口是公开的,任何人都可以调用,在实际生产环境中,你必须增加身份验证机制,
- Token验证:小程序在请求时携带一个Token,织梦后端验证Token的有效性。
- 签名验证:通过密钥对请求参数进行签名,防止请求被篡改。
- IP白名单:只允许特定IP(如小程序服务器)访问API。
-
内容过滤:织梦返回的
content字段是HTML格式。rich-text组件对HTML的支持有限,可能会出现样式错乱,可以考虑使用第三方库(如htmlparser2)或者在后端将HTML转换成小程序支持的nodes格式。 -
性能优化:如果文章列表数据量很大,可以考虑为API接口增加缓存(如使用Redis),或者对数据库查询进行优化。
-
图片域名:确保织梦文章中的图片域名也配置在小程序的
networkRequest域名白名单中。 -
HTTPS:百度小程序要求所有网络请求必须使用
HTTPS协议,请确保你的网站已经配置了SSL证书。
通过以上步骤,你就成功地将织梦CMS与百度小程序连接起来,实现了一个可以展示文章列表和详情的完整Demo,你可以基于这个Demo进行扩展,增加更多功能,如搜索、评论、用户登录等。
