常见问题

怎样在先胜云平台写一个可运行的Python

当您在先胜云平台中点击运行某个Python时,系统会经历以下步骤

  1. 导入该Python文件

  2. 查找文件中的main函数

  3. 解析main函数的签名

    1. main函数只接收一个参数:传入业务参数

    2. main函数接受两个参数:顺次传入系统参数,业务参数

    3. 其他情况,报错

  4. Python加入任务队列等待运行(一般会立即运行)

  5. 收集main函数返回值、运行期间的标准输出和标准错误

基于以上说明,您可以

1. 定义接收 两个 入参的 main 函数

def main(p1, p2):
    # Your code goes here
    return

2. 定义接收 一个 入参的 main 函数

def main(para):
    # Your code goes here
    return

重要

此处的 para 等价于 第1种写法p2

系统参数 p1 如何获取

在先胜云平台中新建python脚本,输入以下内容:

def main(p1, p2):
    print(p1)

保存后点击运行,控制台输出内容即系统参数 p1

_images/get_para1.png

业务参数 p2 如何获取

在先胜云平台中新建python脚本,输入以下内容保存:

def main(p1, p2):
    print(p2)

在您想要绑定Python的地方(例如自定义按钮)绑定上述脚本,并且触发Python脚本(例如点击自定义按钮)。

通过 作业管理 查看当前任务的运行状态,作业管理空间管理 界面中可以看到:

_images/search_python_log.png

作业日志 里会记录入参和运行过程的输出。

_images/python_log_detail1.png

下载日志后的附件内容如下:

_images/python_log_detail2.png

重要

作业日志中复制出来的 p2 是字符串格式,且可能经过了java加密压缩

如遇到不是json格式的p2,需要用deepfos.lib.sysutils 中的 ParamZipHelper 来解压

_images/python_p2_java_serialized.png
# json格式的p2

import json

p2 = json.loads(p2)

# java加密的p2

from deepfos.lib.sysutils import ParamZipHelper

p = ParamZipHelper(ori_str=p2, encoding='utf-8')

p2 = p.decompress_json()

业务参数 p2 的数据结构

业务模型

业务模型可以在保存前后置和删除前后置逻辑中配置Python,两者的参数格式有所不同。

保存前后置(业务模型V1.0)

业务模型V1.0保存前后置调用Python传参格式如下:

{
    "type": "SAVE", #: 操作类型
    "operateType": "1", #: 页面操作类型
    #: 保存参数
    "saveParam": {
        "formInfoJson": {...},  #: 全量json
        #: 更新数据json
        "modifyJson": [
            {...},
            ...
        ]
    }
}

其中需要关注的主要是 saveParam 里的 formInfoJsonmodifyJson

  • formInfoJson 是业务明细表整张表单的全量数据

  • modifyJson 是本次保存用户改动过的数据。

保存前后置(业务模型V1.1+)

传入的是全量的树结构JSON,详细待补充。。

删除前后置

传入的为模型业务主键的键值对。

审批流

审批流前后置调用Python的入参格式如下:

{
  "currentStatus": "a",
  "operationTime": "2021-08-14 11:02:13",
  "operationUser": "759a55fd-094a-464c-b021-39b393b5b01a",
  "pcRemark": "",
  "primaryKeyValue": {
    "partition_id": "SUBEDGLD8JAK0J",
    "sys_sub_id": "1",
    "sys_object_id": "94_1"
  },
  "targetStatus": "b"
}

其中需要关注的有 currentStatus, targetStatus, primaryKeyValue

currentStatustargetStatus 分别是此次审批操作的当前和目标状态,用于Python判断操作的节点。

primaryKeyValue 是业务主键的键值对。特别要注意如果审批流是绑定在业务模型的子模型上的,则 primaryKeyValue 是子模型的业务主键键值对,partition_id 是子模型id。

返回结果如何影响前端展示(弹窗效果)

目前支持根据python返回值展示弹窗效果的组件有:

  • 业务模型

  • 审批流

要求的返回格式如下:

{
"success": False,
"errors": [
    {
        #: 描述1
        "description": ""
    },
    {
        #: 描述2
        "description": ""
    }
],
"warnings": [
     {
        #: 描述
        "description": ""
    }
]
}

success 用于标识本次Python执行是否成功,如果为 False 可能会中止原逻辑,并且 errors/warningsdescription 字段的描述信息会出现在右上角的弹框中, errors 为红色,warnings 为橙色。

示例

在业务模型保存前置中配置Python,如果调用该Python返回值 success == False,将打断保存操作。

如何让本地代码和线上代码一致

在项目主入口的同级目录下新建 _debug.py 文件,输入以下内容:

from deepfos.options import OPTION

# -----------------------------------------------------------------------------
# 从系统中获取以下参数
#: 环境参数
para1 = {'app': 'zzaoxv008', 'space': 'zzaoxv', 'user': '1fff29c5-abdc-4929-ab6c-8a6ca9479091', 'language': 'zh-cn', 'token': 'Bearer 358E9662AE86B3DCCA2973B0EA067C4BC832F4C00B95828F026A0121AEF50675', 'cookie': '', 'Content-Type': 'application/json;charset=UTF8'}

#: 业务参数
para2 = {'currentStatus': 'Status587e', 'operationTime': '2021-07-27 14:48:53', 'operationUser': '1fff29c5-abdc-4929-ab6c-8a6ca9479091', 'pcRemark': '', 'primaryKeyValue': {'partition_id': 'SUBEEB6VDKAO0I', 'sub_id': '1', 'sys_store_id': 'fran_store0003'}, 'targetStatus': 'Statusa600'}

#: 环境域名,根据自己的使用环境更改
host = "https://alpha.deepfos.com"


# -----------------------------------------------------------------------------
# 下面的代码是固定的

OPTION.general.use_eureka = False
OPTION.server.base = f"{host}/seepln-server"
OPTION.server.app = f"{host}/seepln-server/app-server"
OPTION.server.system = f"{host}/seepln-server/system-server"
OPTION.server.space = f"{host}/seepln-server/space-server"
OPTION.server.platform_file = f"{host}/seepln-server/platform-file-server"
OPTION.api.header = para1
OPTION.api.dump_on_failure = True

本地调试时,推荐的代码模板如下:

try:
    from _debug import para1, para2
except ImportError:
    para1 = para2 = {}


def main(p1, p2):
    # 在这里写主代码
    # Your code goes here
    return


if __name__ == '__main__':
    main(para1, para2)

重要

开头的 try import 部分必须放在所有其他 import 之前, 以保证 _debug.py 文件中的配置能够生效。