实际案例-业务办理¶
1 插件功能设计¶
插件用途:支持用户提交开通手机卡的办理请求,客服接收后手动联系处理。
1.1 插件使用流程说明¶
1.1.1 用户流程(业务视角)¶
-
用户访问网站域名,进入西瓜分类信息首页:
plugin.php?id=xigua_hb -
点击“手机计划办理”入口,跳转至插件页面:
plugin.php?id=xigua_simtelecom -
页面展示所有可选套餐内容,用户选择套餐项。
-
用户填写办理表单:姓名、手机号(必填,需验证)、地址、电子邮箱。
-
用户勾选同意协议并提交。
-
系统接收后执行以下操作:
- 验证信息合法性;
- 自动生成唯一订单编号(如:
SIM20240527-00001); - 将数据写入数据库表;
- 发送邮件通知后台客服。
-
客服查看邮件后联系用户处理订单。
-
后台管理者可在 Discuz 后台查看并更新处理状态。
1.2 功能模块分解(技术视角)¶
1.2.1 前端模块¶
-
套餐选择区域
- 形式:单选框或图文列表(多选一,必选)
- 显示:套餐名、价格、说明
-
信息录入表单
- 姓名(必填)
- 手机号码(必填)
- 地址(必填)
- 邮箱(必填)
- 协议确认(必选)
-
提交逻辑
- 校验表单项
- 弹窗反馈提交成功/失败
- 自动生成订单编号(规则:
SIM+ 日期 + 序号)
该表单需在用户点击“提交申请”按钮时进行严格的数据校验,确保信息完整、格式正确,并避免垃圾或无效数据写入数据库。校验需覆盖前端(用户体验)和后端(安全保障)两个层面。
校验字段列表与要求
| 字段名称 | 表单字段名 | 是否必填 | 验证规则 | 校验层级 | 错误提示 |
|---|---|---|---|---|---|
| 套餐选择 | package | 是 | 必须选择一个非空项 | 前端 + 后端 | 请选择套餐 |
| 姓名 | username | 是 | 非空 | 前端 + 后端 | 请输入姓名 |
| 手机号码 | phone | 是 | 仅限中国大陆号段(11位)或北美号段(10位) | 前端 + 后端 | 请输入有效的中国或北美手机号 |
| 邮箱地址 | 是 | 标准 Email 格式 | 前端 + 后端 | 请输入有效邮箱地址 | |
| 联系地址 | address | 是 | 非空,最大长度 100 个字符 | 前端 + 后端 | 地址不能为空且不超过100字符 |
| 协议勾选 | N/A | 是 | 用户必须勾选同意协议项 | 前端 | 请阅读并同意《办理协议》和《隐私协议》 |
说明补充:
- 手机号验证规则:
- 中国大陆手机号:^1[3-9]\d{9}$
- 美国/加拿大手机号:^\d{10}$(默认不含区号)
- 邮箱格式规则:
- 使用正则:/[@\s]+@[@\s]+.[@\s]+$/
- 地址字段限制:
- TEXT 类型,但前端需限制输入长度不超过 100 字符,避免滥用
- 协议勾选:
- 不勾选则禁止提交,仅需前端控制
校验责任分层说明
| 校验内容 | 前端是否实现 | 后端是否必须实现 | 原因 |
|---|---|---|---|
| 必填项检查 | ✅ | ✅ | 避免空值插入数据库 |
| 正则格式检查 | ✅ | ✅ | 防止脚本绕过前端 |
| 协议勾选 | ✅ | 可选 | 用户交互为主,服务器一般不校验 |
| 异常提示 | ✅(alert()) | ✅(showmessage()) | 及时反馈用户错误 |
1.2.2 后端服务处理¶
-
数据存储
- 表结构保存字段:套餐名、用户信息、提交时间、订单编号、处理状态
-
邮件通知
- 提交成功后自动发送邮件给客服邮箱
1.3 后台管理功能(管理员视角)¶
-
订单状态更新
- 管理员可筛选所有订单,查看详细信息
- 支持更新处理状态(未处理 / 已联系 / 已完成)
-
管理界面建议
- 可留出“处理人”字段用于分配任务
- 可在插件后台菜单中添加管理页入口(admin.inc.php)
1.4 后续可扩展内容(预留)¶
- 支持短信验证码(阿里云短信接口)
- 支持小程序 API 接口提交
- 支持用户端查询订单状态
- 记录操作日志便于跟踪办理过程
1.5 订单编号规则说明¶
2 插件开发总流程(开发视角 + 初始化流程融合)¶
2.1 开启开发模式(环境准备)¶
- 本地路径:
D:\3 Work\58halifax\58haiwailife\MyDev\xigua_simtelecom - 打开 VSCode + Chrome DevTools,开启移动模拟器
- 可同步 SSH 到服务器部署测试路径
2.2 创建插件目录结构(Discuz 规范)¶
xigua_simtelecom/
├── file/ # ⬅️ 用户上传资料 / 客服二维码图片
│ └── CSWechatBQ.png # 示例:客服微信二维码
│
├── inc/
│ └── xigua_simtelecom_order.inc.php # 商户端订单处理
│
├── table/
│ └── table_xigua_simtelecom.php # 数据表封装
│
├── template/
│ ├── front/
│ │ └── manage_order_list.htm # PC端订单查看
│
│ ├── static/
│ │ ├── custom.css
│ │ └── iconfont.woff2
│
│ └── touch/
│ ├── user_order_form.htm # ✅ 用户提交订单页
│ ├── manage_order_list.htm # ✅ 商户订单列表
│ ├── dialog_noupdate.htm
│ ├── dialog_privacy.htm
│ ├── dialog_success_update.htm
│ ├── dialog_terms.htm
│ ├── common_header.php
│ └── common_footer.php
│
├── plugin.xml
├── install.php / uninstall.php
├── xigua_simtelecom.inc.php # 插件默认入口
└── xigua_simtelecom.lang.php
上传至云服务器:
- 打开 MobaXterm,使用 SSH 连接你的生产环境
- 登录后,左侧“SFTP”窗口将自动显示远程文件系统
- 浏览到远程路径
- 拖拽到文件完成上传临时目录:
/home/ecs-user/tmp/xigua_simtelecom - 在服务器上拷贝到目标目录:
rsync -av --update /home/ecs-user/tmp/xigua_simtelecom/ /www/wwwroot/58haiwai_life/source/plugin/xigua_simtelecom/ - 或使用命令行:
scp -r ....
2.3 编写插件描述文件 plugin.xml¶
- 设置
<identifier>xigua_simtelecom</identifier> - 指定
<directory>source/plugin/xigua_simtelecom/</directory> - 添加语言文件、后台菜单、扩展项(可选)
- 注册安装/卸载脚本:
<?xml version="1.0" encoding="utf-8"?>
<plugin>
<identifier>xigua_simtelecom</identifier>
<name>电信业务办理</name>
<version>1.0</version>
<description>提供用户提交手机卡开通请求的插件,适配移动端</description>
<copyright>西蒙2.0</copyright>
<directory>source/plugin/xigua_simtelecom/</directory>
<language>./xigua_simtelecom.lang.php</language>
<script>xigua_simtelecom.inc.php</script>
<installfile>install.php</installfile>
<uninstallfile>uninstall.php</uninstallfile>
<modules>
</modules>
</plugin>
2.4 设计数据表结构(可选)¶
- 表名建议:
pre_xigua_simtelecom_log - 封装类命名:
table_simtelecom.php - 类继承
discuz_table并实现insert()方法 - 配合 install.php 自动建表
<?php
if (!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
exit('Access Denied');
}
$sql = <<<EOF
CREATE TABLE IF NOT EXISTS `pre_xigua_simtelecom_log` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`orderid` VARCHAR(30) NOT NULL DEFAULT '',
`username` VARCHAR(100) NOT NULL DEFAULT '',
`phone` VARCHAR(20) NOT NULL DEFAULT '',
`package` VARCHAR(100) NOT NULL DEFAULT '',
`address` TEXT,
`email` VARCHAR(100) DEFAULT '',
`status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0=未处理, 1=已联系, 2=已完成',
`operator` VARCHAR(50) DEFAULT '' COMMENT '客服处理人',
`dateline` INT(10) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `orderid` (`orderid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
ALTER TABLE pre_xigua_simtelecom_log
ADD COLUMN uid INT(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '用户ID',
ADD COLUMN username_dz VARCHAR(50) NOT NULL DEFAULT '' COMMENT 'Discuz用户名',
ADD COLUMN userip VARCHAR(45) NOT NULL DEFAULT '' COMMENT '用户IP地址';
EOF;
runquery($sql);
$finish = true;
<?php
if (!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
exit('Access Denied');
}
$sql = <<<EOF
DROP TABLE IF EXISTS `pre_xigua_simtelecom_log`;
EOF;
runquery($sql);
$finish = true;
2.5 编写插件主逻辑入口 .inc.php¶
- 判断是否 POST 提交
- 表单校验 → 写入数据库 → 返回 showmessage
- 否则加载模板
<?php
// 防止非法访问(Discuz常规保护机制)
if (!defined('IN_DISCUZ')) {
exit('Access Denied');
}
// 引入数据表封装类,便于操作自定义数据表(本插件为 table_xigua_simtelecom)
require_once DISCUZ_ROOT.'./source/plugin/xigua_simtelecom/table/table_xigua_simtelecom.php';
// 加载语言缓存(Discuz 平台预定义机制)
loadcache('pluginlanguage_template');
// 引入插件语言包(多语言支持)
// 使用 @ 忽略加载失败时的 PHP warning
@include_once DISCUZ_ROOT . './data/plugindata/xigua_simtelecom.lang.php';
// 将插件语言包注入 $_G['lang'] 全局变量,供模板/JS 使用
if (isset($lang) && is_array($lang)) {
$_G['lang'] = array_merge($_G['lang'], $lang);
}
// 点击协议文字跳转至独立页面
if ($_GET['mod'] == 'protocol' && in_array($_GET['doc'], ['terms', 'privacy'])) {
$tpl = "touch/protocol_" . $_GET['doc'];
include template("xigua_simtelecom:$tpl");
exit;
}
// 插入函数定义
/**
* 从插件后台配置中读取套餐选项并返回键值数组
* 支持配置格式:每行一个套餐名称,或用中文分号“;”分隔
*
* @return array 示例:['package1' => '基础套餐', 'package2' => '增强套餐', ...]
*/
function xigua_get_packages() {
global $_G;
$packages = array();
$raw = $_G['cache']['plugin']['xigua_simtelecom']['package_options'] ?? '';
// 分割:支持 \n、\r\n、中文分号;
$option_lines = preg_split("/\r?\n|;/", $raw);
$i = 1;
foreach ($option_lines as $line) {
$line = trim($line);
if ($line !== '') {
$packages['package' . $i] = $line;
$i++;
}
}
return $packages;
}
// 判断是否为 POST 请求,并校验表单哈希(防 CSRF 攻击)
if ($_SERVER['REQUEST_METHOD'] === 'POST' && submitcheck('ordersubmit')) {
// 获取并过滤表单字段,防止 XSS 注入
$username = dhtmlspecialchars(trim($_POST['username']));
$phone = dhtmlspecialchars(trim($_POST['phone']));
$address = dhtmlspecialchars(trim($_POST['address']));
$email = dhtmlspecialchars(trim($_POST['email']));
// 读取套餐映射
$packages = xigua_get_packages();
// 获取套餐编号和映射中文名
$package = dhtmlspecialchars(trim($_POST['package']));
$package_display = $packages[$package] ?? $package;
// 强制校验协议勾选字段(防用户跳过前端校验提交)
if (empty($_POST['agree'])) {
showmessage('请先阅读并同意协议');
}
// 校验:姓名为必填项
if (!$username) {
showmessage('请填写姓名');
}
// 校验:手机号为必填项
if (!$phone) {
showmessage('请填写手机号');
}
// 校验:手机号支持中国/北美(10或11位数字)
if (!preg_match('/^(1[3-9]\d{9}|[2-9]\d{2}[2-9]\d{2}\d{4})$/', $phone)) {
showmessage('请输入有效的中国或北美手机号(不需输入国家代码)');
}
// 校验:邮箱格式建议使用内置过滤器,更准确
if (!$email || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
showmessage('请输入有效邮箱地址');
}
// 校验:地址不能为空且不超过100字符(注意中文字符需用 mb_strlen)
if (!$address || mb_strlen($address, 'UTF-8') > 100) {
showmessage('地址不能为空,且不超过100个字符');
}
// 生成唯一订单编号:SIM + 年月日时分秒 + 4位随机数
$orderid = 'SIM' . date('YmdHis') . random(4, 1);
// 构造插入数据库所需数据结构
$data = array(
'orderid' => $orderid,
'username' => $username,
'phone' => $phone,
'package' => $package_display,
'address' => $address,
'email' => $email,
'dateline' => TIMESTAMP, // 当前 UNIX 时间戳
'uid' => $_G['uid'] ?? 0, // 当前用户 ID(游客为0)
'username_dz' => $_G['username'] ?? '', // 当前用户在 Discuz 系统中的用户名
'userip' => $_G['clientip'] ?? '', // 记录 IP,便于风控分析
);
// 使用封装类执行插入操作,符合插件开发规范
$table = new table_xigua_simtelecom();
$table->insert($data);
// 发送通知邮件至客服
include_once libfile('function/mail');
// 获取套餐中文名(来自前面生成的 $packages 数组)
$packages = xigua_get_packages();
$package_display = $packages[$package] ?? $package;
// 当前时间格式化
$time_str = date('Y-m-d H:i:s');
$message_body = <<<EOF
有一位用户提交了SIM卡业务申请,信息如下:<br>
姓名:{$username}<br>
手机号:{$phone}<br>
邮箱:{$email}<br>
套餐:{$package_display}<br>
地址:{$address}<br>
提交时间:{$time_str}<br>
用户IP:{$_G['clientip']}<br>
UID/用户名:{$_G['uid']} / {$_G['username']}<br>
EOF;
sendmail('284641883@qq.com', '【新订单通知】SIM卡业务申请提交成功', $message_body);
// 返回跳转
// showmessage('提交成功,我们会尽快与您联系', 'plugin.php?id=xigua_simtelecom', array(), '', 3); // 3 表示页面跳转
// exit;
//showmessage('提交成功,我们会尽快与您联系', 'plugin.php?id=xigua_simtelecom', array(), array('refreshtime' => 5, 'alert' => 'right'));
// 成功提示页
$tpl = checkmobile() ? 'touch/success_dialog' : 'success_dialog';
include template("xigua_simtelecom:$tpl");
exit;
} else {
// 从插件配置读取套餐选项
$packages = xigua_get_packages();
// 非提交请求:根据访问设备类型加载不同模板
$tpl = checkmobile() ? 'touch/front_order_form' : 'front_order_form';
include template("xigua_simtelecom:$tpl");
}
<?php
if (!defined('IN_DISCUZ')) {
exit('Access Denied');
}
class table_xigua_simtelecom extends discuz_table {
public function __construct() {
// 设置数据表名称,Discuz 会自动加前缀 pre_
$this->_table = 'xigua_simtelecom_log';
$this->_pk = 'id';
parent::__construct();
}
/**
* 插入新数据
* @param array $data 插入的数据数组
* @return int 返回插入记录的主键ID
*/
public function insert($data) {
if (!is_array($data) || empty($data)) {
return 0;
}
return DB::insert($this->_table, $data, true);
}
/**
* 根据订单ID获取记录
* @param string $orderid
* @return array|null
*/
public function fetch_by_orderid($orderid) {
return DB::fetch_first("SELECT * FROM %t WHERE orderid=%s", array($this->_table, $orderid));
}
/**
* 获取所有记录(用于后台展示)
* @param int $start 起始
* @param int $limit 数量
* @return array
*/
public function fetch_all($start = 0, $limit = 20) {
return DB::fetch_all("SELECT * FROM %t ORDER BY dateline DESC LIMIT %d, %d", array($this->_table, $start, $limit));
}
}
2.6 编写表单模板 .htm 文件¶
- 模拟微信小程序/移动风格
- 使用
{$lang['key']}调用语言 - 支持响应式布局
- 校验用户输入
<!DOCTYPE html>
<!-- 保留原有多系统 class,可用于响应式样式控制 -->
<html lang="zh-cmn-Hans" class="pixel-ratio-2 retina ios ios-16 ios-16-6 ios-gt-15 ios-gt-14 ios-gt-13 ios-gt-12 ios-gt-11 ios-gt-10 ios-gt-9 ios-gt-8 ios-gt-7 ios-gt-6">
<head>
<meta charset="UTF-8">
<!-- viewport-fit=cover 可配合安全区域适配 iOS 刘海屏 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<title>58海外</title>
<link rel="stylesheet" href="source/plugin/xigua_simtelecom/template/static/custom.css">
</head>
<body>
<!-- 页头模板 -->
<!--{template xigua_simtelecom:touch/common_header}-->
<!-- 表单区域 -->
<!-- 表单区域容器,避让顶部 header 与底部 footer -->
<div class="page__content" style="padding-top: 2.2rem; padding-bottom: 2.6rem;">
<!-- 表单开始 -->
<form method="post" autocomplete="off" action="plugin.php?id=xigua_simtelecom" class="weui-form">
<!-- CSRF 防护字段 -->
<input type="hidden" name="formhash" value="{FORMHASH}">
<!-- 提交标识字段 -->
<input type="hidden" name="ordersubmit" value="yes">
<!-- 套餐选择(动态) -->
<div class="weui-cell weui-cell_select">
<div class="weui-cell__bd">
<select class="weui-select" name="package" required>
<option value="">{$lang['simtelecom_package']}</option>
<!--{loop $packages $key $val}-->
<option value="{$key}">{$val}</option>
<!--{/loop}-->
</select>
</div>
</div>
<!-- 姓名输入框:添加 required + maxlength 限制 -->
<div class="weui-cell">
<div class="weui-cell__bd">
<input class="weui-input"
type="text"
name="username"
placeholder="{$lang['simtelecom_name']}"
required
maxlength="20" />
<!-- 姓名限制最多 30 字符,避免溢出和非法内容 -->
</div>
</div>
<!-- 手机号输入框:添加 required + maxlength(中国手机号11位) -->
<div class="weui-cell">
<div class="weui-cell__bd">
<input class="weui-input"
type="tel"
name="phone"
placeholder="{$lang['simtelecom_phone']}"
required
maxlength="15" />
<!-- 最大长度留出扩展空间(国际用户) -->
</div>
</div>
<!-- 邮箱输入框:添加 required + maxlength 限制 -->
<div class="weui-cell">
<div class="weui-cell__bd">
<input class="weui-input"
type="email"
name="email"
placeholder="{$lang['simtelecom_email']}"
required
maxlength="50" />
<!-- 邮箱最大长度常规建议 50 字符以内 -->
</div>
</div>
<!-- 地址输入框:添加 required + maxlength 限制(100 字) -->
<div class="weui-cell">
<div class="weui-cell__bd">
<textarea class="weui-textarea"
rows="2"
name="address"
placeholder="{$lang['simtelecom_address']}"
required
maxlength="100"></textarea>
<!-- 限制最大 100 字,防止后端字段溢出 -->
</div>
</div>
<!-- 协议勾选区域(用户必须同意协议) -->
<div style="padding: 1em;" class="">
<div style="display: flex; align-items: center; gap: 0.5em; font-size: 0.8em; flex-wrap: nowrap;">
<input type="checkbox" name="agree" value="1" required="" style="width: 1.1em !important; height: 1.1em !important;">
<span class="weui-agree__text" style="line-height: 1.6; flex: 1; word-break: break-word;">
我已阅读并同意
<a href="plugin.php?id=xigua_simtelecom&mod=protocol&doc=terms" style="color: #337ab7; text-decoration: none;">《办理协议》</a>
和
<a href="plugin.php?id=xigua_simtelecom&mod=protocol&doc=privacy" style="color: #337ab7; text-decoration: none;">《隐私协议》</a>
</span>
</div>
</div>
<!-- 提交按钮:保留 JS 触发,按钮 type 设为 button 避免误提交 -->
<div class="weui-btn-area" style="margin: 0.1em auto 0.1em !important;">
<button type="button"
class="weui-btn weui-btn_primary"
aria-label="提交申请">{$lang['simtelecom_submit']}</button>
</div>
<!-- 办理须知公告栏 -->
<div style="
margin: 0.2em auto 0.5em;
padding: 0.5em 0.5em;
max-width: 95%;
font-size: 0.58rem;
color: #555;
background-color: #f8f8f8;
border-radius: 2px;
line-height: 1.8;
">
<strong style="display:block; margin-bottom: 0.1em;">办理须知:</strong>
1. 我们联合电信是专业的电信服务商,已有 20+ 年行业经验,与多家大型电信公司合作,提供高质量的服务,信誉卓著。<br>
2. 电信套餐计划可能会不定期调整,您提交订单后,我们的客服人员将在工作时间 15 分钟内与您联系,确认套餐有效性并协助您选择最合适的方案。<br>
3. 可根据需要提供上门办理服务。
</div>
</div>
<!-- 错误提示容器:样式简单但兼容性强,支持移动端 -->
<div id="toast" style="
display: none;
background: #ff552e;
color: white;
padding: 10px;
border-radius: 5px;
position: fixed;
top: 20%;
left: 50%;
transform: translateX(-50%);
z-index: 9999;
max-width: 80%;
font-size: 14px;
text-align: center;">
<p id="toastMsg"></p>
</div>
<!-- 前端校验逻辑增强版:含重复提交锁 + 转义 + 可访问性支持 -->
<script>
document.addEventListener('DOMContentLoaded', function () {
const btn = document.querySelector('.weui-btn_primary');
const form = document.querySelector('.weui-form');
const toast = document.getElementById('toast');
const toastMsg = document.getElementById('toastMsg');
// 提示框安全转义输出
function escapeHtml(str) {
return str.replace(/[&<>'\"]/g, c => ({
'&': '&', '<': '<', '>': '>', '\"': '"', '\'': '''
}[c]));
}
function showToast(msg) {
toastMsg.innerHTML = escapeHtml(msg);
toast.style.display = 'block';
setTimeout(() => { toast.style.display = 'none'; }, 2000);
}
// 表单按钮点击绑定校验逻辑
btn.addEventListener('click', function () {
// 防止重复提交(4秒内锁定按钮)
if (btn.disabled) return;
btn.disabled = true;
setTimeout(() => { btn.disabled = false; }, 4000);
const pkg = form.package.value.trim();
const name = form.username.value.trim();
const phone = form.phone.value.trim();
const email = form.email.value.trim();
const address = form.address.value.trim();
const agree = form.querySelector('input[name="agree"]').checked;
const phoneReg = /^(1[3-9]\d{9}|[2-9]\d{2}[2-9]\d{2}\d{4})$/;
const emailReg = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
if (!pkg) { showToast('请选择套餐计划'); return; }
if (!name) { showToast('请输入您的姓名'); return; }
if (!phone || !phoneReg.test(phone)) { showToast('请输入有效的中国或北美手机号(不需输入国家代码)'); return; }
if (!email || !emailReg.test(email)) { showToast('请输入正确邮箱'); return; }
if (!address || address.length > 100) { showToast('请填写地址(不超过100字)'); return; }
if (!agree) { showToast('请勾选协议'); return; }
// 只在校验通过后提交表单
form.submit();
});
});
</script>
<!-- 页脚模板 -->
<!--{template xigua_simtelecom:touch/common_footer}-->
</body>
</html>
<!-- 页面顶部头部栏 -->
<header class="x_header bgcolor_11 cl f15">
<!-- 左侧返回按钮,使用浏览器后退功能 -->
<a class="z f14" href="javascript:window.history.go(-1);">
<!-- 返回图标(通过 iconfont 字体图标显示) -->
<i class="iconfont icon-fanhuijiantou w15"></i>返回
</a>
<!-- 中间标题文本,显示当前页面名称 -->
<div class="navtitle">电信业务办理</div>
</header>
<!-- 简化移动端底部模板 -->
<!-- 底部导航栏,使用 WeUI 组件样式 -->
<div class="weui-tabbar">
<!-- 首页 Tab 按钮,当前处于选中状态 -->
<a href="plugin.php?id=xigua_hb" class="weui-tabbar__item weui-bar__item_on">
<i class="iconfont icon-home_fill_light weui-tabbar__icon"></i>
<p class="weui-tabbar__label">首页</p>
</a>
<!-- 发布 Tab 按钮,带有发布按钮的特殊圆形背景 -->
<a href="plugin.php?id=xigua_hb&ac=pub&needlogin=1" class="weui-tabbar__item weui-bar__item_on showpubfont">
<div class="pub_circle"></div>
<i class="iconfont icon-fabu1 weui-tabbar__icon"></i>
<p class="weui-tabbar__label pub_circle_p" style="color:#555!important">发布</p>
</a>
<!-- 我的 Tab 按钮 -->
<a href="plugin.php?id=xigua_hb&ac=my&needlogin=1" class="weui-tabbar__item">
<i class="iconfont icon-wode weui-tabbar__icon"></i>
<p class="weui-tabbar__label">我的</p>
</a>
</div>
2.7 引用样式文件 .css¶
- 复用西瓜插件中主色调/字体样式 (custom.css,iconfont.css,iconfont.woff2,iconfont.ttf等)
2.8 编写语言文件 .lang.php¶
- 命名为
xigua_simtelecom.lang.php
<?php
$lang = array(
'simtelecom_package' => '请选择套餐计划',
'simtelecom_name' => '您的姓名',
'simtelecom_phone' => '您的手机号码(中国或美加手机号码,不需要输入国家代码)',
'simtelecom_email' => '您的电子邮箱',
'simtelecom_address' => '您的住址',
'simtelecom_submit' => '提交订单',
);
2.9 编写 install/uninstall.php(自动建表)¶
<?php
if (!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
exit('Access Denied');
}
$sql = <<<EOF
CREATE TABLE IF NOT EXISTS `pre_xigua_simtelecom_log` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`orderid` VARCHAR(30) NOT NULL DEFAULT '',
`username` VARCHAR(100) NOT NULL DEFAULT '',
`phone` VARCHAR(20) NOT NULL DEFAULT '',
`package` VARCHAR(100) NOT NULL DEFAULT '',
`address` TEXT,
`email` VARCHAR(100) DEFAULT '',
`status` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0=未处理, 1=已联系, 2=已完成',
`operator` VARCHAR(50) DEFAULT '' COMMENT '客服处理人',
`dateline` INT(10) UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `orderid` (`orderid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
EOF;
runquery($sql);
$finish = true;
<?php
if (!defined('IN_DISCUZ') || !defined('IN_ADMINCP')) {
exit('Access Denied');
}
$sql = <<<EOF
DROP TABLE IF EXISTS `pre_xigua_simtelecom_log`;
EOF;
runquery($sql);
$finish = true;
2.10 本地测试与部署¶
- 在 Discuz 后台 → 插件 → 安装
xigua_simtelecom - 访问地址测试:
plugin.php?id=xigua_simtelecom - 用 Chrome 模拟器(F12) → 手机尺寸调试样式
- 验证:
- 表单是否提交成功
- 数据是否写入(可用 SQL 工具查看)
- 页面是否兼容移动端显示
3 可扩展功能¶
- 插件配置项:plugin.xml →
<vars>添加配置(如启用开关)- 在插件后台「变量」页配置套餐内容(如:basic=基础套餐, plus=增强套餐)
- 前端
- 后端也能获取套餐名对应中文
| 场景 | 功能点 |
|---|---|
| ① 前端模板 | 动态生成 |
| ② 表单处理 | 将套餐编号写入数据库,并显示对应中文 |
| ③ 邮件通知 | 套餐显示为后台配置中的中文项 |
| ④ 将来拓展 | 可做套餐分析、筛选、后台管理等功能 |
// 插入函数定义
/**
* 从插件后台配置中读取套餐选项并返回键值数组
* 支持配置格式:每行一个套餐名称,或用中文分号“;”分隔
*
* @return array 示例:['package1' => '基础套餐', 'package2' => '增强套餐', ...]
*/
function xigua_get_packages() {
global $_G;
$packages = array();
$raw = $_G['cache']['plugin']['xigua_simtelecom']['package_options'] ?? '';
// 分割:支持 \n、\r\n、中文分号;
$option_lines = preg_split("/\r?\n|;/", $raw);
$i = 1;
foreach ($option_lines as $line) {
$line = trim($line);
if ($line !== '') {
$packages['package' . $i] = $line;
$i++;
}
}
return $packages;
}
// 读取套餐映射
$packages = xigua_get_packages();
// 获取套餐编号和映射中文名
$package = dhtmlspecialchars(trim($_POST['package']));
$package_display = $packages[$package] ?? $package;
if ($_SERVER['REQUEST_METHOD'] === 'POST' && submitcheck('ordersubmit')) {
...
} else {
// 从插件配置读取套餐选项
$packages = xigua_get_packages();
// 非提交请求:根据访问设备类型加载不同模板
$tpl = checkmobile() ? 'touch/front_order_form' : 'front_order_form';
include template("xigua_simtelecom:$tpl");
}
<!-- 套餐选择(动态) -->
<div class="weui-cell weui-cell_select">
<div class="weui-cell__bd">
<select class="weui-select" name="package" required>
<option value="">{$lang['simtelecom_package']}</option>
<!--{loop $packages $key $val}-->
<option value="{$key}">{$val}</option>
<!--{/loop}-->
</select>
</div>
</div>
- 邮件通知客服
- 当用户在前台提交电信办理表单后:后台立即发一封包含用户提交信息的邮件至客服邮箱。
// 发送通知邮件至客服
include_once libfile('function/mail');
// 获取套餐中文名(来自前面生成的 $packages 数组)
$packages = xigua_get_packages();
$package_display = $packages[$package] ?? $package;
// 当前时间格式化
$time_str = date('Y-m-d H:i:s');
$message_body = <<<EOF
有一位用户提交了SIM卡业务申请,信息如下:<br>
姓名:{$username}<br>
手机号:{$phone}<br>
邮箱:{$email}<br>
套餐:{$package_display}<br>
地址:{$address}<br>
提交时间:{$time_str}<br>
用户IP:{$_G['clientip']}<br>
UID/用户名:{$_G['uid']} / {$_G['username']}<br>
EOF;
sendmail('284641883@qq.com', '【新订单通知】SIM卡业务申请提交成功', $message_body);
4. 业务后台管理功能¶
4.1 需求规划¶
需求本质是:为多个外部业务服务商(如电信、快递、租房等)分别提供独立的“数据管理后台”,但不开放 Discuz 的后台管理中心权限。
采用“前台权限控制 + 管理界面”方式实现,这样做的优势:
1) 隔离权限安全性高:外部商户无法访问 Discuz 核心后台;
2) 业务定制灵活性强:每个业务模块可以单独设计操作页面和权限;
3) 风格统一更好控制:你可以做成移动端后台、桌面样式后台、或轻量 UI;
4) 扩展性好:便于日后每类业务维护多个服务商账号。
4.2 结构设计(多业务多商户管理规划)¶
xigua_partnercenter/
├── admin_account.inc.php # 后台管理子账号
├── admin_setting.inc.php # 插件业务注册配置页面
├── table/
│ └── table_xigua_partnercenter_account.php # 商户账号数据表操作类
├── template/
│ ├── front/(暂未用到)
│ ├── static/(暂未用到)
│ └── touch/(暂未用到)
├── plugin.xml # 注册插件和后台菜单(待扩展为配置业务插件列表)
├── install.php / uninstall.php # 安装/卸载逻辑(如初始化商户账户表)
├── xigua_partnercenter.inc.php # 插件入口,按 biz=xxx 分发业务处理
└── xigua_partnercenter.lang.php # 插件语言包
├── xigua_simtelecom/
│ └── … ← 业务提交页面、表单、用户表结构、逻辑
├── xigua_express/
│ └── … ← 快递业务表单、提交、管理逻辑
各插件职责分离
| 插件名 | 职责说明 |
|---|---|
| xigua_simtelecom | 提供电信业务套餐提交、订单入库等 |
| xigua_express | 提供快递寄件信息提交等 |
| xigua_partnercenter | 商户独立登录、订单管理、权限控制,支持多个业务类型的统一入口 |
partnercenter 插件的作用
1) 为所有商户(如电信、快递代理)提供统一的登录与权限管理;
2) 为每个业务调用其插件的数据表,如 pre_xigua_simtelecom_log, pre_xigua_express_log;
3) 每个业务有独立的子控制器(如 simtelecom_order.inc.php);
4) 商户通过前台入口如 plugin.php?id=xigua_partnercenter:partner&biz=simtelecom 访问。
CREATE TABLE IF NOT EXISTS $table (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
uid INT(10) UNSIGNED NOT NULL COMMENT '商户UID',
biz_type VARCHAR(30) NOT NULL COMMENT '业务类型标识',
permission_level TINYINT DEFAULT 1 COMMENT '权限等级,默认1',
status TINYINT DEFAULT 1 COMMENT '状态:1启用,0禁用',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
merchant_type TINYINT DEFAULT 1 COMMENT '商户类型:1=个人,2=企业',
PRIMARY KEY (id),
UNIQUE KEY uid_biz (uid, biz_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
4.3 实际文件结构规划¶
source/plugin/
├── xigua_partnercenter/ ← 商户管理中心插件(多业务管理平台)
│ ├── admin_account.inc.php # 后台管理子账号
│ ├── admin_setting.inc.php # 插件业务注册配置页面
│ ├── table/
│ │ └── table_xigua_partnercenter_account.php # 商户账号数据表操作类
│ ├── template/
│ │ ├── front/(暂未用到)
│ │ ├── static/(暂未用到)
│ │ └── touch/(暂未用到)
│ ├── plugin.xml # 注册插件和后台菜单(待扩展为配置业务插件列表)
│ ├── install.php / uninstall.php # 安装/卸载逻辑(如初始化商户账户表)
│ ├── xigua_partnercenter.inc.php # 插件入口,按 biz=xxx 分发业务处理
│ └── xigua_partnercenter.lang.php # 插件语言包
├── xigua_simtelecom/
│ ├── file/ # ⬅️ 用户上传资料 / 客服二维码图片
│ │ └── CSWechatBQ.png # 示例:客服微信二维码
│ │
│ ├── inc/ # 控制器逻辑(商户端处理)
│ │ └── xigua_simtelecom_order.inc.php # 商户端订单处理
│ │
│ ├── table/ # 数据表操作封装类
│ │ └── table_xigua_simtelecom.php # 数据表封装
│ │
│ ├── template/ # 模板资源
│ │ ├── front/ # PC端模板(如后台报表)
│ │ │ └── manage_order_list.htm # PC端订单查看
│ │
│ │ ├── static/ # 静态资源(css/icon等)
│ │ │ ├── custom.css
│ │ │ └── iconfont.woff2
│ │
│ │ └── touch/ # 移动端模板(用户/商户/公共)
│ │ ├── user_order_form.htm # ✅ 用户提交订单页
│ │ ├── manage_order_list.htm # ✅ 商户订单列表
│ │ ├── dialog_noupdate.htm # 弹窗:无需更新提示
│ │ ├── dialog_privacy.htm # 弹窗:隐私协议
│ │ ├── dialog_success_update.htm # 弹窗:提交成功提示
│ │ ├── dialog_terms.htm # 弹窗:服务条款
│ │ ├── common_header.php # 公共页头
│ │ └── common_footer.php # 公共页脚(建议补全)
│ │
│ ├── plugin.xml # 插件定义文件
│ ├── install.php / uninstall.php # 安装与卸载脚本
│ ├── xigua_simtelecom.inc.php # 插件默认入口(用户默认页)
│ └── xigua_simtelecom.lang.php # 插件语言包
4.4 插件开发¶
4.4.1 数据表设计 pre_table_xigua_partnercenter_account¶
数据表设计目标(业务视角)
我们需要记录并控制哪些用户是商户,以及:
| 功能需求 | 是否需要字段 |
|---|---|
| 一个用户可关联多个业务类型(如电信/快递) | ✅ biz_type |
| 可扩展多个商户 | ✅ uid 作为主身份 |
| 商户可启用/禁用 | ✅ status |
| 商户是否有权限访问此业务 | ✅ permission_level 或 bool |
| 记录商户添加时间(便于审计) | ✅ created_at |
| 后续可扩展商户类型(企业/个人) | ⚠️ 可留字段 merchant_type |
CREATE TABLE pre_xigua_partnercenter_account (
id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
uid INT(10) UNSIGNED NOT NULL COMMENT '用户UID',
biz_type VARCHAR(30) NOT NULL COMMENT '业务标识,如 simtelecom/express',
permission_level TINYINT DEFAULT 1 COMMENT '权限等级,1为普通权限',
status TINYINT DEFAULT 1 COMMENT '状态:1启用,0禁用',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
merchant_type TINYINT DEFAULT 1 COMMENT '预留:商户类型(1个人 2企业)',
PRIMARY KEY (id),
UNIQUE KEY uid_biz (uid, biz_type)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
字段设计说明:
| 字段名 | 类型 | 含义及用途说明 |
|---|---|---|
| id | 自增主键 | 表内唯一识别 |
| uid | 用户ID | 商户绑定的 Discuz 用户 |
| biz_type | VARCHAR | 表示业务模块(如 simtelecom) |
| permission_level | TINYINT | 权限等级,便于日后做权限分层 |
| status | TINYINT | 0=禁用,1=启用 |
| created_at | DATETIME | 添加时间,方便审计 |
| merchant_type | TINYINT | 留作扩展字段,可设置个人/企业商户 |
| UNIQUE(uid, biz_type) | 联合唯一索引 | 保证一个用户只能在某业务下出现一次 |
4.4.2 插件基础配置文件 plugin.xml¶
这是插件在 Discuz! 后台识别、安装、加载的核心文件。
4.4.3 插件主控制器 xigua_partnercenter.inc.php¶
这是商户通过 plugin.php?id=xigua_partnercenter 访问时的统一入口,用于权限判断并分发到具体业务子模块。
核心功能说明:
1) 判断用户是否已登录;
2) 校验当前 UID 是否为注册商户(查询 pre_xigua_partner_account);
3) 根据请求参数 biz=simtelecom 跳转到对应控制器(如 inc/simtelecom_order.inc.php);
4) 默认提供业务列表(可选)。
注意事项:
1) 如果后续你添加新业务(如 express),只需添加 express_order.inc.php 并更新 $allowed_biz;
2) 所有子业务控制器共享当前用户信息 $_G['uid'] 和 $partner 商户记录。
| :---------------- | :------- | :---------------------- |
| 一个商户多个业务 | ✅ | 每条记录一个业务标识 |
| 商户启用/停用控制 | ✅ | 使用 status 字段 |
| 扩展商户角色/类型 | ✅ | 留出 merchant_type |
| 后续支持权限细分 | ✅ | permission_level 可调整 |
4.4.4 商户权限封装类 table_xigua_partnercenter_account.php¶
该类用于读取 pre_table_xigua_partnercenter_account 表,判断当前用户是否为商户、拥有何种权限、支持哪些业务类型等。
使用建议:
1) 主控器中通过 get_by_uid() 或 get_by_uid_and_biz() 进行身份校验;
2) 后台可扩展接口或脚本管理商户账号权限;
3) 若后期做 API 接入也可重用该封装类。
<?php
if (!defined('IN_DISCUZ')) {
exit('Access Denied');
}
// 商户账号权限表封装类:对应表 pre_xigua_partnercenter_account
class table_xigua_partnercenter_account extends discuz_table {
public function __construct() {
$this->_table = 'xigua_partnercenter_account'; // 表名(不带前缀)
$this->_pk = 'id';
parent::__construct();
}
/**
* 获取指定用户在指定业务下的有效商户信息
*/
public function get_by_uid_and_biz($uid, $biz_type) {
return DB::fetch_first(
"SELECT * FROM %t WHERE uid=%d AND biz_type=%s AND status=1",
array($this->_table, $uid, $biz_type)
);
}
/**
* 插入或更新商户权限记录(如站长后台授权用)
*/
public function insert_or_update($uid, $biz_type, $level = 1, $merchant_type = 1) {
$record = $this->get_by_uid_and_biz($uid, $biz_type);
if ($record) {
return DB::update(
$this->_table,
array(
'permission_level' => $level,
'merchant_type' => $merchant_type
),
"uid=$uid AND biz_type='$biz_type'"
);
} else {
return DB::insert($this->_table, array(
'uid' => $uid,
'biz_type' => $biz_type,
'permission_level' => $level,
'merchant_type' => $merchant_type,
'status' => 1,
'created_at' => date('Y-m-d H:i:s')
));
}
}
/**
* ✅ 获取指定用户所有启用状态(status=1)的业务类型列表
* 用于业务切换下拉框展示,如:simtelecom / insurance 等
*
* @param int $uid 当前登录用户的 Discuz UID
* @return array 数组列表,如:[ ['biz_type' => 'simtelecom'], ['biz_type' => 'express'] ]
*/
public function fetch_biz_by_uid($uid) {
return DB::fetch_all(
"SELECT biz_type FROM %t WHERE uid=%d AND status=1 ORDER BY biz_type ASC",
array($this->_table, $uid)
);
}
}
4.4.5 插件安装脚本(创建商户权限表) install.php¶
该脚本在插件安装时由 Discuz 自动调用,用于初始化数据库表 pre_xigua_partnercenter_account。
说明:
- 使用 runquery($sql) 是 Discuz 插件初始化建表的标准方式;
- 通过 CREATE TABLE IF NOT EXISTS 防止重复创建;
- $finish = true; 告诉 Discuz 安装结束。
4.4.6 插件卸载脚本(删除商户权限表) uninstall.php¶
该脚本在插件卸载时由 Discuz 自动调用,用于清除插件使用的数据库表。
注意事项:
- DROP TABLE IF EXISTS 确保不会报错;
- 删除操作不可恢复,请确保不影响其他依赖数据;
- 插件之间不要共用表(该表仅属于 xigua_partnercenter 插件,因此可安全删除)。
4.4.7 多语言包文件 xigua_partnercenter.lang.php¶
该文件用于定义插件中所有页面展示文字,增强可维护性和国际化能力。语言调用方式应使用:
- {lang key} 用于 Discuz 后台模块模板;
- 前台插件模板中应统一使用 {$lang['key']};
- 所有模板变量应通过 lang() 或手动 $lang 注入模板数组。
4.4.8 商户订单列表管理功能 simtelecom_order.inc.php¶
xigua_simtelecom的服务插件数据表结构为:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | INT(10) | 主键,自增 |
| orderid | VARCHAR(50) | 订单编号 |
| username | VARCHAR(50) | 申请人姓名 |
| phone | VARCHAR(20) | 手机号 |
| package | VARCHAR(50) | 套餐 |
| address | TEXT | 收货地址 |
| VARCHAR(100) | 邮箱 | |
| dateline | INT(10) | 提交时间(UNIX时间戳) |
| uid | INT(10) | 提交人 UID |
| username_dz | VARCHAR(50) | 提交人 Discuz 用户名 |
| userip | VARCHAR(45) | 提交人 IP 地址 |
| operator | VARCHAR(50) | 处理人用户名(默认 58agent) |
| status | TINYINT(1) | 状态(0=待处理,1=处理中,2=已完成,3=已取消) |
| remark | VARCHAR(300) | 备注限制为 100 汉字(300 UTF8 字节) |
接下来处理计划::
simtelecom_order.inc.php 控制器,支持:
- 筛选字段:手机号、姓名、邮箱、状态、处理员、提交时间段;
- 分页与查询;
- 备注字段变更检测机制:通过 remark_changed[$id] 区分是否要写入 remark 字段;
- 权限说明已注释;
- 数据更新:status, remark, operator 字段可由商户修改;
- 支持 GET 搜索,POST 更新。
查询筛选项扩展:
| 筛选字段 | 类型 | 查询方式 |
|---|---|---|
| 状态 | int | 精确匹配 |
| 手机号 | string | 模糊匹配 |
| 姓名 | string | 模糊匹配 |
| 邮箱 | string | 模糊匹配 |
| 提交时间段 | datetime | 起止区间 |
| 处理员 | string | 精确匹配 |
4.4.9 处理页面模板 order_list.htm¶
模板文件结构:
source/plugin/xigua_partnercenter/template/
├── front/
│ └── order_list.htm ← PC端模板
└── touch/
└── order_list.htm ← 移动端模板
加载方式(自适应):
$tpl = checkmobile() ? 'touch/order_list' : 'front/order_list';
include template("xigua_partnercenter:$tpl");
功能模块应包含:
- 顶部筛选表单(手机号、姓名、邮箱、状态、时间段、处理员);
- 表格展示所有订单信息;
- 每行订单:
- 状态可选下拉;
- 备注可编辑;
- 操作按钮(提交);
- 提交按钮;
- 分页;
- 业务切换下拉框;
业务切换功能设计:
前提设定:
- 商户账号可能拥有多个业务权限(如 simtelecom, express, insurance 等);
- 当前页面仅处理一个业务(由主控制器通过 $_GET['biz'] 指定);
- 可通过下拉框列出商户已授权的全部业务类型。
功能实现逻辑:
- 后端:主控器中提供商户的业务列表,已有的主控器 xigua_partnercenter.inc.php 中应获取当前商户所有业务权限。
- 模板:渲染
$biz_list = C::t('#xigua_partnercenter#xigua_partnercenter_account')->fetch_biz_by_uid($_G['uid']);
// 封装方法
public function fetch_biz_by_uid($uid) {
return DB::fetch_all("SELECT biz_type FROM %t WHERE uid=%d AND status=1", array($this->_table, $uid));
}
4.4.10 安装与部署¶
1) 数据库创建商户权限表
CREATE TABLE IF NOT EXISTS `pre_xigua_partnercenter_account` (
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID',
`uid` INT(10) UNSIGNED NOT NULL COMMENT '商户UID',
`biz_type` VARCHAR(30) NOT NULL COMMENT '业务类型标识',
`permission_level` TINYINT DEFAULT 1 COMMENT '权限等级,默认1',
`status` TINYINT DEFAULT 1 COMMENT '状态:1启用,0禁用',
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`merchant_type` TINYINT DEFAULT 1 COMMENT '商户类型:1=个人,2=企业',
PRIMARY KEY (`id`),
UNIQUE KEY `uid_biz` (`uid`, `biz_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO pre_xigua_partnercenter_account (uid, biz_type, permission_level, status, created_at)
VALUES (1, 'simtelecom', 1, 1, NOW())
ON DUPLICATE KEY UPDATE status = 1;
2) Discuz管理后台安装插件


4.4.11 插件管理页(对商户进行授权)子插件开发 partnercenter_admin¶
这是一个核心管理功能,涉及后台站长对商户进行授权配置。站长需要在后台:
- 选择业务类型(如 simtelecom、otherservice 等)
- 指定 Discuz 用户 ID 或用户名 为商户
- 设定商户权限等级(如普通、管理员等)
- 选择商户类型(企业/个人等)
- 激活/禁用授权
- 支持编辑/删除已有商户授权
核心设计思路
- 插件管理页入口设计:插件后台菜单中新增一个子菜单项:
商户授权管理(partnercenter_admin) - 表单设计思路,表单字段应包括:
| 字段 | 类型 | 说明 |
|---|---|---|
| 用户名/UID | 输入框 | 必填;后台自动解析用户ID |
| 业务类型 | 下拉列表 | 来源于插件已注册业务列表 |
| 权限等级 | 下拉或单选 | 例如:1普通,2管理员等 |
| 商户类型 | 下拉 | 例如:1企业,2个人 |
| 启用状态 | 单选 | 1启用,0禁用 |
-
交互流程与逻辑验证
- 输入用户名 → 自动查询并显示 UID
- 如果用户已存在某业务授权 → 不允许重复添加
- 支持修改已有商户权限设置
- 支持批量启用/停用/删除操作(表格中提供管理按钮)
-
后台安全机制
- 必须为 站长级用户 才能访问该后台页面
- 所有操作均校验 formhash
- 所有更新操作记录操作管理员和时间(可拓展日志功能)
-
数据来源依赖
- 使用 pre_xigua_partnercenter_account 表存储授权信息;
- 业务类型字段应来自系统配置,支持动态扩展;
- 插件可使用已有 table_xigua_partnercenter_account 类封装所有操作;
| 项目 | 建议 |
|---|---|
| 后台页面设计 | 插件后台 -> 商户授权管理 |
| 表单验证 | 用户存在验证、重复授权检查 |
| 数据结构 | 使用现有 partnercenter 表 |
| 扩展性 | 支持多业务、多用户权限控制 |
| 安全性 | 站长权限控制、表单校验 |
4.4.11.1 数据库交互逻辑封装设计 table_xigua_partnercenter_account.php¶
要支持后台站长管理商户授权,以下几点功能目前缺失或需增强:
| 功能需求 | 是否已实现 | 方法或备注 |
|---|---|---|
| 获取某用户在某业务的有效授权 | ✅ get_by_uid_and_biz() | |
| 获取用户所有业务授权列表 | ✅ fetch_biz_by_uid() | |
| 插入或更新(前台注册/站长授权) | ✅ insert_or_update() | |
| 后台分页列出所有授权记录 | ❌ fetch_all_by_biz() 建议新增 | |
| 按主键ID查询记录 | ❌ fetch_by_id() 建议新增 | |
| 新增记录前检查是否已存在 | ✅ 部分封装在 insert_or_update() 中 | |
| 后台新增记录独立入口 | ❌ insert_new() 建议新增(解耦 insert_or_update) | |
| 编辑指定记录 | ❌ update_by_id() 建议新增 | |
| 删除指定授权记录 | ❌ delete_by_id() 建议新增 | |
| 总记录数统计(配合分页) | ❌ count_by_biz() 建议新增 |
新增功能总结如下:
- fetch_all_by_biz():用于后台分页列出授权列表
- count_by_biz():统计某业务下总商户数
- fetch_by_id():后台编辑页面获取详情
- insert_new():站长手动添加授权(避免重复)
- update_by_id():站长编辑权限或状态
- delete_by_id():后台删除授权记录
4.4.11.2 插件后台管理“商户授权”的控制器 admin_account.inc.php¶
文件命名符合 Discuz 规范(根据 Discuz! X 插件开发规范,插件的后台管理文件应放置在插件目录下的 admin 子目录中,文件名通常以 admin_ 开头,后接功能名称,并以 .inc.php 结尾。):source/plugin/xigua_partnercenter/admin/admin_account.inc.php
功能说明
该控制器允许站长:
1) 查看所有商户授权记录(按业务类型筛选)
2) 添加新授权
3) 编辑授权记录
4) 删除授权
4.5 插件部署后台添加 admin_account.inc.php 功能入口¶
- 更新文件结构:
- 编辑插件的 plugin.xml 文件(或通过后台管理配置)
在插件目录中找到或新增 plugin.xml,确认其中包含如下内容:
- 配置项填写建议
| 字段名 | 推荐填写内容 |
|---|---|
| 新增加位置 | 管理中心 |
| 程序模块 | admin_account(对应 admin_account.inc.php) |
| 链接名称 | 商户授权管理(或其他你偏好的名称) |
| 链接 URL | 留空(Discuz 会自动拼接) |
| 使用等级 | 选择“仅管理员” |
| 显示顺序 | 1~99,决定菜单项排序(可随意) |
-
登录后台,进入插件管理页:
- 进入【后台】→【插件】→ 找到 xigua_partnercenter
- 点击【设置】(即插件的“配置”)
- 看到左侧有“商户授权管理”菜单项,即成功挂载
-
测试入口:
admin.php?action=plugins&operation=config&identifier=xigua_partnercenter&pmod=admin_account
4.6 待开发的功能¶
- Ajax 提交 + 无刷新体验
- 微信小程序 API 封装支持(如 JSON 返回接口)
5 相关知识¶
5.1 Discuz!下插件页面访问执行链路总览表¶
| 执行顺序 | 文件路径 | 文件名称 | 主要作用 |
|---|---|---|---|
| 1 | /www/wwwroot/58haiwai_life/plugin.php | plugin.php | 入口文件,识别 id=xigua_hb,定位并加载插件主控制器 |
| 2 | /www/wwwroot/58haiwai_life/source/plugin/xigua_hb/xigua_hb.inc.php | xigua_hb.inc.php | 插件主逻辑分发控制器,根据 $ac 路由不同子模块 |
| 3 | /www/wwwroot/58haiwai_life/source/plugin/xigua_hb/common.php | common.php | 加载插件配置、通用函数等(不含设备判断) |
| 4 | /www/wwwroot/58haiwai_life/source/plugin/xigua_hb/function_callback.php | function_callback.php | 定义 hb_index_init():初始化 $ac、分页、登录状态、短信配置等 |
| 5 | (同上) | hb_index_init() 函数 | 初始化并控制 $ac 合法性、用户验证、环境变量等 |
| 6 | /www/wwwroot/58haiwai_life/source/plugin/xigua_hb/include/city.inc.php | city.inc.php | 默认 $ac='index' 时加载,处理首页展示/城市结构逻辑 |
| 7 | 内部判断:checkmobile() | function_core.php 中定义 | 判断是否为移动端,设定常量 IN_MOBILE(已在 Discuz 内核中执行) |
| 8 | template() 函数自动执行 | function_core.php 调用 → discuz_template 类 | 根据 IN_MOBILE 判断优先使用移动端模板路径 /template/touch/ |
| 9 | /www/wwwroot/58haiwai_life/source/plugin/xigua_hb/template/touch/index.php | index.php | 最终生成返回页面的模板文件,渲染首页 HTML |
5.2 Unicode 图标 + 中文含义对照表¶
| Unicode | Codepoint | Glyph | 中文含义 | |
|---|---|---|---|---|
| 0 | \ue600 | U+E600 | star | 星形 |
| 1 | \ue601 | U+E601 | download-circle | 下载(圆圈) |
| 2 | \ue602 | U+E602 | right | 右箭头 |
| 3 | \ue603 | U+E603 | left | 左箭头 |
| 4 | \ue604 | U+E604 | top | 上箭头 |
| 5 | \ue605 | U+E605 | ok | 确认 |
| 6 | \ue606 | U+E606 | chat | 聊天 |
| 7 | \ue607 | U+E607 | help | 帮助 |
| 8 | \ue608 | U+E608 | add-circle-fine | 精细加号圆 |
| 9 | \ue609 | U+E609 | release | 发布 |
| 10 | \ue60a | U+E60A | list | 列表 |
| 11 | \ue60b | U+E60B | about | 关于 |
| 12 | \ue60c | U+E60C | face-smile-fine | 微笑脸(细) |
| 13 | \ue60d | U+E60D | picture-fine | 图片(细) |
| 14 | \ue60e | U+E60E | log | 日志 |
| 15 | \ue60f | U+E60F | menu-fill | 填充菜单 |
| 16 | \ue610 | U+E610 | cols | 列 |
| 17 | \ue611 | U+E611 | reply-fill | 回复(填充) |
| 18 | \ue612 | U+E612 | friends | 朋友 |
| 19 | \ue613 | U+E613 | group | 群组 |
| 20 | \ue614 | U+E614 | set-fill | 设置(填充) |
| 21 | \ue615 | U+E615 | search | 搜索 |
| 22 | \ue616 | U+E616 | reduce-circle | 减号圆圈 |
| 23 | \ue617 | U+E617 | circle-dot | 圆点 |
| 24 | \ue618 | U+E618 | 邮箱 | |
| 25 | \ue619 | U+E619 | up | 向上 |
| 26 | \ue61a | U+E61A | down | 向下 |
| 27 | \ue61b | U+E61B | layim-theme | |
| 28 | \ue61c | U+E61C | 404 | |
| 29 | \ue61d | U+E61D | layim-uploadfile | |
| 30 | \ue61e | U+E61E | layim-download | |
| 31 | \ue61f | U+E61F | add-circle | |
| 32 | \ue620 | U+E620 | set-sm | |
| 33 | \ue621 | U+E621 | file | 文件 |
| 34 | \ue622 | U+E622 | screen-full | 全屏 |
| 35 | \ue623 | U+E623 | triangle-r | |
| 36 | \ue624 | U+E624 | addition | |
| 37 | \ue625 | U+E625 | triangle-d | |
| 38 | \ue626 | U+E626 | service | |
| 39 | \ue627 | U+E627 | gift | |
| 40 | \ue628 | U+E628 | engine | 引擎 |
| 41 | \ue629 | U+E629 | chart-screen | |
| 42 | \ue62a | U+E62A | tabs | |
| 43 | \ue62b | U+E62B | fonts-strong | |
| 44 | \ue62c | U+E62C | chart | 图表 |
| 45 | \ue62d | U+E62D | table | |
| 46 | \ue62e | U+E62E | tree | |
| 47 | \ue62f | U+E62F | upload-circle | |
| 48 | \ue630 | U+E630 | templeate-1 | |
| 49 | \ue631 | U+E631 | util | |
| 50 | \ue632 | U+E632 | layouts | |
| 51 | \ue633 | U+E633 | prev-circle | |
| 52 | \ue634 | U+E634 | carousel | |
| 53 | \ue635 | U+E635 | code-circle | |
| 54 | \ue636 | U+E636 | water | |
| 55 | \ue637 | U+E637 | date | |
| 56 | \ue638 | U+E638 | layer | |
| 57 | \ue639 | U+E639 | fonts-clear | |
| 58 | \ue63a | U+E63A | dialogue | |
| 59 | \ue63b | U+E63B | cellphone-fine | |
| 60 | \ue63c | U+E63C | form | 表单 |
| 61 | \ue63d | U+E63D | loading | 加载中 |
| 62 | \ue63e | U+E63E | loading-1 | 加载1 |
| 63 | \ue63f | U+E63F | circle | |
| 64 | \ue640 | U+E640 | delete | 删除 |
| 65 | \ue641 | U+E641 | share | 分享 |
| 66 | \ue642 | U+E642 | edit | 编辑 |
| 67 | \ue643 | U+E643 | radio | |
| 68 | \ue644 | U+E644 | fonts-i | |
| 69 | \ue645 | U+E645 | speaker | |
| 70 | \ue646 | U+E646 | fonts-u | |
| 71 | \ue647 | U+E647 | align-center | |
| 72 | \ue648 | U+E648 | align-right | |
| 73 | \ue649 | U+E649 | align-left | |
| 74 | \ue64a | U+E64A | picture | |
| 75 | \ue64b | U+E64B | fonts-html | |
| 76 | \ue64c | U+E64C | link | 链接 |
| 77 | \ue64d | U+E64D | unlink | 取消链接 |
| 78 | \ue64e | U+E64E | fonts-code | |
| 79 | \ue64f | U+E64F | fonts-del | |
| 80 | \ue650 | U+E650 | face-smile-b | |
| 81 | \ue651 | U+E651 | pause | 暂停 |
| 82 | \ue652 | U+E652 | play | 播放 |
| 83 | \ue653 | U+E653 | app | |
| 84 | \ue654 | U+E654 | add-1 | |
| 85 | \ue655 | U+E655 | file-b | |
| 86 | \ue656 | U+E656 | template-1 | |
| 87 | \ue657 | U+E657 | cart | 购物车 |
| 88 | \ue658 | U+E658 | star-fill | |
| 89 | \ue659 | U+E659 | dollar | 美元 |
| 90 | \ue65a | U+E65A | prev | |
| 91 | \ue65b | U+E65B | next | |
| 92 | \ue65c | U+E65C | return | |
| 93 | \ue65d | U+E65D | camera-fill | 相机(填充) |
| 94 | \ue65e | U+E65E | rmb | |
| 95 | \ue65f | U+E65F | more | |
| 96 | \ue660 | U+E660 | camera | 相机 |
| 97 | \ue661 | U+E661 | female | |
| 98 | \ue662 | U+E662 | male | |
| 99 | \ue663 | U+E663 | template | |
| 100 | \ue664 | U+E664 | face-surprised | |
| 101 | \ue665 | U+E665 | console | |
| 102 | \ue666 | U+E666 | refresh-1 | |
| 103 | \ue667 | U+E667 | notice | |
| 104 | \ue668 | U+E668 | shrink-right | |
| 105 | \ue669 | U+E669 | refresh | |
| 106 | \ue66a | U+E66A | theme | |
| 107 | \ue66b | U+E66B | spread-left | |
| 108 | \ue66c | U+E66C | flag | 旗帜 |
| 109 | \ue66d | U+E66D | ||
| 110 | \ue66e | U+E66E | note | |
| 111 | \ue66f | U+E66F | username | |
| 112 | \ue670 | U+E670 | find-fill | 查找(填充) |
| 113 | \ue671 | U+E671 | more-vertical | |
| 114 | \ue672 | U+E672 | auz | |
| 115 | \ue673 | U+E673 | password | 密码 |
| 116 | \ue674 | U+E674 | senior | |
| 117 | \ue675 | U+E675 | login-weibo | 微博登录 |
| 118 | \ue676 | U+E676 | login-qq | QQ登录 |
| 119 | \ue677 | U+E677 | login-wechat | 微信登录 |
| 120 | \ue678 | U+E678 | cellphone | 手机 |
| 121 | \ue679 | U+E679 | vercode | |
| 122 | \ue67a | U+E67A | rate-solid | 评分(实心) |
| 123 | \ue67b | U+E67B | rate | 评分 |
| 124 | \ue67c | U+E67C | upload | |
| 125 | \ue67d | U+E67D | export | |
| 126 | \ue67e | U+E67E | subtraction | |
| 127 | \ue67f | U+E67F | windows | |
| 128 | \ue680 | U+E680 | ios | |
| 129 | \ue681 | U+E681 | upload-drag | |
| 130 | \ue682 | U+E682 | logout | 登出 |
| 131 | \ue683 | U+E683 | key | |
| 132 | \ue684 | U+E684 | android | |
| 133 | \ue685 | U+E685 | mute | 静音 |
| 134 | \ue686 | U+E686 | firefox | Firefox浏览器 |
| 135 | \ue687 | U+E687 | at | 艾特 |
| 136 | \ue688 | U+E688 | voice | 声音 |
| 137 | \ue689 | U+E689 | bluetooth | |
| 138 | \ue68a | U+E68A | chrome | Chrome浏览器 |
| 139 | \ue68b | U+E68B | edge | Edge浏览器 |
| 140 | \ue68c | U+E68C | heart | |
| 141 | \ue68d | U+E68D | time | |
| 142 | \ue68e | U+E68E | home | 首页 |
| 143 | \ue68f | U+E68F | heart-fill | |
| 144 | \ue690 | U+E690 | music | 音乐 |
| 145 | \ue691 | U+E691 | transfer | |
| 146 | \ue698 | U+E698 | cart-simple | 购物车(简) |
| 147 | \ue69c | U+E69C | face-cry | 哭脸 |
| 148 | \ue6af | U+E6AF | face-smile | 笑脸 |
| 149 | \ue6b1 | U+E6B1 | snowflake | |
| 150 | \ue6b2 | U+E6B2 | survey | |
| 151 | \ue6c5 | U+E6C5 | tread | |
| 152 | \ue6c6 | U+E6C6 | praise | |
| 153 | \ue6c9 | U+E6C9 | rate-half | |
| 154 | \ue6dc | U+E6DC | mike | |
| 155 | \ue6ed | U+E6ED | video | 视频 |
| 156 | \ue6fc | U+E6FC | headset | 耳机 |
| 157 | \ue702 | U+E702 | tips | |
| 158 | \ue705 | U+E705 | read | |
| 159 | \ue714 | U+E714 | slider | |
| 160 | \ue715 | U+E715 | location | |
| 161 | \ue716 | U+E716 | set | 设置 |
| 162 | \ue735 | U+E735 | diamond | 钻石 |
| 163 | \ue748 | U+E748 | light | 灯光 |
| 164 | \ue756 | U+E756 | fire | 火焰 |
| 165 | \ue758 | U+E758 | screen-restore | 恢复窗口 |
| 166 | \ue770 | U+E770 | user | 用户 |
| 167 | \ue7ae | U+E7AE | website | |
| 168 | \ue7bb | U+E7BB | ie | IE浏览器 |
| 169 | \ue7e0 | U+E7E0 | wifi | Wi-Fi |
| 170 | \ue808 | U+E808 | rss | 订阅 |
| 171 | \ue857 | U+E857 | component | 组件 |
| 172 | \ue9aa | U+E9AA | refresh-3 |
5. 3 custom.css样式类汇总¶
字体与文本(Typography):
| 类名 | 描述说明 |
|---|---|
| .f12 | 设置字体大小为 12px |
| .f14 | 设置字体大小为 14px |
| .f15 | 设置字体大小为 15px |
| .f16 | 设置字体大小为 16px |
| .f18 | 设置字体大小为 18px |
| .text-center | 文本居中 |
| .text-left | 文本左对齐 |
| .text-right | 文本右对齐 |
| .nowrap | 不换行 |
| .ellipsis | 单行文本溢出显示省略号(…) |
| .bold | 加粗字体 |
| .gray | 设置文字颜色为灰色 |
| .red | 设置文字颜色为红色(错误/警告) |
| .blue | 设置文字颜色为蓝色 |
布局与间距(Layout & Spacing)
| 类名 | 描述说明 |
|---|---|
| .cl | 清除浮动(clear: both) |
| .z | 设置 float: left |
| .y | 设置 float: right |
| .plr10 | 左右 padding 各 10px |
| .pt10 | 顶部 padding 为 10px |
| .pb10 | 底部 padding 为 10px |
| .mt10 | 顶部 margin 为 10px |
| .mb10 | 底部 margin 为 10px |
| .ml10 | 左边 margin 为 10px |
| .mr10 | 右边 margin 为 10px |
| .p5, .p10 | 全部 padding 分别为 5px、10px |
| .m5, .m10 | 全部 margin 分别为 5px、10px |
| .w100 | 宽度 100% |
| .auto-center | 设置 margin: 0 auto,实现水平居中 |
| .inline-block | 设置 display 为 inline-block |
| .hidden | 设置 display: none |
按钮与表单(Buttons & Forms)
| 类名 | 描述说明 |
|---|---|
| .btn, .btn-primary | 基础按钮样式、主要按钮样式(通常为蓝色背景白字) |
| .btn-disabled | 禁用按钮样式,颜色变灰且不可点击 |
| .btn-block | 按钮宽度撑满容器,通常用于移动端 |
| .form-input | 通用输入框样式(内边距、边框、字体大小等设定) |
| .form-select | 下拉选择框样式 |
| .form-textarea | 多行文本框样式 |
| .form-group | 表单分组容器,一般用于控制 margin/padding |
| .input-error | 输入框错误时添加的类,通常边框为红色 |
| .checkbox-custom | 自定义勾选框样式,搭配 label 使用 |
| .radio-custom | 自定义单选框样式 |
颜色与背景(Colors & Backgrounds)
| 类名 | 描述说明 |
|---|---|
| .color_1 | 主色(通常用于强调/主按钮) |
| .color_2 | 辅助色/次级强调色 |
| .color_gray | 灰色字体/说明文字色 |
| .color_red | 错误提示/重要警告色 |
| .color_green | 成功提示色 |
| .bgcolor_11 | 顶部导航栏背景色(如 header) |
| .bg-light | 浅灰背景色 |
| .bg-dark | 深色背景色 |
| .bg-white | 白色背景,常用于表单容器 |
| .bg-blue | 蓝色背景 |
边距与间距(Spacing)
| 类名 | 描述说明 |
|---|---|
| .mt10, .mt20, .mt30 | 上边距 margin-top(单位通常为 px) |
| .mb10, .mb20 | 下边距 margin-bottom |
| .ml10, .mr10 | 左/右边距 margin-left/right |
| .pt10, .pt20 | 上内边距 padding-top |
| .pb10, .pb20 | 下内边距 padding-bottom |
| .p10, .p20, .p30 | 所有方向内边距 padding(统一设置) |
| .m0, .p0 | 清除边距/内距(margin/padding 为 0) |
| .space-10, .space-15 | 间距块元素,用于组件之间的分隔 |
边框与圆角(Borders & Radius)
| 类名 | 描述说明 |
|---|---|
| .border, .b-all | 元素添加 1px 实线边框(全边) |
| .bt, .bb, .bl, .br | 上/下/左/右边框(border-top/right/...) |
| .b0, .bt0, .bb0 | 移除边框(所有或单边) |
| .radius, .radius5, .radius10 | 设置圆角(border-radius),数值为 px |
| .circle, .round | 完全圆形或椭圆圆角(适用于头像、图标按钮等) |
| .border-gray, .b-light | 边框颜色类,一般用于浅灰色或主题色 |
背景与颜色(Background & Color)
| 类名 | 描述说明 |
|---|---|
| .bg-white, .bg-gray | 设置背景颜色为白色 / 灰色 |
| .bgcolor_11 | 插件定义的主题背景色(如顶部 header 背景) |
| .bg-transparent | 设置背景为透明 |
| .color-primary | 主色调文字颜色 |
| .color-gray, .color-lightgray | 设置字体颜色为浅灰、灰色等 |
| .text-danger | 设置文字颜色为红色(用于提示错误等) |
| .text-success | 设置文字颜色为绿色(成功提示) |
图片与图标(Images & Icons)
| 类名 | 描述说明 |
|---|---|
| .w15, .w20, .w30 | 控制图标/图片宽度为 15/20/30 像素 |
| .iconfont | 使用字体图标(需配合对应 icon class 使用) |
| .icon-fanhuijiantou | 返回箭头图标,常用于顶部返回按钮 |
| .icon-fabui1, .icon-wode 等 | 插件图标类名,配合 .iconfont 使用显示图标 |
按钮与操作元素(Buttons & Actions)
| 类名 | 描述说明 |
|---|---|
| .btn, .btn-primary | 通用按钮样式,主色调按钮 |
| .pn, .pn strong | Discuz 默认风格的按钮(如提交按钮) |
| .weui-btn, .weui-btn_primary | WeUI 规范下的主按钮,适配移动端 |
| .weui-btn_area | 提交按钮的布局容器 |
| .weui-agree | 协议勾选项容器 |
| .weui-agree__checkbox | 协议复选框样式 |
| .weui-agree__text | 协议说明文字样式 |
| .disable, .disabled | 禁用态按钮样式 |
| .btn-block | 块级按钮,占满父元素宽度 |
动画与过渡效果(Animations & Transitions)
| 类名 | 描述说明 |
|---|---|
| .fade-in | 渐入动画,通常用于页面元素加载时 |
| .fade-out | 渐出动画,元素消失时使用 |
| .slide-up | 向上滑入动画 |
| .slide-down | 向下滑出动画 |
| .transition | 应用于过渡属性,如颜色或位置变化 |
| .animated | 通用动画启动类,搭配 keyframe 使用 |
响应式布局与媒体查询(Responsive & Media Queries)
| 类名 | 描述说明 |
|---|---|
| .mobile-only | 仅在移动设备显示(通常配合媒体查询显示隐藏元素) |
| .desktop-only | 仅在桌面端显示 |
| .hidden-xs | 超小屏隐藏(max-width: 480px) |
| .hidden-sm | 小屏隐藏(max-width: 768px) |
| .hidden-md | 中屏隐藏(max-width: 992px) |
| .hidden-lg | 大屏隐藏(max-width: 1200px) |
| .visible-xs | 仅超小屏可见(通常 < 480px) |
| .visible-sm | 小屏可见(通常 481px–768px) |
| .visible-md | 中屏可见(769px–992px) |
| .visible-lg | 大屏可见(993px 以上) |
| @media ...规则 | 文件中内嵌多个 media query 控制样式响应适配 |
按钮与交互组件(Buttons & Interactions)
| 类名 | 描述说明 |
|---|---|
| .btn, .button | 通用按钮样式 |
| .btn-primary | 主按钮(通常为主色背景、白色文字) |
| .btn-secondary | 次要按钮(灰色背景或边框) |
| .btn-disabled | 禁用状态按钮 |
| .btn-block | 宽度 100% 的按钮,占据整行 |
| .btn-sm, .btn-lg | 小尺寸、大尺寸按钮 |
| .btn-circle | 圆形按钮(例如图标按钮) |
| .btn-loading | 加载中状态(可能结合 loading 图标样式) |
| .pn, .pn2 | Discuz平台通用按钮样式,常用于插件 submit 按钮等 |
| .button-group | 按钮组样式,常用于多个操作按钮并排 |
| .active, .hover | 按钮悬停或激活时的样式(hover 效果) |
警告与提示样式(Alerts & Notifications)
| 类名 | 描述说明 |
|---|---|
| .alert, .alert-warning | 通用警告提示容器,背景通常为浅黄或橙色 |
| .alert-success | 成功提示(绿色背景) |
| .alert-error, .error | 错误提示(红色背景或红字) |
| .toast, .weui-toast | 居中短时提示框(如表单错误提示等),支持图标 + 文字 |
| .xg-toptip, .xg-toptip-error | 页面顶部提示条,显示重要错误信息 |
| .tips, .tips2 | 简单行内提示信息(一般为提示说明或错误提醒) |
| .msg, .msg-error | 表单错误信息提示(通常出现在输入框下方) |
| .weui-agree__text .error | 协议勾选相关提示错误样式 |
| .tip-text, .note-text | 小字提示,常用于备注信息 |
输入与表单组件(Forms & Inputs)
| 类名 | 描述说明 |
|---|---|
| .weui-form | WeUI 标准表单外壳样式,用于包含整体表单结构 |
| .weui-cell, .weui-cell_select | 单个输入项容器,支持常规输入框与下拉框形式 |
| .weui-cell__bd | 输入区域容器,一般包裹 input 或 textarea |
| .weui-input | 表单输入框,通用输入样式(包括姓名、手机号、邮箱等) |
| .weui-textarea | 多行输入框样式,用于地址、备注等 |
| .weui-select | 下拉选择框样式 |
| .weui-agree | 协议勾选容器样式 |
| .weui-agree__checkbox | 协议勾选框样式 |
| .weui-agree__text | 协议勾选说明文字样式 |
| .weui-btn, .weui-btn_primary | 表单按钮样式,primary 表示主要按钮 |
| .weui-btn-area | 按钮容器区域,用于底部按钮居中排版 |
| .form-error, .field-error | 表单字段错误提示样式,常用于校验失败提示 |
| .input-tips, .form-tips | 提示信息,常用于输入框下方的说明文字 |
按钮与操作(Buttons & Actions)
| 类名 | 描述说明 |
|---|---|
| .weui-btn | WeUI 通用按钮基础类,需配合样式类使用 |
| .weui-btn_primary | 主操作按钮,蓝色背景,白色文字 |
| .weui-btn_default | 默认按钮,灰色背景 |
| .weui-btn_warn | 警告按钮,红色背景,用于删除等操作 |
| .weui-btn_disabled | 禁用状态按钮,通常配合 disabled 属性 |
| .weui-btn-area | 按钮区域容器,通常用于表单提交按钮的包裹 |
| .btn-block, .btn-center | 宽度全屏或居中排版样式 |
| .btn-small, .btn-large | 控制按钮大小(可能配合字体一起设置) |
| .btn-radius, .btn-round | 按钮圆角处理样式(部分可能与 .weui-btn 冲突) |
列表与单元格(Lists & Cells)
| 类名 | 描述说明 |
|---|---|
| .weui-cells | WeUI 标准单元格列表容器类 |
| .weui-cell | 单元格项的基础类 |
| .weui-cell_select | 带下拉选择的单元格样式 |
| .weui-cell__bd | 单元格主体区域,用于输入框、文本等 |
| .weui-cell__ft | 单元格尾部区域,常用于提示或说明 |
| .weui-cells_form | 表单专用单元格容器,配合输入项 |
| .weui-cells__title | 分组标题样式 |
| .weui-cells_checkbox | 多选框列表容器样式 |
| .weui-check | WeUI 复选框样式(需配合 label 使用) |
| .weui-icon-checked | 复选状态图标(一般通过伪类实现) |
| .weui-cell_switch | 切换开关类单元格 |
| .weui-switch | 开关样式按钮,常用于设置类功能项 |
表单输入(Forms & Inputs)
| 类名 | 描述说明 |
|---|---|
| .weui-input | 文本输入框样式 |
| .weui-textarea | 多行文本框样式 |
| .weui-select | 下拉选择框样式 |
| .weui-agree | 协议勾选区域容器样式 |
| .weui-agree__checkbox | 协议勾选框样式(checkbox) |
| .weui-agree__text | 协议说明文字样式 |
| .weui-btn | 按钮通用基础样式 |
| .weui-btn_primary | 主按钮样式(绿色背景,白色文字) |
| .weui-btn_disabled | 禁用按钮状态样式 |
| .weui-btn_area | 按钮容器区域,适用于表单提交按钮放置 |
| .weui-btn_loading | 加载状态按钮样式 |
| .weui-btn_warn | 警告样式按钮(一般为红色背景) |
| .weui-btn_default | 默认按钮样式(灰底黑字) |
加载与反馈(Loaders & Toasts)
| 类名 | 描述说明 |
|---|---|
| .weui-toast | 通用 toast 提示框容器,通常用于顶部或中部提示 |
| .weui-toast__content | toast 提示框中的文本样式 |
| .weui-icon_toast | toast 图标样式(如对号、警告图标等) |
| .weui-icon-success | 成功提示图标(一般为绿色圆圈内对号) |
| .weui-icon-warn | 警告提示图标(一般为黄色感叹号) |
| .weui-mask_transparent | 半透明蒙层,常用于 toast 背景防点击 |
| .weui-loading | 加载中图标动画容器,常配合 .weui-toast 使用 |
| .weui-loadmore | 加载更多提示样式容器 |
| .weui-loadmore_line | 加载分割线样式 |
| .weui-loadmore_dot | 加载点点样式 |
| .weui-loadmore_tips | 加载提示语样式 |
对话框与弹窗(Dialogs & Modals)
| 类名 | 描述说明 |
|---|---|
| .weui-dialog | 基础对话框容器,含标题、正文、按钮区域 |
| .weui-dialog__hd | 对话框标题区域 |
| .weui-dialog__title | 对话框标题文字样式 |
| .weui-dialog__bd | 对话框正文内容区域 |
| .weui-dialog__ft | 对话框底部按钮区域 |
| .weui-dialog__btn | 对话框底部按钮通用样式 |
| .weui-dialog__btn_default | 对话框默认按钮(灰色)样式 |
| .weui-dialog__btn_primary | 对话框主按钮(蓝色或主题色)样式 |
| .weui-half-screen-dialog | 半屏对话框样式,用于移动端底部弹出页 |
| .weui-half-screen-dialog__hd | 半屏对话框标题区域 |
| .weui-half-screen-dialog__bd | 半屏对话框内容区域 |
| .weui-half-screen-dialog__ft | 半屏对话框按钮区域 |
图片与相册(Image & Gallery)
| 类名 | 描述说明 |
|---|---|
| .weui-gallery | 图片查看器的容器样式(模态层) |
| .weui-gallery__img | 被查看的图片样式 |
| .weui-gallery__opr | 图片操作区域(如删除按钮容器) |
| .weui-gallery__del | 删除按钮图标样式 |
| .weui-uploader | 上传组件外层容器 |
| .weui-uploader__hd | 上传组件标题区域 |
| .weui-uploader__info | 上传状态提示(如“0/3”) |
| .weui-uploader__bd | 上传图片内容区域 |
| .weui-uploader__files | 上传图片列表容器 |
| .weui-uploader__file | 单个已上传图片样式 |
| .weui-uploader__input-box | 上传按钮外层容器 |
| .weui-uploader__input | 上传文件 的样式隐藏控制 |
加载中与遮罩层(Loading & Mask)
| 类名 | 描述说明 |
|---|---|
| .weui-mask | 全屏半透明遮罩层样式,用于模态弹窗或加载中效果 |
| .weui-loading | 加载动画容器,配合旋转动画显示 |
| .weui-loading:before | 加载动画的具体圆环图形部分 |
| .weui-toast | 全局提示(Toast)容器样式 |
| .weui-icon_toast | Toast 中图标样式(如成功、失败、警告等图标) |
| .weui-toast__content | Toast 中文字内容样式 |
| .weui-loading_toast | 加载中时显示的 Toast 样式(含 loading 图标与提示文字) |
| .weui-loading_toast .weui-toast__content | 加载提示文字样式 |
Flex布局与自定义工具类(Flex & Utility Classes)
| 类名 | 描述说明 |
|---|---|
| .flex | 设置为 display: flex,用于弹性布局容器 |
| .flex-v | 垂直方向的弹性布局(flex-direction: column) |
| .flex-h | 水平方向的弹性布局(flex-direction: row) |
| .jc-between | 主轴方向两端对齐(justify-content: space-between) |
| .jc-center | 主轴方向居中对齐(justify-content: center) |
| .ai-center | 交叉轴方向居中对齐(align-items: center) |
| .wrap | 内容自动换行(flex-wrap: wrap) |
| .nowrap | 内容不换行(flex-wrap: nowrap) |
| .grow | 项目可伸展填满剩余空间(flex-grow: 1) |
| .shrink | 项目允许收缩(flex-shrink: 1) |
| .basis-0 | 初始主轴尺寸为 0(flex-basis: 0) |
媒体查询与响应式设计(Media Queries & Responsive Utilities)
| 类名 / 区块 | 描述说明 |
|---|---|
| @media screen and (max-width: 768px) | 针对平板及以下设备的样式适配。常用于设置字体大小、按钮尺寸等 |
| .hide-sm | 小屏幕下隐藏元素 |
| .show-sm | 小屏幕下显示元素 |
| @media (min-width: 769px) | 针对桌面端设备的样式适配 |
| .hide-md | 中屏及以上隐藏 |
| .show-md | 中屏及以上显示 |
| .responsive-img | 图片宽度 100%,高度自适应 |
| .full-width | 设置宽度为 100% |
| .auto-width | 宽度自动,根据内容调整 |
| .max-w-640 | 设置最大宽度为 640px,常用于中小屏限制表单或内容块宽度 |
动画与过渡效果(Animations & Transitions)
| 类名 / 属性片段 | 描述说明 |
|---|---|
| .fade-in | 淡入动画效果,通常与 opacity: 0 → 1 配合 transition 使用 |
| .fade-out | 淡出动画效果,反向透明度动画 |
| .slide-up | 向上滑入效果(常用于弹出层、提示条等) |
| .slide-down | 向下滑入效果(同上) |
| .transition-all | 统一应用所有变化属性的过渡动画(如背景色、边距、透明度等) |
| .transition-fast | 设置过渡速度较快(如 0.2s) |
| .transition-slow | 设置过渡速度较慢(如 0.5s 或以上) |
| .animated | 通用动画类,和其他如 fade-in 组合使用 |
| @keyframes fadeIn | 定义淡入关键帧动画 |
| @keyframes slideUp | 向上滑动关键帧动画 |
卡片样式(Card Style)
| 类名 / 结构元素 | 描述说明 |
|---|---|
| .card | 通用卡片容器,通常包含背景、圆角、阴影,适合信息块、模块展示等 |
| .card-header | 卡片头部区域,常用于标题显示或图标 |
| .card-body | 卡片主要内容区域,包含文字、按钮、输入框等 |
| .card-footer | 卡片底部区域,常用于操作按钮、备注信息等 |
| .card-shadow | 应用于 .card 的阴影效果增强(如 box-shadow) |
| .card-radius | 圆角卡片边框(可设为 4px, 8px, 12px 不同风格) |
| .card-bordered | 卡片边框样式,搭配 .card 使用更具分割感 |
| .card-hover:hover | 鼠标悬浮时变色或阴影增强效果,提升交互感 |
| .card-image | 卡片中的图片容器(如顶部配图或图标) |
| .card-title | 卡片标题专用样式 |
| .card-text | 卡片正文文本样式 |
| .card-disabled | 禁用态卡片,背景变淡,文字变灰,禁止点击 |
提示/标签样式(Tips & Labels)
| 类名 / 结构元素 | 描述说明 |
|---|---|
| .label | 通用标签样式,适用于状态标签、分类提示等 |
| .label-success | 成功状态标签,绿色背景 |
| .label-warning | 警告状态标签,黄色背景 |
| .label-error | 错误状态标签,红色背景 |
| .label-info | 提示信息标签,蓝色背景 |
| .label-round | 圆角标签样式 |
| .tip-text | 小号提示文字,例如“必填”“最多50字”等 |
| .tip-error | 红色错误提示文字 |
| .tip-success | 成功提示文字,通常绿色 |
| .tip-icon | 搭配图标使用的提示样式 |
| .notice | 公告提示类容器(灰底圆角) |
模态窗口 / 弹窗(Modal / Dialog)
| 类名 / 元素结构 | 描述说明 |
|---|---|
| .modal | 模态窗口主容器,通常为固定定位 + 遮罩层 |
| .modal-dialog | 弹窗内容容器,用于承载标题、正文和按钮 |
| .modal-header | 模态标题区域 |
| .modal-title | 弹窗标题文字 |
| .modal-body | 主体内容区域,支持富文本或表单 |
| .modal-footer | 底部按钮区域,通常放置“取消”和“确定”按钮 |
| .modal-btn | 弹窗按钮基础类 |
| .modal-btn-primary | 主操作按钮(蓝色/绿色背景) |
| .modal-btn-cancel | 取消按钮(灰色) |
| .modal-close | 关闭图标按钮(通常右上角 ×) |
| .modal-mask | 背景遮罩,点击可关闭弹窗(视交互设计而定) |
Tabs 标签页组件(Tab Navigation)
| 类名 / 结构 | 描述说明 |
|---|---|
| .tab-container | 标签页容器外框 |
| .tab-header | 标签导航区(横向按钮) |
| .tab-header-item | 单个 tab 按钮 |
| .tab-header-item.active | 激活状态的 tab |
| .tab-content | 内容区父容器 |
| .tab-panel | 每个标签页的内容区域 |
| .tab-panel.active | 当前激活内容区域 |
Iconfont 图标使用规范(Icon Fonts)
| 类名 / 使用方式 | 描述说明 |
|---|---|
| .iconfont | 通用字体图标基础类,需与字体文件 @font-face 搭配使用 |
| .icon-xxx:before | 图标类命名(如 .icon-fabui1),通过 content 输出符号 |
| font-family: "iconfont" | 必须设置字体为 iconfont 才能正确显示图标 |
| 示例: | 使用方式,i 标签为常见容器 |
补充说明:
- 字体图标基于 .woff2/.woff/.ttf 文件引用;
- 图标 unicode(如 \e607)必须匹配字体映射;
- 图标大小/颜色可通过 font-size 和 color 控制;
- 图标垂直对齐建议使用 line-height 或 vertical-align 调整;
辅助显示类(Utility Display Classes)
| 类名 | 描述说明 |
|---|---|
| .hide, .dn | 隐藏元素(display: none) |
| .show, .db | 显示块级元素(display: block) |
| .di, .dib | 行内元素 / 行内块级显示 |
| .va-m, .va-t | vertical-align 中部 / 顶部 |
| .clearfix | 清除浮动 |
| .hidden-xs | 隐藏小屏(移动)设备 |
| .visible-xs | 仅在小屏显示 |
.xg- 自定义样式组件(Xigua 定制)
| 类名 | 描述说明 |
|---|---|
| .xg-header, .x_header | 顶部导航栏容器,含背景色、字体设置 |
| .xg-footer | 自定义页脚容器样式 |
| .xg-toptip-error | 顶部错误提示样式,背景红色、白色文字 |
| .xg-title | 页面标题,通常居中加粗 |
| .xg-form-wrap | 表单外层容器类,带 padding |
| .xg-input | 自定义输入框样式 |
| .xg-btn, .xg-btn-red | 自定义按钮类,红色为强调操作 |
| .xg-divider | 分隔线(灰色细线) |
| .xg-list, .xg-item | 用于自定义列表结构的类 |
| .xg-note, .xg-alert | 提示文案 / 公告块,配合边框和背景色 |
WeUI 自带组件辅助类总结(weui-)
- 注意:这些类配合 weui.css 使用(如 weui-form, weui-input 等)
| 类名 | 描述说明 |
|---|---|
| .weui-form | 表单主容器 |
| .weui-input, .weui-select, .weui-textarea | 表单控件(输入框 / 下拉 / 文本域) |
| .weui-cell, .weui-cell__bd | 表单项结构(cell 模块) |
| .weui-btn, .weui-btn_primary | 按钮与主按钮 |
| .weui-agree, .weui-agree__checkbox, .weui-agree__text | 协议勾选部分 |
| .weui-toast, .weui-toast__content | 弹出提示(JS 控制) |
| .weui-icon-warn, .weui-icon_toast | 图标配合 toast 提示使用 |