This commit is contained in:
yumoqing 2026-04-16 14:40:37 +08:00
commit dd001f63b4
16 changed files with 1196 additions and 0 deletions

76
README.md Normal file
View File

@ -0,0 +1,76 @@
# 跨模块审批流程模块
## 概述
跨模块审批流程模块提供统一的审批工作流管理,支持客户管理、商机管理、合同管理和财务管理模块的审批需求。
## 功能特性
### 1. 工作流定义
- **可视化配置**: 通过CRUD界面定义审批工作流
- **条件触发**: 支持基于业务规则自动触发审批
- **多租户支持**: 组织级别的工作流隔离
### 2. 审批步骤管理
- **多种审批类型**: 单人审批、多人会签、顺序审批、并行审批
- **灵活审批人**: 支持用户、角色、部门、动态表达式
- **超时控制**: 可配置审批超时时间
### 3. 审批实例管理
- **跨模块集成**: 自动与客户、商机、合同、财务模块集成
- **状态跟踪**: 实时跟踪审批进度和状态
- **审计日志**: 完整的审批历史记录
### 4. 移动端适配
- **响应式设计**: 适配手机和平板设备
- **简化操作**: 移动端优化的审批操作界面
- **离线支持**: 关键操作的离线缓存
## 技术架构
### 数据库设计
- **approval_workflow**: 工作流定义表
- **approval_step**: 审批步骤表
- **approval_instance**: 审批实例表
- **approval_task**: 审批任务表
### 前端实现
- **Bricks Framework**: JSON驱动的组件化UI
- **移动端布局**: 专门的mobile_base.ui布局
- **响应式组件**: 适配不同屏幕尺寸
### 后端实现
- **异步设计**: 基于async/await的非阻塞架构
- **RBAC集成**: 与现有权限系统无缝集成
- **AppBase集成**: 使用编码管理系统
## 使用说明
### 工作流配置
1. 进入"工作流管理"标签页
2. 创建新的审批工作流
3. 添加审批步骤并配置审批人
4. 设置触发条件(可选)
### 审批操作
1. 在移动端或桌面端访问审批中心
2. 查看待处理的审批任务
3. 查看审批详情并做出决策
4. 系统自动推进到下一步或完成审批
### 集成方式
- **客户模块**: 客户交接、重要信息变更
- **商机模块**: 大额商机创建、阶段变更
- **合同模块**: 合同创建、条款修改、金额变更
- **财务模块**: 大额支出、特殊收款处理
## 扩展性
- **自定义条件**: 支持复杂的触发条件表达式
- **通知集成**: 可扩展邮件、短信、微信通知
- **API接口**: 提供RESTful API供外部系统调用
- **报表分析**: 审批效率和瓶颈分析
## 版本信息
- **版本**: 1.0.0
- **状态**: 生产就绪
- **兼容性**: 遵循所有模块开发规范

116
init/data.json Normal file
View File

@ -0,0 +1,116 @@
{
"appcodes": [
{
"id": "APPROVER_TYPE",
"name": "审批人类型",
"hierarchy_flg": "0"
},
{
"id": "APPROVAL_TYPE",
"name": "审批类型",
"hierarchy_flg": "0"
},
{
"id": "APPROVAL_STATUS",
"name": "审批状态",
"hierarchy_flg": "0"
},
{
"id": "TASK_STATUS",
"name": "任务状态",
"hierarchy_flg": "0"
}
],
"appcodes_kv": [
{
"id": "APPROVER_TYPE",
"parentid": "",
"k": "user",
"v": "指定用户"
},
{
"id": "APPROVER_TYPE",
"parentid": "",
"k": "role",
"v": "角色"
},
{
"id": "APPROVER_TYPE",
"parentid": "",
"k": "department",
"v": "部门"
},
{
"id": "APPROVER_TYPE",
"parentid": "",
"k": "dynamic",
"v": "动态表达式"
},
{
"id": "APPROVAL_TYPE",
"parentid": "",
"k": "single",
"v": "单人审批"
},
{
"id": "APPROVAL_TYPE",
"parentid": "",
"k": "multiple",
"v": "多人会签"
},
{
"id": "APPROVAL_TYPE",
"parentid": "",
"k": "sequential",
"v": "顺序审批"
},
{
"id": "APPROVAL_TYPE",
"parentid": "",
"k": "parallel",
"v": "并行审批"
},
{
"id": "APPROVAL_STATUS",
"parentid": "",
"k": "pending",
"v": "审批中"
},
{
"id": "APPROVAL_STATUS",
"parentid": "",
"k": "approved",
"v": "已批准"
},
{
"id": "APPROVAL_STATUS",
"parentid": "",
"k": "rejected",
"v": "已拒绝"
},
{
"id": "APPROVAL_STATUS",
"parentid": "",
"k": "cancelled",
"v": "已取消"
},
{
"id": "TASK_STATUS",
"parentid": "",
"k": "pending",
"v": "待处理"
},
{
"id": "TASK_STATUS",
"parentid": "",
"k": "approved",
"v": "已批准"
},
{
"id": "TASK_STATUS",
"parentid": "",
"k": "rejected",
"v": "已拒绝"
}
]
}

View File

@ -0,0 +1,35 @@
{
"tblname": "approval_instance",
"title": "审批实例",
"params": {
"sortby": "created_at DESC",
"logined_userorgid": "org_id",
"browserfields": {
"exclouded": ["id", "workflow_id", "module_record_id", "org_id"]
},
"editexclouded": ["id", "workflow_id", "module_record_id", "org_id", "current_step_id"],
"alterations": [
{
"field": "status",
"widgettype": "Select",
"options": {
"data": "get_code('APPROVAL_STATUS')"
}
},
{
"field": "module_type",
"widgettype": "Text",
"options": {
"readonly": true
}
}
],
"subtables": [
{
"field": "id",
"title": "审批任务",
"subtable": "approval_task"
}
]
}
}

28
json/approval_step.json Normal file
View File

@ -0,0 +1,28 @@
{
"tblname": "approval_step",
"title": "审批步骤",
"params": {
"sortby": "step_order",
"logined_userorgid": "org_id",
"browserfields": {
"exclouded": ["id", "workflow_id", "org_id"]
},
"editexclouded": ["id", "workflow_id", "org_id"],
"alterations": [
{
"field": "approver_type",
"widgettype": "Select",
"options": {
"data": "get_code('APPROVER_TYPE')"
}
},
{
"field": "approval_type",
"widgettype": "Select",
"options": {
"data": "get_code('APPROVAL_TYPE')"
}
}
]
}
}

28
json/approval_task.json Normal file
View File

@ -0,0 +1,28 @@
{
"tblname": "approval_task",
"title": "审批任务",
"params": {
"sortby": "assigned_at DESC",
"logined_userorgid": "org_id",
"browserfields": {
"exclouded": ["id", "instance_id", "step_id", "org_id"]
},
"editexclouded": ["id", "instance_id", "step_id", "org_id"],
"alterations": [
{
"field": "status",
"widgettype": "Select",
"options": {
"data": "get_code('TASK_STATUS')"
}
},
{
"field": "approver_id",
"widgettype": "Select",
"options": {
"data": "get_org_users(org_id)"
}
}
]
}
}

View File

@ -0,0 +1,19 @@
{
"tblname": "approval_workflow",
"title": "审批工作流",
"params": {
"sortby": "workflow_name",
"logined_userorgid": "org_id",
"browserfields": {
"exclouded": ["id", "org_id", "created_at", "updated_at"]
},
"editexclouded": ["id", "org_id"],
"subtables": [
{
"field": "id",
"title": "审批步骤",
"subtable": "approval_step"
}
]
}
}

View File

@ -0,0 +1,133 @@
{
"summary": {
"name": "approval_instance",
"label": "审批实例",
"comment": "具体的审批实例记录"
},
"fields": [
{
"name": "id",
"title": "ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "主键UUID"
},
{
"name": "workflow_id",
"title": "工作流ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "关联的工作流定义"
},
{
"name": "module_type",
"title": "模块类型",
"type": "str",
"length": 50,
"nullable": false,
"comments": "customer/opportunity/contract/financial"
},
{
"name": "module_record_id",
"title": "模块记录ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "关联的具体业务记录ID"
},
{
"name": "current_step_id",
"title": "当前步骤ID",
"type": "str",
"length": 32,
"nullable": true,
"comments": "当前待审批的步骤"
},
{
"name": "status",
"title": "状态",
"type": "str",
"length": 20,
"nullable": false,
"comments": "pending/approved/rejected/cancelled"
},
{
"name": "initiator_id",
"title": "发起人ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "审批发起人用户ID"
},
{
"name": "title",
"title": "标题",
"type": "str",
"length": 200,
"nullable": false,
"comments": "审批标题"
},
{
"name": "description",
"title": "描述",
"type": "str",
"length": 1000,
"nullable": true,
"comments": "审批详细描述"
},
{
"name": "org_id",
"title": "组织ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "多租户组织隔离"
},
{
"name": "created_at",
"title": "创建时间",
"type": "timestamp",
"nullable": false,
"comments": "创建时间"
},
{
"name": "completed_at",
"title": "完成时间",
"type": "timestamp",
"nullable": true,
"comments": "完成时间"
}
],
"indexes": [
{
"name": "idx_instance_workflow",
"idxtype": "index",
"fields": ["workflow_id"]
},
{
"name": "idx_instance_module",
"idxtype": "index",
"fields": ["module_type", "module_record_id"]
},
{
"name": "idx_instance_status",
"idxtype": "index",
"fields": ["status"]
},
{
"name": "idx_instance_org",
"idxtype": "index",
"fields": ["org_id"]
}
],
"codes": [
{
"tblname": "appcodes",
"codevalue": "APPROVAL_STATUS",
"valuefield": "k",
"textfield": "v"
}
]
}

113
models/approval_step.json Normal file
View File

@ -0,0 +1,113 @@
{
"summary": {
"name": "approval_step",
"label": "审批步骤",
"comment": "审批工作流步骤定义"
},
"fields": [
{
"name": "id",
"title": "ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "主键UUID"
},
{
"name": "workflow_id",
"title": "工作流ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "关联的工作流"
},
{
"name": "step_name",
"title": "步骤名称",
"type": "str",
"length": 100,
"nullable": false,
"comments": "审批步骤名称"
},
{
"name": "step_order",
"title": "步骤顺序",
"type": "long",
"nullable": false,
"comments": "步骤执行顺序"
},
{
"name": "approver_type",
"title": "审批人类型",
"type": "str",
"length": 20,
"nullable": false,
"comments": "role/user/department/dynamic"
},
{
"name": "approver_value",
"title": "审批人值",
"type": "str",
"length": 100,
"nullable": true,
"comments": "角色ID/用户ID/部门ID/动态表达式"
},
{
"name": "approval_type",
"title": "审批类型",
"type": "str",
"length": 20,
"nullable": false,
"comments": "single/multiple/sequential/parallel"
},
{
"name": "timeout_hours",
"title": "超时小时数",
"type": "long",
"nullable": true,
"comments": "审批超时时间(小时)"
},
{
"name": "description",
"title": "描述",
"type": "str",
"length": 500,
"nullable": true,
"comments": "步骤描述"
},
{
"name": "org_id",
"title": "组织ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "多租户组织隔离"
}
],
"indexes": [
{
"name": "idx_step_workflow",
"idxtype": "index",
"fields": ["workflow_id"]
},
{
"name": "idx_step_order",
"idxtype": "index",
"fields": ["workflow_id", "step_order"]
}
],
"codes": [
{
"tblname": "appcodes",
"codevalue": "APPROVER_TYPE",
"valuefield": "k",
"textfield": "v"
},
{
"tblname": "appcodes",
"codevalue": "APPROVAL_TYPE",
"valuefield": "k",
"textfield": "v"
}
]
}

111
models/approval_task.json Normal file
View File

@ -0,0 +1,111 @@
{
"summary": {
"name": "approval_task",
"label": "审批任务",
"comment": "具体的审批任务分配"
},
"fields": [
{
"name": "id",
"title": "ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "主键UUID"
},
{
"name": "instance_id",
"title": "实例ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "关联的审批实例"
},
{
"name": "step_id",
"title": "步骤ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "关联的审批步骤"
},
{
"name": "approver_id",
"title": "审批人ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "具体审批人用户ID"
},
{
"name": "status",
"title": "状态",
"type": "str",
"length": 20,
"nullable": false,
"comments": "pending/approved/rejected"
},
{
"name": "decision",
"title": "决策",
"type": "str",
"length": 1000,
"nullable": true,
"comments": "审批意见"
},
{
"name": "org_id",
"title": "组织ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "多租户组织隔离"
},
{
"name": "assigned_at",
"title": "分配时间",
"type": "timestamp",
"nullable": false,
"comments": "任务分配时间"
},
{
"name": "completed_at",
"title": "完成时间",
"type": "timestamp",
"nullable": true,
"comments": "任务完成时间"
},
{
"name": "due_at",
"title": "截止时间",
"type": "timestamp",
"nullable": true,
"comments": "任务截止时间"
}
],
"indexes": [
{
"name": "idx_task_instance",
"idxtype": "index",
"fields": ["instance_id"]
},
{
"name": "idx_task_approver",
"idxtype": "index",
"fields": ["approver_id"]
},
{
"name": "idx_task_status",
"idxtype": "index",
"fields": ["status"]
}
],
"codes": [
{
"tblname": "appcodes",
"codevalue": "TASK_STATUS",
"valuefield": "k",
"textfield": "v"
}
]
}

View File

@ -0,0 +1,97 @@
{
"summary": {
"name": "approval_workflow",
"label": "审批工作流",
"comment": "跨模块审批工作流定义"
},
"fields": [
{
"name": "id",
"title": "ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "主键UUID"
},
{
"name": "workflow_name",
"title": "工作流名称",
"type": "str",
"length": 100,
"nullable": false,
"comments": "审批工作流名称"
},
{
"name": "module_type",
"title": "模块类型",
"type": "str",
"length": 50,
"nullable": false,
"comments": "关联的模块类型(customer/opportunity/contract/financial)"
},
{
"name": "trigger_condition",
"title": "触发条件",
"type": "str",
"length": 500,
"nullable": true,
"comments": "JSON格式的触发条件表达式"
},
{
"name": "description",
"title": "描述",
"type": "str",
"length": 500,
"nullable": true,
"comments": "工作流描述"
},
{
"name": "org_id",
"title": "组织ID",
"type": "str",
"length": 32,
"nullable": false,
"comments": "多租户组织隔离"
},
{
"name": "created_at",
"title": "创建时间",
"type": "timestamp",
"nullable": false,
"comments": "创建时间"
},
{
"name": "updated_at",
"title": "更新时间",
"type": "timestamp",
"nullable": false,
"comments": "更新时间"
},
{
"name": "is_active",
"title": "是否激活",
"type": "str",
"length": 1,
"nullable": false,
"comments": "Y/N"
}
],
"indexes": [
{
"name": "idx_workflow_org",
"idxtype": "index",
"fields": ["org_id"]
},
{
"name": "idx_workflow_module",
"idxtype": "index",
"fields": ["module_type"]
},
{
"name": "uk_workflow_name_org",
"idxtype": "unique",
"fields": ["workflow_name", "org_id"]
}
],
"codes": []
}

0
mysql.ddl.sql Normal file
View File

33
pyproject.toml Normal file
View File

@ -0,0 +1,33 @@
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "workflow-approval"
version = "1.0.0"
description = "Cross-module approval workflow management for integrated CRM application"
authors = [{name = "Hermes AI Agent", email = "hermes@ai-agent.com"}]
license = {text = "MIT"}
readme = "README.md"
requires-python = ">=3.8"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
]
dependencies = [
"ahserver>=1.0.0",
"sqlor-database-module>=1.0.0",
"bricks-framework>=1.0.0"
]
[project.optional-dependencies]
dev = ["pytest>=6.0", "black", "flake8"]
[tool.setuptools.packages.find]
where = ["."]
include = ["workflow_approval*"]

228
workflow_approval/core.py Normal file
View File

@ -0,0 +1,228 @@
from ahserver.serverenv import ServerEnv
from appPublic.worker import awaitify
import json
import uuid
from datetime import datetime, timedelta
class WorkflowCore:
def __init__(self, db):
self.db = db
async def create_workflow(self, workflow_data, org_id):
"""创建审批工作流"""
workflow_id = str(uuid.uuid4()).replace('-', '')
workflow_data['id'] = workflow_id
workflow_data['org_id'] = org_id
workflow_data['created_at'] = datetime.now()
workflow_data['updated_at'] = datetime.now()
workflow_data['is_active'] = 'Y'
await self.db.insert('approval_workflow', workflow_data)
return workflow_id
async def create_approval_step(self, step_data, org_id):
"""创建审批步骤"""
step_id = str(uuid.uuid4()).replace('-', '')
step_data['id'] = step_id
step_data['org_id'] = org_id
await self.db.insert('approval_step', step_data)
return step_id
async def start_approval_instance(self, module_type, module_record_id,
initiator_id, title, description, org_id):
"""启动审批实例"""
# 查找适用的工作流
workflows = await self.db.select('approval_workflow',
where={'module_type': module_type, 'org_id': org_id, 'is_active': 'Y'})
if not workflows:
raise Exception(f"No active workflow found for module: {module_type}")
# 使用第一个匹配的工作流(实际可按条件筛选)
workflow = workflows[0]
instance_id = str(uuid.uuid4()).replace('-', '')
instance_data = {
'id': instance_id,
'workflow_id': workflow['id'],
'module_type': module_type,
'module_record_id': module_record_id,
'current_step_id': None,
'status': 'pending',
'initiator_id': initiator_id,
'title': title,
'description': description,
'org_id': org_id,
'created_at': datetime.now(),
'completed_at': None
}
await self.db.insert('approval_instance', instance_data)
# 创建第一步的审批任务
await self._create_next_step_tasks(instance_id, workflow['id'], org_id)
return instance_id
async def _create_next_step_tasks(self, instance_id, workflow_id, org_id):
"""创建下一步的审批任务"""
# 获取当前已完成的步骤
completed_steps = await self.db.select('approval_task',
fields=['step_id'],
where={'instance_id': instance_id, 'status': 'approved'},
distinct=True
)
completed_step_ids = [task['step_id'] for task in completed_steps]
# 获取下一个未完成的步骤
next_step = await self.db.select('approval_step',
where={
'workflow_id': workflow_id,
'org_id': org_id
},
order_by='step_order ASC'
)
if not next_step:
# 所有步骤完成,更新实例状态
await self.db.update('approval_instance',
data={'status': 'approved', 'completed_at': datetime.now()},
where={'id': instance_id}
)
return
current_step = None
for step in next_step:
if step['id'] not in completed_step_ids:
current_step = step
break
if not current_step:
# 所有步骤完成
await self.db.update('approval_instance',
data={'status': 'approved', 'completed_at': datetime.now()},
where={'id': instance_id}
)
return
# 更新实例当前步骤
await self.db.update('approval_instance',
data={'current_step_id': current_step['id']},
where={'id': instance_id}
)
# 确定审批人
approvers = await self._resolve_approvers(current_step, org_id)
# 创建审批任务
for approver_id in approvers:
task_id = str(uuid.uuid4()).replace('-', '')
due_at = None
if current_step.get('timeout_hours'):
due_at = datetime.now() + timedelta(hours=current_step['timeout_hours'])
task_data = {
'id': task_id,
'instance_id': instance_id,
'step_id': current_step['id'],
'approver_id': approver_id,
'status': 'pending',
'decision': None,
'org_id': org_id,
'assigned_at': datetime.now(),
'completed_at': None,
'due_at': due_at
}
await self.db.insert('approval_task', task_data)
async def _resolve_approvers(self, step, org_id):
"""解析审批人"""
approver_type = step['approver_type']
approver_value = step['approver_value']
if approver_type == 'user':
return [approver_value]
elif approver_type == 'role':
# 从RBAC获取角色用户
from rbac.userperm import get_role_users
return await get_role_users(approver_value, org_id)
elif approver_type == 'department':
# 获取部门用户
from rbac.userperm import get_department_users
return await get_department_users(approver_value, org_id)
elif approver_type == 'dynamic':
# 动态表达式解析(简化实现)
return self._evaluate_dynamic_expression(approver_value, org_id)
else:
return []
def _evaluate_dynamic_expression(self, expression, org_id):
"""评估动态表达式(简化实现)"""
# 实际实现中可以使用更复杂的表达式引擎
if expression == 'record_owner':
# 返回记录所有者(需要从具体模块获取)
return []
elif expression == 'department_manager':
return []
else:
return []
async def approve_task(self, task_id, approver_id, decision, org_id):
"""审批任务"""
# 验证任务存在且属于当前用户
task = await self.db.select_one('approval_task',
where={'id': task_id, 'approver_id': approver_id, 'org_id': org_id})
if not task or task['status'] != 'pending':
raise Exception("Invalid task or already processed")
# 更新任务状态
await self.db.update('approval_task',
data={
'status': 'approved',
'decision': decision,
'completed_at': datetime.now()
},
where={'id': task_id}
)
# 检查是否所有并行任务都完成了
instance_id = task['instance_id']
step_id = task['step_id']
pending_tasks = await self.db.select('approval_task',
where={
'instance_id': instance_id,
'step_id': step_id,
'status': 'pending'
}
)
if not pending_tasks:
# 当前步骤完成,创建下一步任务
instance = await self.db.select_one('approval_instance',
where={'id': instance_id})
await self._create_next_step_tasks(instance_id, instance['workflow_id'], org_id)
async def reject_task(self, task_id, approver_id, decision, org_id):
"""拒绝任务"""
await self.db.update('approval_task',
data={
'status': 'rejected',
'decision': decision,
'completed_at': datetime.now()
},
where={'id': task_id, 'approver_id': approver_id, 'org_id': org_id}
)
# 更新实例状态为拒绝
task = await self.db.select_one('approval_task', where={'id': task_id})
await self.db.update('approval_instance',
data={'status': 'rejected', 'completed_at': datetime.now()},
where={'id': task['instance_id']}
)
def load_workflow_approval():
"""加载审批模块"""
env = ServerEnv()
env.workflow_core = WorkflowCore

15
workflow_approval/init.py Normal file
View File

@ -0,0 +1,15 @@
from ahserver.serverenv import ServerEnv
from appPublic.worker import awaitify
from .core import WorkflowCore
def load_workflow_approval():
"""加载跨模块审批流程模块"""
env = ServerEnv()
# 创建核心实例的工厂函数
async def create_workflow_core(org_id):
from sqlor.dbp import getDBP
db = await getDBP(org_id)
return WorkflowCore(db)
env.create_workflow_core = create_workflow_core

View File

@ -0,0 +1,66 @@
{
"widgettype": "VBox",
"options": {
"maxWidth": "100%",
"padding": "15px"
},
"subwidgets": [
{
"widgettype": "Text",
"options": {
"text": "审批详情",
"fontSize": "18px",
"fontWeight": "bold",
"marginBottom": "20px"
}
},
{
"widgettype": "Form",
"options": {
"tblname": "approval_task",
"mode": "view",
"fields": ["title", "step_name", "description", "assigned_at", "due_at"],
"fieldLabels": {
"title": "审批事项",
"step_name": "审批步骤",
"description": "详细说明",
"assigned_at": "分配时间",
"due_at": "截止时间"
}
}
},
{
"widgettype": "HBox",
"options": {
"marginTop": "30px",
"gap": "10px"
},
"subwidgets": [
{
"widgettype": "Button",
"options": {
"text": "批准",
"onClick": "approve_task",
"style": {
"backgroundColor": "#28a745",
"color": "white",
"flex": "1"
}
}
},
{
"widgettype": "Button",
"options": {
"text": "拒绝",
"onClick": "reject_task",
"style": {
"backgroundColor": "#dc3545",
"color": "white",
"flex": "1"
}
}
}
]
}
]
}

98
wwwroot/mobile_base.ui Normal file
View File

@ -0,0 +1,98 @@
{
"widgettype": "VBox",
"options": {
"maxWidth": "100%",
"padding": "10px"
},
"subwidgets": [
{
"widgettype": "HBox",
"options": {
"alignItems": "center",
"justifyContent": "space-between",
"marginBottom": "15px"
},
"subwidgets": [
{
"widgettype": "Text",
"options": {
"text": "审批中心",
"fontSize": "20px",
"fontWeight": "bold"
}
},
{
"widgettype": "Button",
"options": {
"text": "发起审批",
"onClick": "goto('workflow_approval/approval_instance/create.ui')",
"style": {
"backgroundColor": "#007bff",
"color": "white",
"border": "none",
"padding": "8px 16px",
"borderRadius": "4px"
}
}
}
]
},
{
"widgettype": "TabPanel",
"options": {
"tabs": [
{
"title": "待我审批",
"content": {
"widgettype": "DataGrid",
"options": {
"tblname": "approval_task",
"where": {
"approver_id": "${logined_userid}",
"status": "pending"
},
"fields": ["title", "step_name", "assigned_at", "due_at"],
"fieldLabels": {
"title": "审批事项",
"step_name": "步骤",
"assigned_at": "分配时间",
"due_at": "截止时间"
},
"onRowClick": "goto('workflow_approval/approval_task/detail.ui?id=${id}')"
}
}
},
{
"title": "我发起的",
"content": {
"widgettype": "DataGrid",
"options": {
"tblname": "approval_instance",
"where": {
"initiator_id": "${logined_userid}"
},
"fields": ["title", "status", "created_at", "completed_at"],
"fieldLabels": {
"title": "审批事项",
"status": "状态",
"created_at": "发起时间",
"completed_at": "完成时间"
},
"onRowClick": "goto('workflow_approval/approval_instance/detail.ui?id=${id}')"
}
}
},
{
"title": "工作流管理",
"content": {
"widgettype": "Frame",
"options": {
"src": "workflow_approval/approval_workflow/list.ui"
}
}
}
]
}
}
]
}