软件vTigerCRM是以Apache为Web服务器,MySQL为数据库,因此选择XAMPP作为其运行环境,在Linux上采用LAMPP,在Windows系统上采用WAMPP。本次研究环境选择WAMPP。
操作系统:Windows 7
Web环境:WAMPP 1.7.7
1)MySQL版本:5.5.16
2)PHP版本:5.3.8
3)Apache版本:2.2.21
4)phpMyAdmin: 3.4.5
5)FileZilla FTP Server: 0.9.39
6)Tomcat: 7.0.21 (with mod_proxy_ajp as connector)
研究对象:vTigerCRM 5.3.0
开发工具:NetBeans 7.0.1
本研究报告的运行环境包括WAMPP 1.7.7和vTigerCRM 5.3.0,下载地址如下:
WAMPP:http://www.apachefriends.org/en/xampp.html(下载WAMPP)
vTigerCRM:http://wiki.vtiger.com/index.php/Vtiger530:Downloads
NetBeans:http://netbeans.org/
在本次研究中,XAMPP的安装路径为F:\XAMPP1.7.7
说明:本次研究侧重软件本身,操作系统和软件自身可能存在的安全性不在研究范围内,考虑到研究的方便性,采用Windows 7操作系统。
WAMPP安装步骤如下:
1) 下载WAMPP 1.7.7,地址:http://www.apachefriends.org/download.php?xampp-win32-1.7.7-VC9-installer.exe
2) 下载完成后,执行该程序;
3) 设置安装路径,例如“F:\XAMPP1.7.7”。安装最后,提示选择“Put XAMPP to desktop”,即把XAMPP控制台放到桌面。
4) 运行XAMPP控制台,启动Apache和MySQL,可注册为系统服务自动启动。
5) 在浏览器访问:http://localhost/xampp,如果正常,则安装成功。
6) 使用root登录进入phpmyadmi,设置root密码;
7) 编辑安装路径F:\xampp1.7.7\phpMyAdmin\config.inc.php,将$cfg['Servers'][$i]['auth_type'] = 'config';修改为$cfg['Servers'][$i]['auth_type'] = 'cookie';
8) 编辑F:\xampp1.7.7\mysql\bin\my.ini,在[client]下添加“default_character_set = utf8”,在[mysqld]下添加“character_set_server=utf8”和“collation_server=utf8_unicode_ci”,重新启动mysql;
vTigerCRM5.3.0安装步骤如下:
下载vTigerCRM 5.3.0,地址:http://www.vtiger.com/vtiger-crm/downloads/,选择“SOURCE”下载项。
将下载包解压缩到F:\xampp1.7.7\htdocs\vtigercrm530,参考如下链接进行安装:http://service.syncomni.com:10080/twiki/bin/view/Syncomni/VTigerCRMSetup
安装需要5-10分钟。
安装完成后,下载中文语言包,下载地址为:http://service.syncomni.com:10080/twiki/pub/Syncomni/VTigerCRMSetup/vTiger_CRM_zh_cn_5.2_Release_20101001.zip,然后解压缩到f:\xampp1.7.7\htdocs\vtigercrm530目录下。
打开mysql命令行,执行:
INSERT INTO `vtiger_language` VALUES ('9', '简体中文', 'zh_cn', '简体中文', '2012-01-12', NULL , '1', '1');
并将第1条记录的is_default设置为0。
使用admin登录到http://localhost/vtigercrm530/index.php
在My Preferences(右上角)中设置Language为“简体中文”,刷新页面即可显示中文。
打开F:\XAMPP1.7.7\htdocs\vtigercrm530\config.inc.php,将$default_language = 'en_us'修改为$default_language = 'zh_cn',即把中文设置为默认语言。
安装到此完成。
从5.3.0版本之前,登录界面提供语言选择,在5.3.0版本中,默认语言的设置转到了config.inc.php中,用户登录后可以在“我的信息”->“更多信息”->“语言”中修改喜欢的语言。
登录界面定义文件:Login.tpl
http://wiki.vtiger.com/index.php/Creating_New_Module
http://forums.vtiger.com/viewtopic.php?t=26465
菜单分为主菜单和子菜单,在vTiger中主菜单称为parent tab,子菜单称为child tab。
与主菜单相关的文件有parent_tabdata.php,该文件定义了主菜单全局变量$parent_tab_info_array,以及和其相关的子菜单(模块)编码数组$parent_child_tab_rel_array。
相关的数据库表有vtiger_parenttab和vtiger_parenttabrel。
和菜单相关的源代码文件:include/utils/CommonUtils.php
如果一个主菜单下的任何模块,不允许当前用户访问,则登录后该主菜单不会显示。
建议增加一个独立菜单编辑器工具,用于管理主菜单和子菜单。该工具只给特定的软件开发人员使用。
文件名 |
变量 |
用途 |
tabdata.php |
$tab_info_array |
定义模块编码 |
$tab_seq_array |
|
|
$tab_ownedby_array |
|
|
$action_id_array |
|
|
$action_name_array |
|
|
parent_tabdata.php |
$parent_tab_info_array |
定义主菜单 |
$parent_child_tab_rel_array |
定义主菜单中包含的子菜单(模块)编码,参见$tab_info_array |
|
|
|
|
文件:CommonUtils.php
函数:checkParentTabExists($parenttab)
要点:如果文件parent_tabdata.php存在,则使用全局变量$parent_tab_info_array,否则,使用数据库表vtiger_parenttab。
函数:getParentTabFromModule($module)
要点:如果文件tabdata.php和parent_tabdata.php存在,则根据文件中定义的全局变量计算;否则根据数据库表vtiger_parenttab、vtiger_tab和vtiger_parenttabrel计算。
函数:getHeaderArray()
要点:需要包含parent_tabdata.php,否则访问页面时会有warning,提示没有该文件,主菜单也无法显示。
总结:
通过对vTigerCRM 5.3.0的研究,菜单相关的数据既保存到文件,也保存到数据库,目前尚不清楚为什么分两处存放。在已有的函数或方法中,既有同时支持文件和数据库存储的方式,也有只支持文件,或者只支持数据库的方式。因此,如果对主菜单进行操作,既要修改文件,也要修改相关数据库。详细的研究过程参加章节“附录1:实验->2. 增加新主菜单”。
建议:
将主菜单数据统一存储到数据库。
添加语言配置:简体中文
执行如下SQL添加中文币种,并在“设置>货币”中添加RMB。
INSERT INTO vtiger_currencies( `currency_name`, `currency_code`,`currency_symbol` ) VALUES ( '人民币元', 'RMB', '¥' ); |
另外,编辑表vtiger_currency_info,将人民币的defaultid设置为-11,作为基础币种,美元的defaultid设置为0,同时设置好汇率。在“我的设定>货币”中设置好当前用的币种即可。
参考:
http://wiki.vtiger.com/index.php/Creating_New_Fields_in_Existing_Modules
http://wiki.vtiger.com/index.php/Ui_types
http://forums.vtiger.com/viewtopic.php?t=25886
类型解释
1) Generated Type
2) Display Type
a) 值为1:在所有视图中显示
b) 值为2:在DetailView中显示(只读,不包括编辑视图EditView)
c) 值为3:不单独显示,与其他字段相关
d) 值为4:只在CreateView视图中显示
UI Type (默认值1) |
说明 |
Column Type (默认值:VARCHAR(100)) |
GeneratedType (默认值1) |
Type Of Data (默认值V~O) |
Display Type (默认值1) |
Quick Create (默认值1) |
6 |
日期时间datetime |
DATETIME |
|
DT~M |
|
|
2 |
文本框textbox |
VARCHAR(255) |
|
V~M |
|
|
4 |
Text box with Inheritance, mandatory entry |
VARCHAR(100) |
2 |
|
|
3 |
15 |
下拉框droplist |
VARCHAR(255) |
|
V~M |
|
|
53 |
用户名下拉框 |
VARCHAR(100) |
|
|
|
|
70 |
日期date |
VARCHAR(100) |
|
T~O |
2 |
|
101 |
用户名弹出窗口 |
VARCHAR(36) |
1 |
V~O |
1 |
1 |
56 |
检查框checkbox |
|
1 |
V~/C~ |
1,3 |
1,2,3 |
28 |
文件上传 |
|
|
|
|
|
19 |
占2个显示单元的描述 |
Varchar(255) |
1 |
|
|
|
21 |
占1个显示单元的描述 |
Varchar(255) |
1 |
|
|
|
10 |
通用弹出窗口 |
Varchar(255) |
|
|
|
|
模块中如果定义了自定义编码字段(uitype=4,generatedtype=2,quickcreate=3),其编码值可以通过“设置 > Customize Record Numbering”进行设置,相关表是vtiger_modentity_num。
用途:用在两个或者两个以上可选择数据的情况。在一个下拉框中可以根据不同的角色分配不同的值。当一个模块中,有2个或者更多的下拉框,且下拉框之间的数据有关联关系的时候,可以通过设置定义依赖关系。
下拉框相关的数据库表包括:
表名 |
说明 |
vtiger_picklist |
定义下拉框的编码和名称 |
vtiger_picklist_seq |
保存vtiger_picklist中最大的picklistid |
vtiger_picklistvalues_seq |
保存最新的下拉框的值,以后依次加1 |
vtiger_picklist_dependency |
定义两个下拉框之间的数据逻辑关系,在“设置->编辑下拉框之间依赖关系”中设置 |
vtiger_picklist_dependency_seq |
保存vtiger_picklist_dependency中最大id |
vtiger_role2picklist |
定义角色与下拉框的对应关系,在“设置->下拉框编辑”中设置 |
vtiger_<picklist_name> |
下拉框名为“picklist_name”的值 |
vtiger_<picklist_name>_seq |
保存vtiger_<picklist_name>中最大id |
视图模板:EditViewUI.tpl(查询uitype eq)
后台代码:CRMEntity.php,DetailView.php,EditView. php(可搜索包含文字“uitype == ”)
新增uitype从1000开始编码,如果是对已有uitype的扩充,则新的uitype编码=1000+原uitype。例如,基于uitype 28新增一个uitype,则新的uitype值为1028.
新增uitype需要两方面工作:
1) 界面显示:编辑smarty/templates/EditViewUI.tpl,找到参考的uitype,复制并进行相应修改;
2) 后台逻辑:选择编辑如下文件:
a) data/CRMEntity.php
b) include/utils/DetailViewUtils.php
c) include/utils/DetailViewUtils.php/EditViewUtils.php
参考:
http://wiki.vtiger.com/archives/index.php?title=Developer:Debug_techniques
http://wiki.vtiger.com/archives/index.php/Log4php
修改config.performance.php中的参数:
'LOG4PHP_DEBUG' => true, |
编辑log4php.properties,打开LOG4PHP的日志标志:
log4php.rootLogger=DEBUG,A1 |
当需要定制List View或者模块的配置页面时,需要创建一个Smart Template的模板文件。模板文件应该创建在Smarty/templates/modules/<NewModuleName>目录下。
调用模板的代码如下:
$smarty->display(vtlib_getModuleTemplate($currentModule, 'MyListview.tpl')); |
文件:Smarty/templates/EditViewUI.tpl
功能:根据uitype进行显示
说明:当需要修改某种uitype的显示时,可在此文件中修改。
在“模块/EditView.php”中给模板$CURRENT_USERNAME赋值;
global $current_user; |
然后,可以在模板中使用,例如在EditFieldUI.tpl中,将uitype101的默认值设置为当前用户名。
{elseif $uitype eq 101}<!-- for reportsto field USERS POPUP --> <td width="20%" class="dvtCellLabel" align=right> <font color="red">{$mandatory_field}</font>{$usefldlabel} {if $MASS_EDIT eq '1'}<input type="checkbox" name="{$fldname}_mass_edit_check" id="{$fldname}_mass_edit_check" class="small" >{/if} </td> <td width="30%" align=left class="dvtCellInfo"> <input id="{$fldname}_display" name="{$fldname}_display" readonly type="text" style="border:1px solid #bababa;" {if isset($fldname)} value="{$fldvalue}" {else} value="{$CURRENT_USER}" value="{$fldvalue}" class="small" /> <input id="{$fldname}" name="{$fldname}" type="hidden" value="{$secondvalue}" id="{$fldname}" /> <input title="{$APP.LBL_CHANGE_TITLE}" accessKey="C" type="button" class="small" value='{$APP.LBL_CHANGE}' name="btn1" onclick='return window.open("index.php?module=Users&action=Popup&html=Popup_picker&form=vtlibPopupView&form_submit=false&fromlink={$fromlink}&recordid={$ID}&forfield={$fldname}","test","width=640,height=603,resizable=0,scrollbars=0");'> <input type="image" src="{'clear_field.gif'|@vtiger_imageurl:$THEME}" alt="{$APP.LBL_CLEAR}" title="{$APP.LBL_CLEAR}" onClick="this.form.{$fldname}.value=''; this.form.{$fldname}_display.value=''; return false;" align="absmiddle" style='cursor:hand;cursor:pointer'> </td> |
表名 |
说明 |
vtiger_seattachmentsrel |
定义crmid(表vtiger_crmentity)与附件的关系。 |
Vtiger_attachments |
附件信息 |
vtiger_attachmentsfolder |
|
vtiger_attachmentsfolder_seq |
|
上传文件UI设置如下:
|
参见:http://service.syncomni.com:10080/twiki/bin/view/Syncomni/VTigerCRMVtlibManual
数据 |
变量 |
当前用户 |
$current_user |
功能:记录模块实体的名字信息
字段 |
描述 |
|
|
字段含义及其赋值:http://service.syncomni.com:10080/twiki/bin/view/Syncomni/VTigerCRMFieldSetting
将Asia/Taipei改为Asia/Beijing
记录与某一个field相关的模块。
不同的角色可以看到不同的picklist类型的数据,这些数据在Settings>Picklist Editor中配置。
参考:http://wiki.vtiger.com/index.php/vtiger510:Module_Workflow
部分配置在config.inc.php中的配置可以通过“设置>Configuration Editor”编辑。
这个模块比较特殊,与其对应的表是vtiger_notes。
如果一个模块不允许批量删除,编辑模块下的ListView.php,注释掉如下内容,将不会在界面上显示批量删除的按钮:
if(isPermitted($currentModule,'Delete','') == 'yes') $list_buttons['del'] = $app_strings[LBL_MASS_DELETE]; |
如果一个模块不允许批量删除,编辑模块下的Delete.php,注释掉如下内容,将不会执行删除操作:
DeleteEntity($currentModule, $return_module, $focus, $record, $return_id); |
实例:例如销售订单(SalesOrder)模块中,当添加一个销售订单时,可以添加多个产品。
本章节重点研究如何实现上述功能。
第一步,将产品信息移植到模块实例Systeo中。
在Smarty/templates下建立目录TrainingPlan,将Smarty/templates/ProductDetails.tpl复制到该目录中。
文件:config.inc.php
修改:$default_timezone = 'Asia/Shanghai';
使用jquery作为javascript开发包,所有javascript的调用都写在新增的文件jquery_vtiger_tools.js中。
版本:jquery1.7.1
功能:增加一个主菜单
算法:在vtiger_parenttab表中增加主菜单,并同步到文件parent_tabdata.php
vTiger代码修改:在vtlib/Vtiger/Menu.php中增加静态方法:
/** * Add one main tab, if the tab name exists, then do nothing. * @param main tab name * By Kevin Wang, 2012/2/1 */ static function addMainMenu($tab_id, $tab_label, $seq) {
self::log("Enter addMainMenu ..."); global $adb; $query = false; $instance = false;
$query = "SELECT * FROM vtiger_parenttab WHERE parenttabid=?"; $result = $adb->pquery($query, Array($tab_id)); if($adb->num_rows($result)) { self::log("Main tab [label=$tab_id] exists! Cannot add again!"); return 1; }
$query = "SELECT * FROM vtiger_parenttab WHERE parenttab_label=?"; $result = $adb->pquery($query, Array($tab_label)); if($adb->num_rows($result)) { self::log("Main tab [label=$tab_label] exists! Cannot add again!"); return 1; }
$adb->pquery("INSERT INTO vtiger_parenttab (parenttabid,parenttab_label,sequence,visible) VALUES(?,?,?)", Array($tab_id, $tab_label, $seq, 0));
self::log("Main tab [id=$tab_id, label=$tab_label,seq=$seq] is added to menu ... DONE"); self::syncfile();
return 0; } |
工具实现:增加文件add_main_menu.html和add_main_menu.php,在jquery_vtiger_tools添加AJAX调用实现。
依赖:jquery/jquery1.7.1.js
充分理解客户需求,明确:
1) 每个功能需求涉及到的业务数据及其格式
2) 和功能相关的配置数据以及修改频率的高低
3) 需求对功能和数据的权限要求
4) 业务流程
在理解需求的基础上,由测试人员负责编写测试计划。
在充分理解需求的前提下,划分功能模块,主要工作如下:
1) 定义出模块数目及其功能
2) 对每个模块设计页面布局,考虑相关数据
3) 设计数据信息,包括只读性、UI类型、数据类型、变量名称及其显示信息
4) 设计权限规划
5) 编写配置信息说明
编码主要包括三部分内容:
1) 根据设计,开发添加和删除模块的脚本
2) 开发多语言支持的代码
3) 根据业务需求,开发特定功能代码
使用开发工具添加/删除模块,按照测试计划测试。
测试通过后,将模块导出到.zip文件,在生产环境中导入该.zip文件。
在基于vTigerCRM开发完成后,如果需要进行客户化项目实施,需要注意如下内容:
在“Settings>Customize Record Numbering”设置好编码规则。
参考:http://service.syncomni.com:10080/twiki/bin/view/Syncomni/VTigerCRMDevelopment
问题1:添加数据时下拉框Systeo Type不显示数据,编辑时可以显示。
分析:
增加一个模块Systeo的脚本代码中,增加了picklist类型(类型编码是15)的字段(field),生成代码如下:
$field2 = new Vtiger_Field(); $field2->name = 'SysteoType'; $field2->label = 'Systeo Type'; $field2->columntype = 'VARCHAR(100)'; $field2->uitype = 15; $field2->typeofdata = 'V~O';// Varchar~Optional $block1->addField($field2); /** table and column are automatically set */
$field2->setPicklistValues( Array ('Employee', 'Trainee') ); |
红字部分将会导致在数据库表“vtiger_picklist”中增加一条记录“SysteoType”,在页面显示时,系统将会查找表“vtiger_SysteoType”,实际的表名字是“vtiger_systeotype”。而数据库中,表名字是大小写敏感的,因此页面不能显示期待显示的下拉框数据。
解决:修改表“vtiger_picklist”中name全部为小写即可。
问题2:Setting>PickList Editor中,编辑Systeo的Picklist,显示有2条记录,但是值都是空白。
分析:
在AssignPicklistValues.tpl编译生成的.php文件中,显示list的代码如下:
<select multiple id="availList" name="availList" class="small crmFormList" style="overflow:auto; height: 150px;width:200px;border:1px solid #666666;font-family:Arial, Helvetica, sans-serif;font-size:11px;"> <?php $_from = $this->_tpl_vars['PICKVAL']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }if (count($_from)): foreach ($_from as $this->_tpl_vars['pick_val']): ?> <option value="<?php echo $this->_tpl_vars['pick_val']; ?> "><?php echo $this->_tpl_vars['pick_val']; ?> </option> <?php endforeach; endif; unset($_from); ?> </select> |
经过研究代码,未发现任何问题。因此,打开日志调试,计划通过打印更多的信息进行跟踪。打开日志后,发现数据显示正常。猜测是某些代码未及时更新到缓冲程序中。
功能:增加一个主菜单Finance,包含2个系统自带的子菜单(模块)Contact和Webmail。
实现:
1) 编辑文件parent_tabdata.php,在$parent_tab_info_array增加:9=>'Finance',在$parent_child_tab_rel_array增加9=>array(4,28)
2) 编辑include/language/en_us.lang.php,在$app_strings中增加’Finance’=>’Finance’
3) 编辑include/language/zh_cn.lang.php,在$app_strings中增加’Finance’=>’财务’
4) 刷新登录页面,出现Finance菜单,但是鼠标划过时没有子菜单出现。
5) 往vtiger_parenttabrel和vtiger_parenttabrel增加对应数据
问题:到第4步,不能显示子菜单,分析如下:
原因:在生成页面时,没有生成菜单层,例如对于Settings菜单,会生成菜单层Settings_sub,内容如下:
<div class="drop_mnu" id="Settings_sub" onmouseout="fnHideDrop('Settings_sub')" onmouseover="fnShowDrop('Settings_sub')"> <table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr><td><a href="index.php?module=Settings&action=index&parenttab=Settings" class="drop_down">Settings</a></td></tr>
<tr><td><a href="index.php?module=Settings&action=ModuleManager&parenttab=Settings" class="drop_down">Module Manager</a></td></tr> </table> </div> |
如上内容通过调用Header.tpl实现,内容如下:
<!-- Drop Down Menu in the Main Tab --> {foreach name=parenttablist key=parenttab item=details from=$QUICKACCESS} <div class="drop_mnu" id="{$parenttab}_sub" onmouseout="fnHideDrop('{$parenttab}_sub')" onmouseover="fnShowDrop('{$parenttab}_sub')"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> {foreach name=modulelist item=modules from=$details} {assign var="modulelabel" value=$modules[1]|@getTranslatedString:$modules[0]}
{* Use Custom module action if specified *} {assign var="moduleaction" value="index"} {if isset($modules[2])} {assign var="moduleaction" value=$modules[2]} {/if}
<tr><td><a href="index.php?module={$modules.0}&action={$moduleaction}&parenttab={$parenttab}" class="drop_down">{$modulelabel}</a></td></tr> {/foreach} </table> </div> {/foreach} |
上述代码翻译后的结果如下:
<!-- Drop Down Menu in the Main Tab --> <?php $_from = $this->_tpl_vars['QUICKACCESS']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }$this->_foreach['parenttablist'] = array('total' => count($_from), 'iteration' => 0); if ($this->_foreach['parenttablist']['total'] > 0): foreach ($_from as $this->_tpl_vars['parenttab'] => $this->_tpl_vars['details']): $this->_foreach['parenttablist']['iteration']++; ?> <div class="drop_mnu" id="<?php echo $this->_tpl_vars['parenttab']; ?> _sub" onmouseout="fnHideDrop('<?php echo $this->_tpl_vars['parenttab']; ?> _sub')" onmouseover="fnShowDrop('<?php echo $this->_tpl_vars['parenttab']; ?> _sub')"> <table width="100%" border="0" cellpadding="0" cellspacing="0"> <?php $_from = $this->_tpl_vars['details']; if (!is_array($_from) && !is_object($_from)) { settype($_from, 'array'); }$this->_foreach['modulelist'] = array('total' => count($_from), 'iteration' => 0); if ($this->_foreach['modulelist']['total'] > 0): foreach ($_from as $this->_tpl_vars['modules']): $this->_foreach['modulelist']['iteration']++; ?> |
count($_from)的值是8,并没有将新增加的菜单Finance计算在内,因此需要研究为什么$_from只有8个元素。
$_from = $this->_tpl_vars['QUICKACCESS']是从函数getAllParenttabmoduleslist()获取的值,如下:
$smarty->assign("QUICKACCESS",getAllParenttabmoduleslist()); |
该函数查询了数据库表vtiger_parenttabrel、vtiger_tab和vtiger_parenttabrel进行计算,SQL语句如下:
select name,tablabel,parenttab_label,vtiger_tab.tabid from vtiger_parenttabrel inner join vtiger_tab on vtiger_parenttabrel.tabid = vtiger_tab.tabid inner join vtiger_parenttab on vtiger_parenttabrel.parenttabid = vtiger_parenttab.parenttabid and vtiger_tab.presence in (0,2) order by vtiger_parenttab.sequence, vtiger_parenttabrel.sequence |
因此,除了在数据文件增加以外还需要往vtiger_parenttabrel和vtiger_parenttabrel增加对应数据,才能在鼠标划过主菜单时显示子菜单。
打开Project模块,初始状态下没有数据,首次添加一个Project,将会提示如下信息:
Duplicate Project No - Click here to Configure the Project No |
原因:没有配置项目编码的规则,点击“here”配置即可。
建议:在“Settings>Customize Record Numbering”设置好编码规则。
文件 |
文件操作 |
modules/SMSNotifier/language/zh_cn.lang.php |
添加 |
modules/Project/language/zh_cn.lang.php |
添加 |
Modules/Settings/language/zh_cn.lang.php |
修改 |
Settings
添加如下内容:
'LBL_PICKLIST_DEPENDENCY_SETUP' => '编辑下拉框依赖关系', 'LBL_PICKLIST_DEPENDENCY_DESCRIPTION' => '定制两个下拉框之间的数据逻辑关系', |
select * from vtiger_picklist where name in (select fieldname from vtiger_field where tablename like '%cashj%' and uitype=15) |
uitype |
功能 |
修改文件 |
1028 |
DocLib文件上传按钮 |
Smarty\templates\EditViewUI.tpl:944~964 |
|
|
|