用友NC二次开发一些经验以及处理的问题



1. 参照开发

 

       系统参照的用法

       UIRefPane  ref = new UIRefPane();

Ref.setRefNodeName(nc.vo.bd.ref.RefNodeNameConst.DEPTDOC);

nc.ui.bd.ref.IBusiType这个类里定义了参照对应的具体类

自定义参照

自己定义的参照类一般都继承自nc.ui.bd.ref.AbstractRefModel这个抽象类

下面列举一些常用的方法:

public String[] getFieldCode()   // 返回参照字段对应的表字段编码

public String[] getFieldName()  //返回参照字段对应的显示名称

public String getPkFieldCode()  //返回主键字段编码

public String getRefTitle()         //返回参照名称

public String getTableName()  //返回查询的表名称,可以是表连接语句

public String[] getHiddenFieldCode() //返回参照的隐藏字段

public int getDefaultFieldCount()     //返回参照的默认字段数量

public String getWherePart()   //返回查询条件

如果需要实现一些特殊的参照,比如树结构的参照,则应该继承AbstractRefTreeModel类

 

2.  ClientUI类常用方法

 

protected ManageEventHandler createEventHandler() //返回UI的事件处理类

protected AbstractManageController createController() //返回UI画面的控制类

protected BusinessDelegator createBusinessDelegator()  //返回UI的业务处理类

protected void initSelfData()                                               //初始化UI界面,比如设置精度

protected void initEventListener()                 //初始化单据监听,比如:BillCardBeforeEditListener

public abstract void setDefaultData() throws Exception //设置界面默认数据

 

3.   多表的树结构(比如说,显示部门下的人员)

      NC的树结构一般都是单表,那么parentid在数据表里也是对应的主键值。那么多表的时候只需在返回数据vo的时候,       手动把父节点的数据添加进去就可以了。

      比如说:部门和人员的树结构

      在自己定义的TreeData中的getTreeVO方法中:

 


Java代码 复制代码 收藏代码
1.public SuperVO[] getTreeVO() { 
2.        PsndocVO[] result = null; 
3.        DeptdocVO[] deptdocvos = null; 
4.        try { 
5.            BusinessDelegator business = new BusinessDelegator(); 
6.            String sql = " isnull(dr,0)=0"; 
7. 
8.            result = (PsndocVO[]) business 
9.                    .queryByCondition(PsndocVO.class, sql); 
10.            deptdocvos = (DeptdocVO[]) business 
11.                        .queryByCondition(DeptdocVO.class, null); 
12.             
13.        } catch (Exception e) { 
14.            e.printStackTrace(); 
15.        } 
16.        PsndocVO[] results = new PsndocVO[result.length + deptdocvos.length ]; 
17.        for (int i = 0; i < deptdocvos.length; i++) { 
18.            PsndocVO vo = new PsndocVO(); 
19.            vo.setPk_psndoc(deptdocvos[i].getPk_deptdoc()); 
20.            vo.setPsncode(""); 
21.            vo.setPsnname(deptdocvos[i].getDeptname()); 
22.            results[i] = vo; 
23.        } 
24.        for (int i = 0; i < result.length;  i++) { 
25.            results[deptdocvos.length + i] = result[i]; 
26.        } 
27.        return results; 
28.    } 


 

 完整的TreeData代码:

 


Java代码 复制代码 收藏代码
1.public class TreeData implements IVOTreeDataByID { 
2. 
3.    public String getIDFieldName() { 
4.        return "pk_psndoc"; 
5.    } 
6.    public String getParentIDFieldName() { 
7. 
8.        return "pk_deptdoc"; 
9.    } 
10. 
11.    public String getShowFieldName() { 
12. 
13.        return "psncode,psnname"; 
14.    } 
15. 
16.    public SuperVO[] getTreeVO() { 
17.        PsndocVO[] result = null; 
18.        DeptdocVO[] deptdocvos = null; 
19.        try { 
20.            BusinessDelegator business = new BusinessDelegator(); 
21.            String sql = " isnull(dr,0)=0"; 
22. 
23.            result = (PsndocVO[]) business 
24.                    .queryByCondition(PsndocVO.class, sql); 
25.            deptdocvos = (DeptdocVO[]) business 
26.                        .queryByCondition(DeptdocVO.class, null); 
27.             
28.        } catch (Exception e) { 
29.            e.printStackTrace(); 
30.        } 
31.        PsndocVO[] results = new PsndocVO[result.length + deptdocvos.length ]; 
32.        for (int i = 0; i < deptdocvos.length; i++) { 
33.            PsndocVO vo = new PsndocVO(); 
34.            vo.setPk_psndoc(deptdocvos[i].getPk_deptdoc()); 
35.            vo.setPsncode(""); 
36.            vo.setPsnname(deptdocvos[i].getDeptname()); 
37.            results[i] = vo; 
38.        } 
39.        for (int i = 0; i < result.length;  i++) { 
40.            results[deptdocvos.length + i] = result[i]; 
41.        } 
42.        return results; 
43.    } 
44. 
45.} 


 

   如果涉及到表增加,则只需按照添加部门那样增加一个for循环即可。同时把第一个循环中的parentid改为新增的表id。    在这里parentid指的是pk_deptdoc

 

 

4. 从后台去掉自定义项引用

    NC提供自定义项的引用,也就是备用字段的使用,但是引用完了以后不能修改,如果不想使用了又不能删除。只能从后    台解除引用。

   bd_defdef 自定义项定义表,先从这个表中找到定义的自定义项记录pk_defdef

   select pk_defdef from bd_defdef where defname='';

   这里的名字即单据上显示的名称

   然后从bd_defquote引用表中去掉pk_defdef内容而pk_defused表示表中字段

   select bd_defquote.rowid,bd_defquote.* from bd_defquote where pk_defdef='';

 

  注意在解除引用后,需要将被引用字段值置空,因为重新引用自定义项时,如果字段值不为空将引用失败,原因是自定义     项引用时默认会检查字段值是否为空。

 

 

5. 显示自定义项

 

 


Java代码 复制代码 收藏代码
1.private void dealDefShow(){ 
2.        String [] strDefObjs=new String[] {"ARAP单据头"}; 
3.        String [] strPrefix=new String[] {"zyx"}; 
4.        try { 
5.            new ManageDefShowUtil(this.getBillCardPanel(), this.getBillListPanel()).showDefWhenRef(strDefObjs,strPrefix, true); 
6.        } catch (Exception e) { 
7.            Logger.error(e.getMessage(), e); 
8.        } 
9.    } 

 
 

 

6.  后台获得登录日期

 


Java代码 复制代码 收藏代码
1.String date = InvocationInfoProxy.getInstance().getDate(); 
2.UFDate loginDate = new UFDate(Long.parseLong(date)); 

 
 

7. NC主画面的头部信息位置。

 

   1. 注销、快速切换、日志、帮助按钮的代码在 nc.ui.sm.desktop.SysFuncBtnPanel

 

   2. 未读消息、代办事务、预警消息的代码在 nc.ui.sm.desktop.MsgCenterInfoPnl

 

   3. 公司+用户+日期的代码在 nc.ui.sm.desktop.DesktopTopBar

 

   4. 快捷码的代码在 nc.ui.sm.desktop.QuickCodePanel

 

   5. 配置文件在nchome\modules\uap\META-INF\clientplugins\uap.plugin

 

 

8. 参照相关的类

 

    参照事件类:nc.ui.bd.ref.RefModelHandlerForClient

    主要方法:getRefTableVO(String pk_corp)

 

    参照显示的列标题:nc.vo.bd.ref.RefcolumnVO

    获得名称方法:getFieldshowname()

 

   系统参照查询:nc.bs.bd.ref.ReftableImpl

   方法:findByNode(String refNodeName, String pk_corp)

 

 

9. 查询模板设置默认值的系统变量。

 

#Sys_Account#,

#Sys_Year#,
 #Sys_Month#,
 #Sys_Date#,
 #Sys_Operator#,
 #Sys_department#,
 #Sys_CurrCorp#

### 解决方案 #### 关于 MySQL Err 1055 (SQL Mode: only_full_group_by) 在启用 `sql_mode=only_full_group_by` 的情况下,MySQL 对 `GROUP BY` 和 `ORDER BY` 子句的要求更加严格。这意味着任何出现在 `SELECT` 列表中的非聚合列都必须包含在 `GROUP BY` 子句中[^3]。 对于 `[Err] 1055` 错误,有以下几种解决方法: ##### 方法一:调整查询逻辑 确保所有非聚合字段均被显式地列入 `GROUP BY` 子句中。例如: ```sql SELECT department_id, SUM(salary) AS total_salary FROM employees GROUP BY department_id; ``` 如果需要按多个字段分组,则应将这些字段全部加入到 `GROUP BY` 中: ```sql SELECT department_id, location, COUNT(*) AS employee_count FROM employees GROUP BY department_id, location; ``` 这种方法是最推荐的方式,因为它保持了 SQL 查询的标准性和兼容性[^3]。 ##### 方法二:禁用 `ONLY_FULL_GROUP_BY` 可以通过修改 `sql_mode` 来暂时或永久关闭 `ONLY_FULL_GROUP_BY` 设置。具体操作如下: ###### (1)临时修改会话级别的 `sql_mode` 执行以下命令以移除 `ONLY_FULL_GROUP_BY` 模式: ```sql SET SESSION sql_mode = 'STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION'; ``` ###### (2)永久修改配置文件 编辑 MySQL 配置文件(通常是 `/etc/my.cnf` 或 `/etc/mysql/my.cnf`),找到并更新 `sql_mode` 参数,去掉 `ONLY_FULL_GROUP_BY`: ```ini [mysqld] sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION ``` 保存后重启 MySQL 服务即可生效。 --- #### 关于 MySQL Err 1064 (`UPDATE` 语句语法错误) `[Err] 1064` 表明 `UPDATE` 语句存在语法问题。常见的原因包括拼写错误、关键字遗漏或不支持的操作尝试。特别是当涉及到子查询或者复杂表达式的 `UPDATE` 时,容易引发此错误。 以下是几个常见场景及其修复方法: ##### 场景一:简单 `UPDATE` 语句 基本的 `UPDATE` 语句格式如下所示: ```sql UPDATE table_name SET column1=value1, column2=value2 WHERE condition; ``` 如果省略了必要的部分(如 `WHERE` 子句),则可能导致语法错误。务必检查每一段是否完整无误。 ##### 场景二:带子查询的 `UPDATE` 有时我们需要基于另一个表的数据来更新目标记录。此时需要注意括号的位置以及正确的连接方式。例如: ```sql UPDATE target_table t JOIN source_table s ON t.id = s.target_id SET t.column_to_update = s.value_column WHERE some_condition; ``` 假如试图直接嵌套带有 `GROUP BY` 的子查询作为源数据集的一部分,则可能会因不符合预期结构而出错。因此应当重构为合适的联接形式而非单纯依靠派生表格[^6]。 ##### 示例修正案例 假设有这样一个报错例子:“Syntax error near 'group by' at line X”,可能是下面这样的非法组合造成的: ```sql UPDATE mytable m SET value_field = ( SELECT AVG(sub.val) FROM subquery_table sub GROUP BY sub.group_col -- 此处存在问题 ); ``` 应该改为先计算好中间结果再做映射赋值: ```sql WITH aggregated_data AS ( SELECT group_col, AVG(val) as avg_val FROM subquery_table GROUP BY group_col ) UPDATE mytable m INNER JOIN aggregated_data ad ON m.ref_col = ad.group_col SET m.value_field = ad.avg_val; ``` --- ### 综合示例代码 结合以上两种情况的实际应用演示如下: ```sql -- 处理 Err 1055 SELECT category, product_name, MIN(price), MAX(price) FROM products GROUP BY category, product_name; -- 修改 sql_mode 禁用 ONLY_FULL_GROUP_BY SET SESSION sql_mode='STRICT_ALL_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'; -- 解决 Err 1064 更新语句 UPDATE inventory i JOIN stock_levels sl USING(item_code) SET i.stock_status = CASE WHEN sl.current_stock >= sl.reorder_level THEN 'In Stock' ELSE 'Low Stock' END, i.last_updated = NOW(); ``` --- ### 总结 针对 `[Err] 1055` 和 `[Err] 1064`,分别提供了合理的应对措施。前者主要集中在调整查询设计或是放松约束条件方面;后者重点在于仔细审查语法规则,并采用更稳健的方式来构建复杂的 `UPDATE` 操作。无论是哪一种情形下,始终要重视测试环节以验证最终效果是否符合预期需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值