我们将采用最主流、最稳定的方式:利用织梦的自定义表单和JS联动,这种方法的好处是:

(图片来源网络,侵删)
- 无需修改核心文件:升级织梦时不会丢失功能。
- 兼容性好:适用于织梦5.7及大部分后续版本。
- 灵活性高:可以轻松添加更多联动项。
核心思路
- 创建数据表:建立一个专门存储联动选项的数据表,
dede_addonsoft(你可以自定义表名),用来存储“地区”和“行业”的层级关系。 - 添加数据:向数据表中手动录入“省份-城市”和“行业大类-子行业”的数据。
- 创建自定义表单:在后台创建一个自定义表单,用于生成前端的HTML选择框(
<select>)。 - 编写联动JS:编写JavaScript代码,监听上级选择框的变化,通过AJAX请求从数据库获取下级选项,并动态填充到下级选择框中。
详细步骤
第一步:创建数据表并添加数据
-
登录你的PHPMyAdmin,找到你的织梦数据库。
-
执行SQL语句创建新表(你可以命名为
dede_linkage_data,或者任何你喜欢的名字):CREATE TABLE `dede_linkage_data` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `pid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父ID,0为顶级', `name` varchar(50) NOT NULL COMMENT '选项名称', `type` varchar(20) NOT NULL COMMENT '类型,如:area, industry', PRIMARY KEY (`id`), KEY `pid` (`pid`), KEY `type` (`type`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8;
id: 每个选项的唯一ID。pid: 父级ID,顶级(如“广东省”)的pid为0,其下级(如“广州市”)的pid就是顶级选项的id。name: 选项显示的名称,如“广东省”、“互联网”。type: 用于区分不同的联动类型,area”代表地区,“industry”代表行业。
-
向表中添加数据:
地区数据示例:
- 顶级 (pid=0)
- id: 1, name: '广东省', pid: 0, type: 'area'
- id: 2, name: '北京市', pid: 0, type: 'area'
- 广东省的子级 (pid=1)
- id: 101, name: '广州市', pid: 1, type: 'area'
- id: 102, name: '深圳市', pid: 1, type: 'area'
- id: 103, name: '东莞市', pid: 1, type: 'area'
- 北京市的子级 (pid=2)
- id: 201, name: '朝阳区', pid: 2, type: 'area'
- id: 202, name: '海淀区', pid: 2, type: 'area'
行业数据示例:
- 顶级 (pid=0)
- id: 1001, name: '互联网', pid: 0, type: 'industry'
- id: 1002, name: '金融', pid: 0, type: 'industry'
- 互联网的子级 (pid=1001)
- id: 1101, name: '电子商务', pid: 1001, type: 'industry'
- id: 1102, name: '软件开发', pid: 1001, type: 'industry'
- 金融的子级 (pid=1002)
- id: 1201, name: '银行', pid: 1002, type: 'industry'
- id: 1202, name: '证券', pid: 1002, type: 'industry'
你可以直接在PHPMyAdmin中手动插入这些数据,也可以写一个批量导入的SQL脚本。
- 顶级 (pid=0)
第二步:创建自定义表单
- 登录织梦后台,进入【核心】 -> 【内容模型管理】 -> 【自定义表单】。
- 点击【增加一个自定义表单】,填写表单信息:
- 表单名称:填写一个你容易识别的名字,如
企业信息提交。 - 数据表:系统会自动生成一个表名,如
dede_addonsoft,保持默认即可。 - 默认表单模板:保持默认。
- 列表模板:保持默认。
- 会员投稿项:根据需要选择。
- 表单名称:填写一个你容易识别的名字,如
- 添加表单字段:
- 点击你刚创建的表单,进入字段管理。
- 我们需要添加两个字段:
province(省份) 和city(城市)。 - 点击【添加新字段】。
- 字段名称:
province - 字段类型:
select(下拉选择框) - 字段提示:
省份 - 默认值:留空
- 选项:这里先不填! 我们将通过JS动态加载。
- 是否必填:根据需要选择。
- 字段名称:
- 再次点击【添加新字段】。
- 字段名称:
city - 字段类型:
select(下拉选择框) - 字段提示:
城市 - 默认值:
请先选择省份 - 选项:同样先不填。
- 是否必填:根据需要选择。
- 字段名称:
- 用同样的方法为行业添加
main_industry(行业大类) 和sub_industry(子行业) 字段。
第三步:编写联动JS代码
这是实现联动的核心,我们需要一个JS文件来处理数据请求和DOM操作。
-
创建JS文件: 在你的模板目录(如
/templets/default/)下,创建一个名为linkage.js的文件。 -
编写JS代码: 将以下代码复制到
linkage.js文件中。// 等待整个文档加载完成 document.addEventListener('DOMContentLoaded', function() { // 1. 地区联动逻辑 const provinceSelect = document.getElementById('province'); // 获取省份下拉框 const citySelect = document.getElementById('city'); // 获取城市下拉框 if (provinceSelect && citySelect) { // 页面加载时,获取并填充所有省份 loadOptions(provinceSelect, 'area', 0); // 监听省份选择框的变化 provinceSelect.addEventListener('change', function() { const selectedProvinceId = this.value; // 清空城市下拉框 citySelect.innerHTML = '<option value="">请选择城市</option>'; // 如果选择了省份,则加载对应的城市 if (selectedProvinceId) { loadOptions(citySelect, 'area', selectedProvinceId); } }); } // 2. 行业联动逻辑 const mainIndustrySelect = document.getElementById('main_industry'); // 获取行业大类下拉框 const subIndustrySelect = document.getElementById('sub_industry'); // 获取子行业下拉框 if (mainIndustrySelect && subIndustrySelect) { // 页面加载时,获取并填充所有行业大类 loadOptions(mainIndustrySelect, 'industry', 0); // 监听行业大类选择框的变化 mainIndustrySelect.addEventListener('change', function() { const selectedMainIndustryId = this.value; // 清空子行业下拉框 subIndustrySelect.innerHTML = '<option value="">请选择子行业</option>'; // 如果选择了行业大类,则加载对应的子行业 if (selectedMainIndustryId) { loadOptions(subIndustrySelect, 'industry', selectedMainIndustryId); } }); } /** * 通用的函数:用于加载指定父ID和类型的选项 * @param {HTMLElement} selectElement - 要填充的下拉框DOM元素 * @param {string} type - 数据类型 ('area' 或 'industry') * @param {number} pid - 父级ID */ function loadOptions(selectElement, type, pid) { // 使用织梦自带的全局变量获取网站根目录 const rootDir = dede_jsurl; const ajaxUrl = rootDir + '/linkage.php'; // 我们将创建这个PHP文件来处理AJAX请求 // 创建一个空的option,避免闪烁 selectElement.innerHTML = '<option value="">加载中...</option>'; // 使用Fetch API发送AJAX请求 fetch(ajaxUrl + '?type=' + type + '&pid=' + pid) .then(response => { if (!response.ok) { throw new Error('Network response was not ok'); } return response.json(); // 期望服务器返回JSON数据 }) .then(data => { // 清空当前下拉框(除了第一个提示选项) selectElement.innerHTML = ''; if (data.length === 0) { selectElement.innerHTML = '<option value="">暂无数据</option>'; return; } // 遍历返回的数据,创建并添加option元素 data.forEach(item => { const option = document.createElement('option'); option.value = item.id; option.textContent = item.name; selectElement.appendChild(option); }); }) .catch(error => { console.error('Error fetching linkage data:', error); selectElement.innerHTML = '<option value="">加载失败</option>'; }); } });
第四步:创建处理AJAX请求的PHP文件
这个PHP文件负责接收JS的请求,从数据库查询数据,并以JSON格式返回。
-
创建PHP文件: 在你的网站根目录(与
/dede/同级)下,创建一个名为linkage.php的文件。 -
编写PHP代码: 将以下代码复制到
linkage.php文件中。<?php /** * 织梦联动数据获取接口 * 用法: /linkage.php?type=area&pid=1 */ // 引入数据库配置文件 require_once (dirname(__FILE__) . "/include/config_global.php"); require_once DEDEINC . '/dedesql.class.php'; // 创建数据库连接实例 $dsql = new Dedesql(false); $dsql->SetQuery("SELECT id, name FROM `#@__linkage_data` WHERE pid = '{$_GET['pid']}' AND type = '{$_GET['type']}'"); $dsql->Execute('al'); $options = array(); while ($row = $dsql->GetArray('al')) { $options[] = array( 'id' => $row['id'], 'name' => $row['name'] ); } // 设置响应头为JSON格式 header('Content-Type: application/json; charset=utf-8'); // 输出JSON数据 echo json_encode($options); // 关闭数据库连接 $dsql->Close(); ?>- 注意:请将
#@__linkage_data修改为你第一步中创建的表名。 config_global.php和dedesql.class.php是织梦的核心文件,确保路径正确。
- 注意:请将
第五步:在前端页面引入并使用
-
在表单模板中引入JS: 打开你的自定义表单模板文件(通常在
/templets/你的模板/plus/list_表单ID.htm)。 在<head>标签内或页面底部引入我们创建的linkage.js文件。<script type="text/javascript" src="{dede:global.cfg_cmsurl/}/templets/default/linkage.js"></script>{dede:global.cfg_cmsurl//}是织梦的标签,用于获取网站根目录,确保路径正确。
-
确保表单字段的ID正确: 在表单模板中,检查你的两个下拉框,确保它们的
id属性与JS代码中获取的ID完全一致。<p>省份: <select name="province" id="province"> <!-- 选项将由JS动态填充 --> </select> </p> <p>城市: <select name="city" id="city"> <option value="">请先选择省份</option> </select> </p> <p>行业大类: <select name="main_industry" id="main_industry"> <!-- 选项将由JS动态填充 --> </select> </p> <p>子行业: <select name="sub_industry" id="sub_industry"> <option value="">请先选择行业大类</option> </select> </p>
总结与检查
完成以上步骤后,访问你的自定义表单页面,你应该能看到:
- 页面加载时,“省份”和“行业大类”下拉框会自动从数据库加载顶级选项。
- 当你选择一个省份后,“城市”下拉框会自动更新,显示该省份下的所有城市。
- 当你选择一个行业大类后,“子行业”下拉框也会自动更新。
如果出现问题,请按以下顺序检查:
- 数据库表和数据:确认表名、字段名和数据是否正确。
- PHP文件路径:确认
linkage.php是否在网站根目录,并且能正常访问(直接在浏览器输入http://你的域名/linkage.php?type=area&pid=0看是否能返回JSON数据)。 - JS文件路径:确认
linkage.js的引入路径是否正确。 - 表单字段ID:确认HTML中
<select>的id和JS中获取的ID是否一致。 - 浏览器控制台:按F12打开开发者工具,查看Console(控制台)是否有JS错误,Network(网络)面板中
linkage.php的请求是否成功及返回了什么数据。
这个方案功能完整且稳定,是解决织梦CMS中多级联动问题的标准做法。
