dev_III笔记补充

news2024/11/20 14:24:11

1.在客户端显示form

思路: 想要在客户端显示form必须先把form放在 menu item中,然后通过url地址的方式打开form
步骤:
1.建立form
2.建立Menu Item (特别注意:是display类型, 不是action类型 不是action类型 不是action类型
3.使用url地址:
https://hmtrain-02e9a583835dcb65aedevaos.axcloud.dynamics.com/?cmp=psgb&mi=menuItem(把menuItem换成自己的菜单项)

2.表、form 数据显示

在客户端显示form数据时,需要把“公司数据源设置为一致”,否则会出现数据不显示现象。
>

3.button绑定单击事件拿数据

[Control("Button")]
    class FormButtonControl1
    {
        /// <summary>
        ///
        /// </summary>
        public void clicked()
        {
            MultiSelectionHelper helper;
            DialogButton button;
            helper = MultiSelectionHelper::construct();
            helper.parmDatasource(FormDataUtil::getFormDataSource(ayUserTable));
                
            ayUserTable selectedRecord = helper.getFirst();
            button = Box::yesNo(strFmt("亲爱的:%1 ,您是否要支付停车费??",ayUserTable.Name),DialogButton::yes);
            if(button == DialogButton::Yes)
            {
                info("ok okok");
            }
            //info(selectedRecord.Name);
           // Box::info("main text",selectedRecord.Name,"help text");
        }
    }

4.方法总结(lookup)

需求,在从表中显示主表的信息时要求:
1.显示主表中的多个字段
2.符合条件的主表信息
以上需求均可用该方法

//
public void lookup()
{

    Query query;
    QueryBuildDataSource  queryBuildDataSource;
    QueryBuildRange range;
    SysTableLookup lookup;
    yprParkTable yprParkTable;
    query = new Query();

    lookup   = SysTableLookup::newParameters(tableNum(yprParkTable), this);
    lookup.addLookupfield(fieldNum(yprParkTable, ParkId));
    //引入数据源
    queryBuildDataSource = query.addDataSource(tableNum(yprParkTable));
    //添加条件
    range = queryBuildDataSource.addRange(fieldNum(yprParkTable,Status));
    range.value(SysQuery::value(yprStatus::Leisure));
    
    lookup.parmQuery(query);
    lookup.performFormLookup();

}

5.dev3练习题

5.1 创建一个基于RunBase类

public class yprBaseRunClassTest extends RunBase
{
   //定义变量
   DialogField dialogParkId;
   DialogField dialogFromDate;
   DialogField dialogToDate;

   yprVetParkId  yprVetParkId;
   FromDate fromDate;
   ToDate toDate;

   #DEFINE.CurrentVersion(1)
   #LOCALMACRO.CurrentList
   yprVetParkId,
   fromDate,
   toDate
   #ENDMACRO

public boolean getFromDialog()//获取用户填写信息“点击ok”后数据
{
    boolean ret;
    ret = super();
    yprVetParkId = dialogParkId.value();
    fromDate = dialogFromDate.value();
    toDate = dialogToDate.value();
    return ret;
}

 //
  public static void main(Args _args)
   {
       yprBaseRunClassTest demoRunBase;
        demoRunBase = new yprBaseRunClassTest();
       if (demoRunBase.prompt())
       {
           demoRunBase.run();
       }
   }

 
 //     //对话框描述
static client server ClassDescription description()
{
    return "Test RunBase Dialog";
}
 //
public Object dialog()//给对话框 获取数据
{
    DialogRunBase dialog;
    DialogGroup groupPeriod;

    dialog = super();
    dialogParkId =
       dialog.addFieldValue(extendedTypeStr(yprVetParkId),
       yprVetParkId);
    groupPeriod = dialog.addGroup("Period");
    dialogFromDate =
       dialog.addFieldValue(extendedTypeStr(FromDate), fromDate,
       "Period from");
    dialogToDate =
       dialog.addFieldValue(extendedTypeStr(ToDate), toDate,
       "Period to");
    return dialog;
}
 //
public container pack()
{
    return [#CurrentVersion,#CurrentList];
}

public boolean unpack(container _packedClass)
{
    Version version = RunBase::getVersion(_packedClass);

    switch (version)
    {
        case(#CurrentVersion) :
            [version,#CurrentList] = _packedClass;
        break;
    default :
        return false;
    }
    return true;
}


public void run()
{
    yprParkTrans yprParkTrans;
    select sum(ParkingPrice) from yprParkTrans
    where yprParkTrans.ParkId == yprVetParkId
    && yprParkTrans.StartDate >= fromDate
    && yprParkTrans.EndDate <= toDate;
    info(strFmt("Sum equals %1", yprParkTrans.ParkingPrice));
}
}

5.2 输入输出文件

5.2.1 输入文件
static void ImportSalesPrice(Args _args) 
{ 
 CommaIO commaIO; 
 container readCon; 
 str column1, column2, column3; 
 PriceDiscTable priceDiscTable; 
 #File 
 ;
 commaIO = new CommaIO('c:\\salesprice.csv', #io_read); 
 
 if (commaIO) 
 { 
 while (commaIO.status() == IO_Status::OK) 
 { 
 readCon = commaIO.read(); 
 column1 = conPeek(readCon, 1); 
 column2 = conPeek(readCon, 2); 
 column3 = conPeek(readCon, 3); 

 
  priceDiscTable.ItemRelation = column1; 
  priceDiscTable.FromDate = 
  str2date(column2,123); 
  priceDiscTable.Amount = str2num(column3); 
  
  pricedisctable.insert(); 
 } 
 } 
}
5.2.2 输出文件为csv格式 参考文章
static void yprJobTest(Args _args)
{
    TextBuffer              textBuffer  = new TextBuffer();
    yprManagerTable         yprManagerTable;
    FileIoPermission        perm;
    counter                 Lines;
    str fileName = "C:\\yprTestFile\\test.csv";


    //#define.ExampleFile(@"c:\\AX2009.csv")
    //#define.ExampleOpenMode("W")
;
    try
    {

        perm = new FileIoPermission(fileName, "w");
        perm.assert();


        textBuffer.appendText("Manager Id,");//必须用逗号分开
        textBuffer.appendText("Manager Name,");//必须用逗号分开
        textBuffer.appendText("Manager phone");
        textBuffer.appendText("\n");//下一行必须以回车分开

        while select yprManagerTable
        {
            textBuffer.appendText(strfmt("%1,",yprManagerTable.ManagerId));

            textBuffer.appendText(strfmt("%1,",yprManagerTable.Name));

            textBuffer.appendText(strFmt("%1,",yprManagerTable.phone));
            textBuffer.appendText("\n");
        }
        Lines = textBuffer.numLines();

        try
        {
            if (textBuffer.toFile(fileName))
                info( strfmt("存放在了%1下",fileName));
        }
        catch ( Exception::Error )
        {
            error ("Generated file error.");
        }
        CodeAccessPermission::revertAssert();
    }
    catch (Exception::Deadlock)
    {
        retry;
    }
}

6.Display方法的正确用法

6.1需求

这里是引用

6.2实现

步骤:
1.在表中的methed中定义好display方法
2.如想在form中的自定义字段中显示,则可以在其属性表中设置
在这里插入图片描述

7.临时表赋值+query赋值

7.1需求

这里是引用

7.1实现

1.创建好临时表和对应的form
2.在form中重写init();

 public void init()
        {
           ayEmployeeCopy.Age = 32;
           ayEmployeeCopy.EmployeeId = "2001";
           ayEmployeeCopy.EmployeeName = "John Mayer";
           ayEmployeeCopy.EmployerId = "1001";
           ayEmployeeCopy.Gender = ayGender::Male;
           ayEmployeeCopy.insert();
           
           ayEmployeeCopy.Age = 24;
           ayEmployeeCopy.EmployeeId = "2002";
           ayEmployeeCopy.EmployeeName = "Bruno Mars";
           ayEmployeeCopy.EmployerId = "1002";
           ayEmployeeCopy.Gender = ayGender::Male;
           ayEmployeeCopy.insert();

           info("111");
           Query query;
           QueryRun queryRun;
           QueryBuildDataSource qbds,qbds1;
           //QueryBuildRange qbr,qbr1;
           ayEmployee Employee;
           //ayEmployer employer;
           info("222");
           query = new Query();
           qbds = query.addDataSource(TableNum (ayEmployer));
           qbds1 = qbds.addDataSource(TableNum (ayEmployee));
          
           info("333");
           qbds1.addLink(fieldNum(ayEmployer, EmployerId), fieldNum(ayEmployee, EmployerId));
           //qbds1.fetchMode(QueryFetchMode::One2Many);
           qbds1.joinMode(JoinMode::InnerJoin);
           //qbds1.relations(true);
           info("444");
           qbds1.addRange(FieldNum (ayEmployee,Gender)).value(SysQuery::value(ayGender::Male));
           qbds.addRange(FieldNum (ayEmployer,Gender)).value(SysQuery::value(ayGender::Male));
           queryRun = new QueryRun(query);
           info("555");
           while(queryRun.next())
           {
               info("6666");
               employee = queryRun.get(tableNum(ayEmployee));
           
               ayEmployeeCopy.EmployeeId = employee.EmployeeId;
               ayEmployeeCopy.EmployerId = employee.EmployerId;
               ayEmployeeCopy.EmployeeName = employee.EmployeeName;
               ayEmployeeCopy.Age = employee.Age;
               ayEmployeeCopy.Gender = employee.Gender;
               ayEmployeeCopy.insert(); 
            }
        }

8.使用FormRun和MenuAction方式打开form

8.1需求

这里是引用

8.2FormRun实现

1.创建Button
2.绑定单击事件

public void clicked()
        {
            FormRun fr;
            Args    args;
            args = new Args();
            args.name(formStr(ayEmployerInfo));
            //form为"将要跳转的form"
            args.caller(this);
            fr = classfactory.formRunClass(args);
            fr.run();
            fr.wait(true);
        }

8.2MenuAction实现

1.创建Button
2.绑定单击事件

public void clicked()
        {
            Args args;
            args = new Args();
            //args.record(zcEmployee::find(zcEmployee.EmployeeId));
            new MenuFunction(menuItemDisplayStr(ayEmployerMenuItem),MenuItemType::Display).run(args);
            //ayEmployerMenuItem为将要跳转的MenuItem
        }

9.表单中点击button更新选中的记录

9.1需求

这里是引用

9.2实现

1.创建一个Button
2.绑定单击事件

 public void clicked()
        {
            Dialog dialog;
            DialogGroup dialoggroup;
            DialogField dialogField;
            ayEmployee ayEmployeeloc;//定义一个ayEmployee变量
            dialog = new Dialog("Update Age");
            dialoggroup =  dialog.addGroup("Age");
            //addFieldValue方法的赋值参数格式
            dialogField = dialog.addFieldValue(extendedTypeStr(ayVetAge),int2Str(ayEmployee.Age));
            if(dialog.run())
            {
                str id = ayEmployee.EmployeeId;//ayEmployee代表当前选中的值
                ttsbegin;
                select forupdate ayEmployeeloc
                    where ayEmployeeloc.EmployeeId == id;

                ayEmployeeloc.Age = dialogField.value();
                ayEmployeeloc.update();
                ttscommit;
            }
            ayEmployee_ds.research(true);//修改完后,需要ayEmployee_ds.research(true)更新数据(从表——form——客户端),否则会出现"修改完后,只留下一行数据"
            //true表示,当更新完光标会停在原来点击的位置

        }

10.1需求:

10.Form的关联

10.1需求:

在这里插入图片描述

10.2 实现

1.在表上把关联关系搭建好
2.在design中创建一个Menu Item Button
3.在该button中设置为关联的Menu Item

11.报表

有两种方式为报表提供数据源,一种是query,另一种是query+DP形式

11.1 纯query

步骤:
1.建SSRS Report
2.添加DataSets(引入Aot query)和Design
3.建立Out put类型的Menu Item,设置其Object Type,Object、report
4.将该Menu Item添加到Menu中
5.新建Controller类时期继承基类: SrsReportRunController(报表入口)

class ayReportTestController extends SrsReportRunController
{
    // menuitem入口
    public client static void main(Args _args)
    {
        ayReportTestController controller = new ayReportTestController();
        controller.parmArgs(_args);
        controller.parmReportName(ssrsReportStr(ayTestReport2, Report));
        //设置report和Design
        controller.parmShowDialog(true);
        controller.parmDialogCaption('Test Employee RDP report');
        controller.startOperation();//调用DP类,纯query此步骤可以省略
    }

}

6.build项目,然后部署Report:右键>report>Deploy Report

11.2 query+DP

步骤:
1.建SSRS Report
2.添加DataSets和Design
3.建立Out put类型的Menu Item,设置其Object Type,Object、report
4.将该Menu Item添加到Menu中
5.新建Controller类时期继承基类:
6.新建DP类(该类像report中提供数据源)

[SRSReportQueryAttribute(queryStr(zcRDPEmployeeQuery)),SRSReportParameterAttribute(classStr(zcRDPEmployeeContract))]
public class zcRDPEmployeeRDP extends SRSReportDataProviderBase
{
    zcRDPEmployeeTmp employeeTmp;
    zcRDPEmployeeContract contract;
    BarcodeCode128      barcode;

    [SRSReportDataSetAttribute(tablestr(zcRDPEmployeeTmp))]
    public zcRDPEmployeeTmp getEmployeeTmp()
    {
        select employeeTmp;
        return employeeTmp;
    }

    /// <summary>
    /// 报表执行入口
    /// </summary>
    public void processReport()
    {
        Query   query = this.parmQuery();

        this.initEmployeeTable(query);

        super();
    }

    private void initEmployeeTable(Query _query)
    {
        contract = this.parmDataContract() as zcRDPEmployeeContract;

        //此处写临时表的insert逻辑
        QueryBuildDataSource qbds = _query.addDataSource(TableNum (zcEmployer));
        QueryBuildDataSource qbds1 = qbds.addDataSource(TableNum (zcEmployee));

        qbds1.addLink(fieldNum(zcEmployer, EmployerId), fieldNum(zcEmployee, EmployerId));
        qbds1.fetchMode(QueryFetchMode::One2Many);
        qbds1.joinMode(JoinMode::InnerJoin);        
        qbds1.addRange(fieldNum(zcEmployee, EmployeeId)).value(SysQuery::value(contract.parmAccountNum()));      
        QueryRun qr = new QueryRun(_query);

        while (qr.next())
        {
            zcEmployee employeeLoc = qr.get(tablenum(zcEmployee));
            employeeTmp.EmployeeId = employeeLoc.EmployeeId;
            employeeTmp.EmployeeName = employeeLoc.EmployeeName;
            employeeTmp.EmployerId = employeeLoc.EmployerId;
            /*
            Query query = new Query();
            QueryBuildDataSource qbds = query.addDataSource(TableNum (zcEmployer));
            qbds.addRange(fieldNum(zcEmployer, EmployerId)).value(SysQuery::value(employeeLoc.EmployerId));
            QueryRun q = new QueryRun(query);
            while (q.next())
            {
                 zcEmployer employerLoc = q.get(tableNum(zcEmployer));
                 employeeTmp.EmployerName = employerLoc.EmployerName;
            }            
            */ 

            zcEmployer employerLoc = qr.get(tableNum(zcEmployer));
            employeeTmp.EmployerName = employerLoc.EmployerName;

            //打印条形码
            barcode = Barcode::construct(BarcodeType::Code128);
            barcode.string(true, employeeTmp.EmployerId);
            employeeTmp.EmployerId = barcode.barcodeStr();
            employeeTmp.insert();
            
        }
    }

}

7.新建Contract类(该类在DP查询时添加限定条件)

[DataContractAttribute]
public class zcRDPEmployeeContract
{
    zcEmployeeId employeeId;

    [DataMemberAttribute('zcEmployeeId')]
    public zcEmployeeId parmAccountNum(zcEmployeeId _employeeId = employeeId)
    {
        employeeId = _employeeId;
        return employeeId;
    }
}

8.新建Build类(如果要给限定的字段做其他功能:eg:lookup等,可以使用该类)
切记如果添加Build方法,需要为Contract类上添加引用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

12.设置虚拟机多人使用

run gpedit.msc > Computer configuration > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop session host > Connections
Limit number of connections : Disable
Restrict Remote Desktop Services users to a single
Remote Desktop Services session : Disable
run gpupdate -force

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/76905.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【分布式技术专题】「架构设计方案」盘点和总结秒杀服务的功能设计及注意事项技术体系

秒杀应该考虑哪些问题 超卖问题 分析秒杀的业务场景&#xff0c;最重要的有一点就是超卖问题&#xff0c;假如备货只有100个&#xff0c;但是最终超卖了200&#xff0c;一般来讲秒杀系统的价格都比较低&#xff0c;如果超卖将严重影响公司的财产利益&#xff0c;因此首当其冲…

python爱心源代码集锦

python爱心源代码集锦 本文目录&#xff1a; 一、代码效果预览索引图 二、爱心源代码集锦 &#xff08;1&#xff09;、爱心图形1&#xff08;弧线型&#xff09;&#xff08;显示的文字写在代码里&#xff09; &#xff08;2&#xff09;、爱心图形2&#xff08;直线型&am…

MySQL 如何优化慢查询?

一、前言 在日常开发中&#xff0c;我们往往会给表加各种索引&#xff0c;来提高 MySQL 的检索效率。 但我们有时会遇到明明给字段加了索引&#xff0c;并没有走索引的Case。 进而导致 MySQL 产生慢查询。 严重场景下&#xff0c;甚至出现主从延迟、数据库拖垮的极端事故。 本…

微服务框架 SpringCloud微服务架构 28 数据同步 28.4 发送mq 消息

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构28 数据同步28.4 发送mq 消息28.4.1 直接开干28 数据同步 28.4 发送mq 消…

《Linux运维实战:使用Percona Backup for MongoDB逻辑备份与恢复Mongodb数据》

一、备份与恢复方案 Percona Backup for MongoDB 是一个开源、分布式和低影响的解决方案&#xff0c;用于MongoDB分片集群和副本集的一致备份。从版本1.7.0开始&#xff0c;Percona Backup for MongoDB支持物理和逻辑备份和恢复&#xff0c;仅支持对逻辑备份进行时间点恢复。 …

UIAutomator测试框架介绍

uiautomator简介 UiAutomator是Google提供的用来做安卓自动化测试的一个Java库&#xff0c;基于Accessibility服务。功能很强&#xff0c;可以对第三方App进行测试&#xff0c;获取屏幕上任意一个APP的任意一个控件属性&#xff0c;并对其进行任意操作&#xff0c;但有两个缺点…

软件测试面试笔试习题参考,你都会了吗?

目录 一、 简答题和应用题&#xff1a; 二、 填空题&#xff1a; 三、 判断题&#xff1a; 四、 选择题&#xff1a; 总结 重点&#xff1a;配套学习资料和视频教学 一、 简答题和应用题&#xff1a; 1. 什么是软件测试&#xff1f; 2. 比较软件测试过程和软件开发过程&a…

基于JavaScript中AES和MD5加密,以及简单二维码的生成

一、加密技术 1、对称加密&#xff1a;单密钥加密。一个密钥可以用来加密也可以用来解密 —- AES 2、非对称加密&#xff1a;有两把密码&#xff0c;公钥(用于加密)&#xff0c;私钥(用于解密) 3、摘要算法&#xff1a;把任意长度的输入&#xff0c;根据算法生成一串固定长度…

有环链表入口问题

有环链表入口问题 当快慢指针相遇时&#xff0c;我们可以判断到链表中有环&#xff0c;这时重新设定一个新指针指向链表的起点&#xff0c;且步长与慢指针一样为1&#xff0c;则慢指针与“新”指针相遇的地方就是环的入口。 图片来源:黑马程序员 证明: 设a为起点位置&#xff…

百变郁锦香,开创新典范,深化全球战略布局成就国际高端酒店品质之选

随着消费需求的不断升级&#xff0c;酒店消费场景也进行着多元化的发展&#xff0c;城市高端度假品牌正积极溯源消费需求&#xff0c;寻得品牌文化延伸的可靠路径。同时&#xff0c;各大酒店品牌也加快在市场布局的脚步&#xff0c;希望通过布局城市核心区域获得可持续发展的更…

Python绘制正二十面体

文章目录正二十面体的顶点绘制棱绘制面正二十面体的顶点 正20面体的12个顶点刚好可以分为三组&#xff0c;每一组都是一个符合黄金分割比例的长方形&#xff0c;而且这三个长方形是互相正交的。 所以&#xff0c;想绘制一个正二十面体是比较容易的 import numpy as np from …

大环配体配合物1407166-70-4,NODA-GA-NHS ester,NODA-GA-NHS 酯

●外观以及性质&#xff1a; NODA-GA-NHS ester产物呈固体或粘性液体&#xff0c;取决于PEG分子量&#xff0c;一般为白色固体&#xff0c;双功能大环化合物&#xff0c;大环配体配合物是指由多齿配体与环骨架上的O、N、P、S等多个配位原子形成的环配合物。 NODA-GA-NHS ester …

前端面试题2022-CSS篇

关于前端面试的题&#xff0c;最近整理了一些干货&#xff0c;经常被问到的一些问题&#xff0c;出现频率比较高的问题&#xff0c;如有不足之处&#xff0c;请高调指出&#xff0c;&#xff08;⭐代表难度&#xff0c;星星越多越难&#xff0c;以次类推&#xff09;&#xff0…

如何自动备份指定文件扩展名的文件?

关于文件扩展名 文件扩展名&#xff0c;一个点后跟几个字母&#xff0c;例如“.doc”或“.jpg”&#xff0c;构成计算机文档名称的结尾。保存文档时&#xff0c;请务必在单击“保存”之前输入文档名称和文件扩展名。 自动备份具有特定文件扩展名的文件 随着计算机的使用&…

第十章 鲁棒性检查(中)

文章目录10.5 时钟门控检查(Clock Gating Checks)高电平时钟门控(Active-High Clock Gating)10.5 时钟门控检查(Clock Gating Checks) 当一个门控信号&#xff08;gating signal&#xff09;可以控制逻辑单元中时钟信号&#xff08;clock signal&#xff09;的路径时&#xff…

最近面试遇到的面试题

先挖坑&#xff0c;有空再填坑&#xff01; 迭代器 生成器 常用高阶函数 MySQL 建索引几大原则 浅拷贝 深拷贝 区别 实现 Linux 进程名字 查看进程号 Linux 杀死一个进程 python Linux shell 脚本 数据库 主从复制 配置 nginx 权限设置 python 去除空行 pandas 保留最后一个空…

深入浅出 Swift 中的 some、any 关键字以及主关联类型(primary associated types)

问题现象 从 Swift 5.1 开始,Apple 陆续引入 some、any 关键字,并且从 Swift 5.7 开始对 any 关键字的用法做了增强,并且引入了主关联类型(primary associated types)的概念。 那么它们到底是什么意思?使用它们又能如何改进我们书写代码的范儿呢? 在本篇博文中,您将学…

自动依据你的数据库生成SQL练习题及答案,宝藏软件鉴赏

原创软件不易&#xff0c;方面多点赞、收藏、加关注鼓励&#xff01;后续领更多好用功能&#xff01; 引言 各位好&#xff0c;相信看见这篇文章的朋友&#xff0c;应该也去体验过了chatGPT了吧~&#xff0c;确实chatGPT拉近了我们与未来科技的距离&#xff0c;所有别人火也是…

电脑技巧:Microsoft Edge浏览器技巧介绍

目录 1、导入浏览器数据 2、Edge边栏 3、实用的扩展功能 4、创建集锦列表 4.1 集锦的作用 4.2 使用方法 5、查找优惠券 6、Edge效率省电模式 Microsoft Edge是Windows10操作系统预装的一款非常棒的浏览器和之前的IE不同&#xff0c;采用了谷歌浏览器内核&#xff0c;相…

项目的成功标准如何衡量?【一杯咖啡谈项目】

每个项目经理都想自己的项目能够成功&#xff0c;但是&#xff0c;什么才叫项目的成功&#xff0c;成功的定义是什么&#xff1f;项目成功标准是什么呢&#xff1f; 很多看似失败的项目其实是成功的&#xff0c;很多看似成功的项目其实是失败的。研究项目成功的标准&#xff0…