钉钉开发之java制作审批表单模板
一、目的:学习钉钉API开发,考虑制作一个出差申请表单模板
二、代码:
1、新建获取token的类Mytoken
package sfccl.api; import com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenResponse; import com.aliyun.tea.TeaException; public class Mytoken { // public static String accessToken; String AppKey = "ding************5"; String AppSecret = "ZM1i*************p"; String accessToken = ""; public static com.aliyun.dingtalkoauth2_1_0.Client createClient() throws Exception { com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config(); config.protocol = "https"; config.regionId = "central"; return new com.aliyun.dingtalkoauth2_1_0.Client(config); } public String accessToken() throws Exception { //java.util.List<String> args = java.util.Arrays.asList(args_); com.aliyun.dingtalkoauth2_1_0.Client client = Mytoken.createClient(); com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest getAccessTokenRequest = new com.aliyun.dingtalkoauth2_1_0.models.GetAccessTokenRequest() .setAppKey(AppKey) .setAppSecret(AppSecret); try { GetAccessTokenResponse tokenResponse = client.getAccessToken(getAccessTokenRequest); // System.out.println(tokenResponse.body); // System.out.println(tokenResponse.getHeaders()); // System.out.println(tokenResponse.getBody()); System.out.println(tokenResponse.getBody().accessToken); System.out.println(tokenResponse.getBody().expireIn); accessToken = tokenResponse.getBody().accessToken; } catch (TeaException err) { if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助开发定位问题 System.out.println("TeaException:"+err.message); } } catch (Exception _err) { TeaException err = new TeaException(_err.getMessage(), _err); if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助开发定位问题 System.out.println("TeaException:" + err.message); } } return accessToken; } }
2、新建类Chuchai_Schema1
package sfccl.api; import com.aliyun.dingtalkworkflow_1_0.models.*; import com.aliyun.tea.TeaException; import com.aliyun.teaopenapi.models.Config; import com.aliyun.teautil.models.RuntimeOptions; public class Chuchai_Schema1 { /** * 使用 Token 初始化账号Client * @return Client * @throws Exception */ public static com.aliyun.dingtalkworkflow_1_0.Client createClient() throws Exception { Config config = new Config(); config.protocol = "https"; config.regionId = "central"; return new com.aliyun.dingtalkworkflow_1_0.Client(config); } public static void main(String[] args_) throws Exception { java.util.List<String> args = java.util.Arrays.asList(args_); Mytoken mytoken = new Mytoken(); String token = mytoken.accessToken(); com.aliyun.dingtalkworkflow_1_0.Client client = Chuchai_Schema1.createClient(); FormCreateHeaders formCreateHeaders = new FormCreateHeaders(); formCreateHeaders.xAcsDingtalkAccessToken = token; // 1. 明细控件 // 1.1. 明细中子控件 单行输入控件 FormComponentProps childFormComponentProps1 = new FormComponentProps() .setComponentId("TextField-child-1") .setPlaceholder("请输入") .setLabel("出差地点") .setRequired(true); FormComponent childFormComponent1 = new FormComponent() .setComponentType("TextField") .setProps(childFormComponentProps1); // 1.2. 明细中子控件 图片控件 FormComponentProps childFormComponentProps2 = new FormComponentProps() .setComponentId("DDPhotoField-abcd") .setLabel("图片"); FormComponent childFormComponent2 = new FormComponent() .setComponentType("DDPhotoField") .setProps(childFormComponentProps2); // 1.3. 明细中子控件 数字输入控件 FormComponentProps childFormComponentProps3 = new FormComponentProps() .setComponentId("NumberField-child-1") .setPlaceholder("请输入") .setLabel("出差次数") // .setUnit("元") .setRequired(true); FormComponent childFormComponent3 = new FormComponent() .setComponentType("NumberField") .setProps(childFormComponentProps3); // 1.3.1 明细中汇总子控件数字统计 FormComponentProps.FormComponentPropsStatField statField1 = new FormComponentProps.FormComponentPropsStatField(); statField1.setComponentId("NumberField-child-1"); statField1.setLabel("出差次数"); FormComponentProps formComponentProps1 = new FormComponentProps() .setComponentId("TableField-abcd") .setUpper("0") .setTableViewMode("table") .setLabel("出差明细") .setStatField(java.util.Arrays.asList(statField1)); FormComponent formComponent1 = new FormComponent() .setComponentType("TableField") .setProps(formComponentProps1) .setChildren(java.util.Arrays.asList(childFormComponent1,childFormComponent2,childFormComponent3)); // 2. 单行输入控件 FormComponentProps formComponentProps2 = new FormComponentProps() .setComponentId("TextField-abcd") .setPlaceholder("请输入") .setLabel("出差人姓名") .setRequired(true); FormComponent formComponent2 = new FormComponent() .setComponentType("TextField") .setProps(formComponentProps2); // 3. 时间区间控件 FormComponentProps formComponentProps3 = new FormComponentProps() .setComponentId("DDDateRangeField-abcd") .setPlaceholder("请选择") .setLabel("[\"开始时间\",\"结束时间\"]") .setUnit("小时") .setFormat("yyyy-MM-dd HH:mm") .setRequired(true); FormComponent formComponent3 = new FormComponent() .setComponentType("DDDateRangeField") .setProps(formComponentProps3); // 4. 数字输入控件 FormComponentProps formComponentProps4 = new FormComponentProps() .setComponentId("NumberField-abcd") .setPlaceholder("请输入") .setLabel("出差人数") .setUnit("人") .setRequired(true); FormComponent formComponent4 = new FormComponent() .setComponentType("NumberField") .setProps(formComponentProps4); // 5. 金额控件 FormComponentProps formComponentProps5 = new FormComponentProps() .setComponentId("MoneyField-abcd") .setUpper("0") .setPlaceholder("请输入金额") .setLabel("差旅费(元)"); FormComponent formComponent5 = new FormComponent() .setComponentType("MoneyField") .setProps(formComponentProps5); // 6. 单选控件 SelectOption option1 = new SelectOption(); option1.setKey("option1"); option1.setValue("A"); SelectOption option2 = new SelectOption(); option2.setKey("option2"); option2.setValue("B"); SelectOption option3 = new SelectOption(); option3.setKey("option3"); option3.setValue("C"); FormComponentProps formComponentProps6 = new FormComponentProps() .setComponentId("DDSelectField-abcd") .setPlaceholder("请选择") .setLabel("出差同伴") .setBizAlias("staff_type") .setOptions(java.util.Arrays.asList(option1, option2, option3)) .setRequired(true); FormComponent formComponent6 = new FormComponent() .setComponentType("DDSelectField") .setProps(formComponentProps6); // 7. 单行输入控件(交通工具) FormComponentProps formComponentProps7 = new FormComponentProps() .setComponentId("TextField-abce") .setPlaceholder("请输入") .setLabel("交通工具") .setRequired(true); FormComponent formComponent7 = new FormComponent() .setComponentType("TextField") .setProps(formComponentProps7); // 8. 多行输入控件 FormComponentProps formComponentProps8 = new FormComponentProps() .setComponentId("TextareaField-abcd") .setPlaceholder("请输入") .setLabel("出差事由") .setRequired(true); FormComponent formComponent8 = new FormComponent() .setComponentType("TextareaField") .setProps(formComponentProps8); FormCreateRequest formCreateRequest = new FormCreateRequest() .setName("出差报销审批_测试1") .setDescription("用于员工差旅费用报销使用_模板1") .setFormComponents(java.util.Arrays.asList( formComponent1, formComponent2, formComponent3, formComponent4, formComponent5, formComponent6, formComponent7, formComponent8 )); try { client.formCreateWithOptions(formCreateRequest, formCreateHeaders, new RuntimeOptions()); } catch (TeaException err) { if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助开发定位问题 System.out.println(err.message); } } catch (Exception _err) { TeaException err = new TeaException(_err.getMessage(), _err); if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) { // err 中含有 code 和 message 属性,可帮助开发定位问题 System.out.println(err.message); } } } }
三、结果
仅出现“Process finished with exit code 0”提示,则程序运行成功。若出现400等结果提示,则需要查找原因,很可能时某个控件的参数错误导致(程序暂时无法直接提示是哪个控件出问题,可在公共错误码 (aliyun.com)查看代码提示)。
点击钉钉app——“更多”——“管理后台”在弹出的页面中,点击快捷入口的“OA审批”进入“表单管理”界面的“其他”栏目中,即可看到新增了“出差报销审批_测试1”应用。点击该应用下的编辑按钮,进入表单设计页面,可看到表单如下: