通达OA模块开发实战

101 阅读3分钟

一、引言

模块开发是通达OA二次开发的核心内容。本文将通过一个完整的实战案例,详细介绍如何创建一个功能完善的OA模块,包括目录结构、数据库设计、代码编写、菜单注册和权限分配等环节。

二、开发前准备

2.1 需求分析

假设我们需要开发一个"项目管理"模块,包含以下功能:

2.2 数据库设计

项目表(project) :

字段名类型说明
project_idint项目ID(主键,自增)
project_namevarchar(100)项目名称
descriptiontext项目描述
start_datedate开始日期
end_datedate结束日期
statustinyint状态(0=进行中,1=已完成)
creator_uidint创建人ID
create_timedatetime创建时间
update_timedatetime更新时间

数据库关系图:

三、模块开发步骤

3.1 步骤一:建立模块目录

在 MYOA\webroot\general 目录下创建模块目录:

New-Item -ItemType Directory -Path "MYOA\webroot\general\project"

目录结构规划:

project/
├── index.php          # 项目列表页
├── add.php            # 添加项目页
├── edit.php           # 编辑项目页
├── detail.php         # 项目详情页
├── delete.php         # 删除项目接口
├── ajax.php           # AJAX接口
└── style.css          # 模块样式文件

3.2 步骤二:创建数据库表

使用phpMyAdmin或SQL语句创建表:

CREATE TABLE IF NOT EXISTS `project` (
    `project_id` int(11) NOT NULL AUTO_INCREMENT,
    `project_name` varchar(100) NOT NULL,
    `description` text,
    `start_date` date DEFAULT NULL,
    `end_date` date DEFAULT NULL,
    `status` tinyint(1) DEFAULT '0',
    `creator_uid` int(11) NOT NULL,
    `create_time` datetime DEFAULT CURRENT_TIMESTAMP,
    `update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`project_id`),
    KEY `creator_uid` (`creator_uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.3 步骤三:编写核心代码

3.3.1 项目列表页(index.php)

<?php
$HTML_PAGE_TITLE = _("项目管理");
include_once("inc/auth.inc.php");
include_once("inc/header.inc.php");

$td = new TD();

// 分页参数
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
$page_size = 10;
$offset = ($page - 1) * $page_size;

// 查询项目列表
$sql = "SELECT p.*, u.name AS creator_name 
        FROM project p 
        LEFT JOIN user u ON p.creator_uid = u.uid 
        ORDER BY p.create_time DESC 
        LIMIT $offset, $page_size";
$result = $td->query($sql);

// 查询总数
$count_sql = "SELECT COUNT(*) AS total FROM project";
$count_result = $td->query($count_sql);
$count_row = $td->fetch_array($count_result);
$total = $count_row['total'];
$total_pages = ceil($total / $page_size);
?>

<div class="main-content">
    <h2><?php echo _("项目列表"); ?></h2>
    
    <a href="add.php" class="btn btn-primary">
        <?php echo _("添加项目"); ?>
    </a>
    
    <table class="table">
        <thead>
            <tr>
                <th><?php echo _("项目名称"); ?></th>
                <th><?php echo _("描述"); ?></th>
                <th><?php echo _("时间范围"); ?></th>
                <th><?php echo _("状态"); ?></th>
                <th><?php echo _("创建人"); ?></th>
                <th><?php echo _("操作"); ?></th>
            </tr>
        </thead>
        <tbody>
            <?php while ($row = $td->fetch_array($result)) { ?>
            <tr>
                <td><?php echo $row['project_name']; ?></td>
                <td><?php echo csubstr($row['description'], 0, 50); ?></td>
                <td><?php echo $row['start_date'] . ' ~ ' . $row['end_date']; ?></td>
                <td><?php echo $row['status'] ? _('已完成') : _('进行中'); ?></td>
                <td><?php echo $row['creator_name']; ?></td>
                <td>
                    <a href="detail.php?id=<?php echo $row['project_id']; ?>">
                        <?php echo _("查看"); ?>
                    </a>
                    <a href="edit.php?id=<?php echo $row['project_id']; ?>">
                        <?php echo _("编辑"); ?>
                    </a>
                    <a href="delete.php?id=<?php echo $row['project_id']; ?>" 
                       onclick="return confirm('<?php echo _('确定删除?'); ?>')">
                        <?php echo _("删除"); ?>
                    </a>
                </td>
            </tr>
            <?php } ?>
        </tbody>
    </table>
    
    <?php // 分页代码省略 ?>
</div>

<?php
include_once("inc/footer.inc.php");
?>

3.3.2 添加项目页(add.php)

<?php
$HTML_PAGE_TITLE = _("添加项目");
include_once("inc/auth.inc.php");
include_once("inc/header.inc.php");

if ($_POST) {
    $td = new TD();
    
    $project_name = $td->escape($_POST['project_name']);
    $description = $td->escape($_POST['description']);
    $start_date = $_POST['start_date'];
    $end_date = $_POST['end_date'];
    $creator_uid = $_SESSION['uid'];
    
    $sql = "INSERT INTO project (project_name, description, start_date, end_date, creator_uid) 
            VALUES ('$project_name', '$description', '$start_date', '$end_date', $creator_uid)";
    
    if ($td->query($sql)) {
        Message(_("添加成功"), "index.php");
        exit;
    } else {
        Message(_("添加失败"), "add.php");
        exit;
    }
}
?>

<div class="main-content">
    <h2><?php echo _("添加项目"); ?></h2>
    
    <form method="post" action="add.php">
        <div class="form-group">
            <label><?php echo _("项目名称"); ?>:</label>
            <input type="text" name="project_name" required class="form-control">
        </div>
        
        <div class="form-group">
            <label><?php echo _("项目描述"); ?>:</label>
            <textarea name="description" class="form-control"></textarea>
        </div>
        
        <div class="form-group">
            <label><?php echo _("开始日期"); ?>:</label>
            <input type="date" name="start_date" required class="form-control">
        </div>
        
        <div class="form-group">
            <label><?php echo _("结束日期"); ?>:</label>
            <input type="date" name="end_date" required class="form-control">
        </div>
        
        <button type="submit" class="btn btn-primary">
            <?php echo _("提交"); ?>
        </button>
        <a href="index.php" class="btn btn-default">
            <?php echo _("返回"); ?>
        </a>
    </form>
</div>

<?php
include_once("inc/footer.inc.php");
?>

3.3.3 删除项目(delete.php)

<?php
include_once("inc/auth.inc.php");

$td = new TD();
$project_id = isset($_GET['id']) ? intval($_GET['id']) : 0;

if ($project_id > 0) {
    $sql = "DELETE FROM project WHERE project_id = $project_id";
    if ($td->query($sql)) {
        Message(_("删除成功"), "index.php");
    } else {
        Message(_("删除失败"), "index.php");
    }
} else {
    Message(_("参数错误"), "index.php");
}
?>

3.4 步骤四:注册菜单

在通达OA系统管理中注册菜单:

Mermaid 渲染失败: Lexical error on line 9. Unrecognized text.
...al/project/index.php]    E -->|父菜单| E3[
-----------------------^

菜单注册信息:

字段值
菜单名称项目管理
菜单地址/general/project/index.php
父菜单工作台(或其他合适的父菜单)
菜单图标选择合适的图标
排序号根据需要设置

3.5 步骤五:分配权限

权限分配步骤:

  1. 进入系统管理 → 角色管理
  2. 选择需要分配权限的角色
  3. 点击"编辑权限"
  4. 在权限列表中找到"项目管理"并勾选
  5. 保存权限设置

四、高级功能开发

4.1 附件上传功能

使用OA内置的文件上传函数:

<?php
include_once("inc/utility_file.php");

// 处理文件上传
if ($_FILES['attachment']['name']) {
    $attach = upload('attachment', 0, 0, 'project');
    if ($attach['error'] == 0) {
        $attach_id = $attach['id'];
        // 保存附件ID到数据库
    }
}
?>

4.2 人员选择组件

使用OA的人员选择组件:

<?php
include_once("inc/header.inc.php");
?>

<!-- 人员多选组件 -->
<input type="hidden" name="user_ids" id="user_ids">
<script type="text/javascript">
    // 调用人员选择组件
    selectUser('user_ids', 'multi');
</script>

4.3 AJAX交互

<?php
// ajax.php
include_once("inc/auth.inc.php");

$action = isset($_GET['action']) ? $_GET['action'] : '';

if ($action == 'search') {
    $keyword = $_GET['keyword'];
    $td = new TD();
    $keyword = $td->escape($keyword);
    
    $sql = "SELECT * FROM project WHERE project_name LIKE '%$keyword%'";
    $result = $td->query($sql);
    
    $data = array();
    while ($row = $td->fetch_array($result)) {
        $data[] = $row;
    }
    
    echo json_encode($data);
    exit;
}
?>

五、调试与测试

5.1 调试方法

调试工具:

工具用途
php_errors.logPHP错误日志
浏览器开发者工具前端调试
phpMyAdmin数据库查询
var_dump()变量输出

5.2 测试用例

功能测试:

测试项测试步骤预期结果
添加项目填写表单提交项目成功添加
编辑项目修改信息提交项目信息更新
删除项目点击删除确认项目成功删除
列表显示访问列表页显示所有项目
权限控制无权限用户访问提示无权限

六、模块部署与发布

6.1 部署流程

6.2 发布清单

项目说明
代码文件所有PHP文件
样式文件CSS文件
数据库脚本SQL文件
配置文件菜单配置
权限配置角色权限

七、最佳实践总结

7.1 代码规范

编码规范:

规范项要求
变量命名驼峰式命名
文件命名小写字母,下划线分隔
数据库表小写字母,下划线分隔
SQL语句使用TD类的escape方法转义

7.2 安全注意事项

  1. 输入验证:对所有用户输入进行验证
  2. SQL注入:使用参数化查询或escape方法
  3. 文件上传:验证文件类型和大小
  4. 权限控制:使用auth.inc.php进行权限验证
  5. 敏感信息:不输出敏感信息到页面