下面我将为你提供一个非常详细、完整的分步教程,包含了从数据库准备到前端实现的全部代码。

核心思路
- 数据准备:在数据库中创建三个表(或一个表)来存储省、市、区的数据。
- 前端结构:在自定义表单中创建三个
<select>下拉框,分别对应省、市、区。 - 数据加载:
- 页面加载时,通过 AJAX 请求获取所有省份数据,并填充到“省份”下拉框。
- 当用户选择一个“省份”时,通过 AJAX 请求该省份下的所有城市数据,并填充到“城市”下拉框,同时清空“区/县”下拉框。
- 当用户选择一个“城市”时,通过 AJAX 请求该城市下的所有区县数据,并填充到“区/县”下拉框。
- 后端支持:创建一个专门的 PHP 文件(如
ajax_area.php),用于接收前端请求,查询数据库,并返回 JSON 格式的数据。 - 表单提交:确保这三个字段的
name属性与你在自定义表单后台定义的字段名一致,这样提交的数据才能被正确保存。
第一步:准备数据库数据
最简单的方式是创建三个独立的表:dede_pinyin (省), dede_pinyin_city (市), dede_pinyin_area (区)。
创建省份表 dede_pinyin
CREATE TABLE `dede_pinyin` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `name` varchar(120) NOT NULL COMMENT '省份名称', `pinyin` varchar(120) NOT NULL COMMENT '省份拼音', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
创建城市表 dede_pinyin_city
CREATE TABLE `dede_pinyin_city` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `pid` int(10) unsigned NOT NULL COMMENT '所属省份ID', `name` varchar(120) NOT NULL COMMENT '城市名称', `pinyin` varchar(120) NOT NULL COMMENT '城市拼音', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
创建区县表 dede_pinyin_area

CREATE TABLE `dede_pinyin_area` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `cid` int(10) unsigned NOT NULL COMMENT '所属城市ID', `name` varchar(120) NOT NULL COMMENT '区县名称', `pinyin` varchar(120) NOT NULL COMMENT '区县拼音', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
导入数据
你需要手动或通过脚本向这三个表中导入中国的省、市、区数据,网上有很多现成的 SQL 数据文件可以下载,这是最省时省力的方法。
第二步:创建 DedeCMS 自定义表单
- 登录 DedeCMS 后台。
- 进入 [核心] -> [内容模型管理] -> [自定义表单]。
- 点击 [增加一个自定义表单]。
- 填写表单信息:
- 表单名称:
用户反馈(或你想要的任何名称) - 默认表单模板:
[field:html /](保持默认) - 信息提示模板:
提交成功!(或跳转链接)
- 表单名称:
- 点击 [保存]。
- 在表单管理页面,点击你刚创建的表单名称进入字段管理。
- 增加三个字段:
- 字段名:
sheng(英文名,用于 JS 识别)- :
省份 - 字段类型:
下拉菜单 - 选项值:
(留空,将由JS动态填充)
- :
- 字段名:
shi- :
城市 - 字段类型:
下拉菜单 - 选项值:
(留空)
- :
- 字段名:
qu- :
区/县 - 字段类型:
下拉菜单 - 选项值:
(留空)
- :
- 字段名:
- 保存字段设置,现在你的数据库
dede_sysdiy表和dede_sysdiy_field表中已经有了这三个新字段。
第三步:创建 AJAX 数据处理文件
在网站根目录下创建一个名为 ajax_area.php 的文件,并粘贴以下代码:
<?php
/**
* DedeCMS 省市区三级联动 AJAX 数据接口
* 作者:Your Name
* 日期:2025-10-27
*/
require_once (dirname(__FILE__) . "/include/common.inc.php");
require_once DEDEINC."/datalistcp.class.php";
// 设置 header 为 JSON
header('Content-Type: application/json; charset=utf-8');
$action = isset($action) ? trim($action) : '';
// 获取省份列表
if ($action == 'getProvinces') {
$dsql = new DedeSql(false);
$sql = "SELECT id, name FROM `dede_pinyin` ORDER BY id ASC";
$dsql->SetQuery($sql);
$dsql->Execute('pro');
$provinces = array();
while ($row = $dsql->GetArray('pro')) {
$provinces[] = $row;
}
echo json_encode($provinces);
exit;
}
// 获取城市列表
if ($action == 'getCitys') {
$province_id = isset($province_id) ? intval($province_id) : 0;
if ($province_id > 0) {
$dsql = new DedeSql(false);
$sql = "SELECT id, name FROM `dede_pinyin_city` WHERE pid = {$province_id} ORDER BY id ASC";
$dsql->SetQuery($sql);
$dsql->Execute('citys');
$citys = array();
while ($row = $dsql->GetArray('citys')) {
$citys[] = $row;
}
echo json_encode($citys);
} else {
echo json_encode(array()); // 返回空数组
}
exit;
}
// 获取区县列表
if ($action == 'getAreas') {
$city_id = isset($city_id) ? intval($city_id) : 0;
if ($city_id > 0) {
$dsql = new DedeSql(false);
$sql = "SELECT id, name FROM `dede_pinyin_area` WHERE cid = {$city_id} ORDER BY id ASC";
$dsql->SetQuery($sql);
$dsql->Execute('areas');
$areas = array();
while ($row = $dsql->GetArray('areas')) {
$areas[] = $row;
}
echo json_encode($areas);
} else {
echo json_encode(array()); // 返回空数组
}
exit;
}
// 如果没有匹配的 action,返回错误
echo json_encode(array('error' => 'Invalid action'));
exit;
?>
第四步:修改表单模板文件
找到你的自定义表单模板文件,通常位于 /templets/plus/ 目录下,文件名类似于 diy_form.htm。

-
引入 jQuery 库: 在
<head>标签内,确保引入了 jQuery 库,如果你的模板没有,可以添加:<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
-
修改 HTML 结构: 找到之前创建的省份、城市、区县三个下拉菜单的 HTML 代码,确保它们的
name属性和id属性正确,并添加一个onchange事件来触发联动。修改前 (可能的样子):
<select name='sheng' id='sheng'> <option value=''>请选择省份</option> </select> <select name='shi' id='shi'> <option value=''>请选择城市</option> </select> <select name='qu' id='qu'> <option value=''>请选择区/县</option> </select>修改后 (推荐的样子):
<tr> <td height="30">所在地区:</td> <td> <select name="sheng" id="sheng" style="width:120px;" onchange="getCitys(this.value)"> <option value="">请选择省份</option> </select> <select name="shi" id="shi" style="width:120px;" onchange="getAreas(this.value)"> <option value="">请选择城市</option> </select> <select name="qu" id="qu" style="width:150px;"> <option value="">请选择区/县</option> </select> </td> </tr> -
编写 JavaScript 联动代码: 在
<head>标签内或页面底部的</body>标签之前,添加以下 JS 代码:<script type="text/javascript"> $(function(){ // 页面加载时,获取所有省份 $.get("/ajax_area.php", { action: "getProvinces" }, function(data){ if(data.length > 0){ var html = "<option value=''>请选择省份</option>"; for(var i = 0; i < data.length; i++){ html += "<option value='" + data[i].id + "'>" + data[i].name + "</option>"; } $("#sheng").html(html); } }, "json"); }); // 获取城市列表 function getCitys(province_id){ if(province_id > 0){ $.get("/ajax_area.php", { action: "getCitys", province_id: province_id }, function(data){ var html = "<option value=''>请选择城市</option>"; if(data.length > 0){ for(var i = 0; i < data.length; i++){ html += "<option value='" + data[i].id + "'>" + data[i].name + "</option>"; } } $("#shi").html(html); // 清空区县列表 $("#qu").html("<option value=''>请选择区/县</option>"); }, "json"); } else { $("#shi").html("<option value=''>请选择城市</option>"); $("#qu").html("<option value=''>请选择区/县</option>"); } } // 获取区县列表 function getAreas(city_id){ if(city_id > 0){ $.get("/ajax_area.php", { action: "getAreas", city_id: city_id }, function(data){ var html = "<option value=''>请选择区/县</option>"; if(data.length > 0){ for(var i = 0; i < data.length; i++){ html += "<option value='" + data[i].id + "'>" + data[i].name + "</option>"; } } $("#qu").html(html); }, "json"); } else { $("#qu").html("<option value=''>请选择区/县</option>"); } } </script>
第五步:测试与最终提交
- 检查文件路径:确保
ajax_area.php文件已上传到网站根目录,jQuery 库路径正确。 - 刷新页面:清空浏览器缓存,重新打开你的自定义表单页面。
- 测试联动:
- 页面加载后,“省份”下拉框应该自动填充所有省份。
- 选择一个省份后,“城市”下拉框应立即填充对应的城市,并清空“区/县”。
- 选择一个城市后,“区/县”下拉框应立即填充对应的区县。
- 提交表单:填写完其他必填项后,提交表单,登录后台,在自定义表单管理中查看数据,你应该能看到
sheng,shi,qu三个字段中分别存储了你选择的省、市、区的 ID。
可选优化:保存名称而非 ID
目前我们保存的是数据库中的 id,如果你希望保存的是具体的“省、市、区”名称,你需要稍微修改一下。
方法一(推荐):修改 JS 提交逻辑
在表单提交前,用选中的文本替换 value 值。
// 在你的表单提交按钮的 onclick 事件中,或者在表单的 onsubmit 事件中添加以下逻辑
function checkForm() {
// ... 其他验证 ...
// 获取选中的文本并替换value
$('#sheng option:selected').each(function() {
$(this).val($(this).text());
});
$('#shi option:selected').each(function() {
$(this).val($(this).text());
});
$('#qu option:selected').each(function() {
$(this).val($(this).text());
});
document.diyform.submit(); // 提交表单
return true;
}
将提交按钮的 onclick 事件修改为 onclick="return checkForm()"。
修改后端处理
在 ajax_area.php 中,查询数据时同时获取 id 和 name,然后在 JS 中将 value 设置为 name,这种方法更直接,但需要修改前端的 html 构建部分。
// JS 代码中的循环部分修改为 html += "<option value='" + data[i].name + "'>" + data[i].name + "</option>";
这样,提交到数据库的就是中文名称了。
这个教程已经非常全面,涵盖了从零开始实现省市区联动的所有关键步骤,按照这个流程操作,你一定可以成功实现,祝你使用愉快!
