mirror of
https://gitee.com/ShopeX/OMS
synced 2026-03-22 18:35:35 +08:00
455 lines
14 KiB
Plaintext
455 lines
14 KiB
Plaintext
desktop开发手册
|
||
|
||
since : %%date(%Y-%m-%d) $Rev$
|
||
|
||
%!target:html
|
||
%!postproc(tex): '\.gif' '.eps'
|
||
%!preproc(html): '\.dot' '.gif'
|
||
%!preproc(tex): '\.dot' '.pdf'
|
||
%!encoding:utf-8
|
||
=desktop简介=
|
||
desktop提供一个带有权限和工作流的操作环境,一个网站一般分为前台和后台,它提供了常用的后台操作实现机制,这大大节省了你后台开发的时间。
|
||
desktop作为ecos的一个基础app一般不单独存在,是其他app操作流程的载体。ecstore是基于ecos的开源商城系统,亦依赖desktop,它使用了绝大部分desktop的功能,建议使用desktop开发新的应用时,多参照下ecstore,为便于理解,本手册亦以ecstore为例讲解。
|
||
=此手册目标人群=
|
||
开发者:开发基于ecos的新应用或扩展已有应用功能时,需开发后台功能的会用到desktop
|
||
|
||
|
||
=desktop提供了下列功能:=
|
||
- 权限管理
|
||
- 回收站
|
||
- 显示app提供的菜单项或控制面板项
|
||
- finder功能
|
||
|
||
|
||
==desktop.xml说明==
|
||
|
||
装了desktop这个app,就能识别其他app目录下的desktop.xml文件,这个文件必须列出所有后台看见或看不见的控制器,否则除非是超级管理员,任何其他非超级管理员desktop用户无法访问这些控制器。
|
||
desktop.xml的结构大概是这样的:
|
||
|
||
|
||
```
|
||
<desktop>
|
||
|
||
<panelgroup id="other" icon="panel-other.png" order="100">其他</panelgroup>
|
||
...
|
||
<adminpanel group="desktop_other" permission="other" controller='admin_member_attr' action='index' display='true'>会员注册项</adminpanel>
|
||
...
|
||
<permissions>
|
||
<permission id="shipment" display='true'>配送设置</permission>
|
||
...
|
||
</permissions>
|
||
|
||
<workground name="商品" id="b2c.wrokground.goods" controller="admin_goods" action="index" order="20">
|
||
<menugroup name="商品管理">
|
||
<menu controller='admin_goods_editor' action='add' permission='goods' display='false' order='10'>添加商品</menu>
|
||
...
|
||
</menugroup>
|
||
...
|
||
</workground>
|
||
...
|
||
</desktop>
|
||
|
||
```
|
||
desktop.xml不一定包含上面的所有标签,各个标签及属性含义如下:
|
||
|
||
- ``desktop ``
|
||
|
||
每个 desktop.xml 的根标签
|
||
- ``panelgroup``
|
||
|
||
控制面板里的组
|
||
其属性含义如下:
|
||
|
||
1. ``id:``控制面板里组的唯一标识
|
||
|
||
2. ``icon:`` 控制面板里组的图标,路径默认的起点是app下的static,假如此desktop.xml是desktop这个app的,则图标的路径会自动解析成/app/desktop/static/panel-other.png
|
||
|
||
3. ``order:`` 组的显示顺序
|
||
|
||
- ``adminpanel``
|
||
|
||
控制面板里的项
|
||
其属性含义如下:
|
||
|
||
1. ``group:`` 指属性那个控制面板组,其值是panelgroup的id属性值加app前缀,例如group="desktop_other"
|
||
|
||
2. ``permission:`` 指此控制面板里的项属性那个权限(下面讲到权限)
|
||
|
||
3. ``controller:`` controller和action(构成点此控制面板项时的去处,如果action属性未写则默认值为index)
|
||
|
||
4. ``action:`` controller和action(构成点此控制面板项时的去处,如果action属性未写则默认值为index)
|
||
|
||
5. ``display:`` 是否显示在控制面板组里,true为显示,false为不显示
|
||
|
||
|
||
- ``permissions``
|
||
权限被包括在它里面
|
||
|
||
- ``permission``
|
||
包含在permissions标签里,每一个都是一个权限
|
||
其属性含义如下:
|
||
|
||
1. ``id:`` 权限的唯一标识,全局唯一
|
||
|
||
2. ``display:`` 新建角色时,是否显示在角色权限列表里,true为显示,false为不显示
|
||
|
||
|
||
|
||
- ``workground``
|
||
|
||
可以包含多个menugroup,看【图 desktop.png】
|
||
其属性有:
|
||
|
||
1.``name:`` 1区显示出来的label
|
||
|
||
2.``id:``(workground的唯一标识)
|
||
|
||
3.``controller:`` 构成点此workground tab时的去处,如果action属性未写则默认值为index
|
||
|
||
4.``action:`` 构成点此workground tab时的去处,如果action属性未写则默认值为index
|
||
|
||
5.``order:`` 此workground在tab列表中的排序
|
||
|
||
- ``menugroup``
|
||
|
||
可以包含多个``menu``,看【图 desktop.png】 2区
|
||
|
||
- ``menu``
|
||
|
||
看【图 desktop.png】为3区提供菜单,除了拥有跟workground一样的属性外,此标签还有另外两个属性:
|
||
|
||
``permission:`` 权限,为标签permission里的id属性的值
|
||
|
||
``display:`` 是否显示,有些控制器里的方法是不必显示成菜单的,比如得到post数据保存商品的控制器等,这时需把display设成false的
|
||
|
||
|
||
=先来看下,一个典型的desktop的列表页包含了哪些内容=
|
||
|
||
|
||
【图 desktop.png】
|
||
[images/desktop.png]
|
||
|
||
=接下来我们看各个区里的内容是如何增删及展示出来的=
|
||
|
||
- 1、2、3区都是根据app下的``desktop.xml``产生,如何填充,可以参照desktop.xml的介绍试试看
|
||
|
||
|
||
|
||
- 5区顶部菜单产生是靠往服务id为desktop_menu里注册服务实现
|
||
|
||
在``service.xml``里添加
|
||
```
|
||
<service id="desktop_menu">
|
||
<class>b2c_service_view_menu</class>
|
||
</service>
|
||
```
|
||
|
||
``b2c_service_view_menu``内容如下
|
||
```
|
||
class b2c_service_view_menu{
|
||
function function_menu(){
|
||
$shop_base = app::get('site')->router()->gen_url(array('app'=>'site', 'ctl'=>'default'));
|
||
$html[] = "<a href='$shop_base' target='_blank'>浏览商店</a>";
|
||
return $html;
|
||
|
||
}
|
||
}
|
||
```
|
||
说明:``desktop_menu``的服务,必须定义名字为function_menu的方法,它的返回值即为5区的菜单项
|
||
|
||
- 4区finder,先看下细分图
|
||
|
||
【图 finder.png】
|
||
|
||
[images/finder.png]
|
||
|
||
|
||
finder说明:下面对finder各个区的内容的来龙去脉做解释,我们平时做任何web应用大概都少不了,后台管理功能,这之中最常看到的大概就是:数据列表,对数据进行单条查看,删除,搜索列表数据。finder就是做这样工作的,要做到这些事情只需简单的给一个方法传几个参数而已。
|
||
|
||
例如:
|
||
```
|
||
function index(){
|
||
$this->finder('b2c_mdl_goods',array(
|
||
'title'=>app::get('b2c')->_('商品列表'),
|
||
'actions'=>array(array('label'=>app::get('b2c')->_('添加商品'),'href'=>'index.php?app=b2c&ctl=admin_goods_editor&act=add','target'=>'_blank'),),
|
||
'use_buildin_set_tag'=>true,
|
||
'use_buildin_filter'=>true,
|
||
'use_buildin_export'=>true,
|
||
'allow_detail_popup'=>true,
|
||
'use_view_tab'=>true,
|
||
'finder_aliasname'=>'xxxx',
|
||
));
|
||
}
|
||
```
|
||
后台的控制器必须继承desktop_controller,继承后才有finder方法,下面介绍下finder方法的几个参数:
|
||
|
||
- 第一个参数是字符串,(上例中是b2c_mdl_goods),是model里的class名,它决定了finder列表的数据源,默认情况下是b2c_mdl_goods类里的getlist方法返回的数据
|
||
|
||
- 第二个参数是数组,这个数组内涵相当丰富,解释如下:
|
||
|
||
``title:`` 【图 finder.png】中的1区显示出来的内容
|
||
|
||
``actions:`` 【图 finder.png】2区里的内容除了显示内置的操作以外(use_buildin_set_tag,use_buildin_filter这些是控制项),还可以自定义添加新操作,参照上面格式。
|
||
|
||
``allow_detail_popup:`` allow_detail_popup和其下面的其他项,是上面所说的内置的操作的控制项,其值为true时,显示此内置项。完整的内置操作及含义如下(可到desktop_finder_builder_view类里查看):
|
||
|
||
**use_buildin_new_dialog:** 是否显示新建操作
|
||
|
||
**use_buildin_set_tag:** 是否显示设置标签操作
|
||
|
||
**use_buildin_recycle:** 是否显示删除操作
|
||
|
||
**use_buildin_export:** 是否显示导出操作
|
||
|
||
**use_buildin_import:** 是否显示导入操作
|
||
|
||
**use_buildin_tagedit:** 是否显示标签管理操作
|
||
|
||
|
||
|
||
下面几个控制项不是控制【图 finder.png】2区里的内容
|
||
|
||
**use_view_tab:** 是否显示finder中的tab(如果有),有无需看控制器中是否有_views方法。
|
||
|
||
**use_buildin_filter:** 是否使用高级赛选 【图 finder.png】6区
|
||
|
||
**use_buildin_refresh:** 是否显示刷新操作(高级赛选旁)
|
||
|
||
**use_buildin_setcol:** 是否显示列配置
|
||
|
||
**use_buildin_selectrow:** 是否显示每条记录前的复选按钮
|
||
|
||
**allow_detail_popup:** 是否显示查看列中的弹出查看图标(【图 finder.png】4区第二个图标)
|
||
|
||
**finder_aliasname:** 此finder的别名,用于保存此finder的
|
||
|
||
=下面对几个重点区域内容的填充做详细讲解=
|
||
|
||
-
|
||
==增加finder列表的自定义列==
|
||
|
||
|
||
finder列表的列分为以下三种:
|
||
|
||
1.查看列 (分为下列查看和弹出查看)
|
||
|
||
2.自定义列(也可称函数列),可以通过一种方法扩展
|
||
|
||
3.普通列(数据表里有的字段,也即dbschema里有的字段)
|
||
|
||
|
||
【图 finder.png】5区的两列操作和标签都不是dbschema里的字段,还能显示出来是因为他们是自定义列,通过下面的步骤实现:
|
||
|
||
1.注册一个service,其id是desktop_finder.xxx,xxx是finder方法的第一个参数,上例中是b2c_mdl_goods,最终结果在相应的应用中services.xml中如下样子:
|
||
|
||
```
|
||
<service id="desktop_finder.b2c_mdl_goods">
|
||
<class>b2c_finder_goods</class>
|
||
</service>
|
||
|
||
```
|
||
|
||
b2c_finder_goods类里有两种方法,两种属性,属性和方法成对出现:
|
||
|
||
第一种 属性以detail_开头,对应的方法也以detail_开头 例如:
|
||
```
|
||
|
||
var $detail_basic = '基本信息';
|
||
function detail_basic($gid){
|
||
...
|
||
return $str;
|
||
}
|
||
```
|
||
|
||
|
||
属性detail_basic是作为列头显示的,方法detail_basic的返回值是点击查看里出现的内容[如果有多个detail_开头的方法,则显示第一个里面的内容]
|
||
|
||
|
||
|
||
第二种:属性以column_开头,对应的方法也以column_开头
|
||
|
||
|
||
```
|
||
var $column_editbutton = '操作';
|
||
public function column_editbutton($row)
|
||
{
|
||
...
|
||
return $str;
|
||
}
|
||
```
|
||
|
||
属性column_editbutton是作为列头显示的,方法column_editbutton的返回值是每行此列的显示内容,方法column_editbutton的参数是当前行的数组。
|
||
|
||
补充:自定义列后来又加了一个属性,属性名规则是列变量加_order 例如 var $column_editbutton_order = **order**
|
||
order 可以是COLUMN_IN_HEAD[放在普通列前面]或COLUMN_IN_TAIL[放在普通列后面]
|
||
|
||
|
||
-
|
||
==高级赛选==
|
||
|
||
高级赛选中的搜索项大部分来自dbschema中,搜索类型[单选或下拉或输入关键词]也定义在dbschema
|
||
|
||
除此之外,高级赛选中的搜索项还可以通过注册service扩展,id为extend_filter_xxx,xxx为finder方法的第一个参数,例如:
|
||
|
||
|
||
```
|
||
<service id="extend_filter_b2c_mdl_orders">
|
||
<class>b2c_finder_extend_orders</class>
|
||
</service>
|
||
|
||
```
|
||
|
||
b2c_finder_extend_orders 类如下:
|
||
|
||
```
|
||
|
||
class b2c_finder_extend_members{
|
||
function get_extend_colums(){
|
||
$db['members']=array (
|
||
'columns' =>
|
||
array (
|
||
'refer_id' =>
|
||
array (
|
||
'type' => 'varchar(200)',
|
||
'required' => true,
|
||
'default' => 0,
|
||
'label' => '首次来源ID',
|
||
'width' => 75,
|
||
'editable' => true,
|
||
'filtertype' => 'yes',
|
||
'filterdefault' => true,
|
||
'in_list' => true,
|
||
'default_in_list' => true,
|
||
),
|
||
|
||
...
|
||
|
||
'refer_url' =>
|
||
array (
|
||
'type' => 'varchar(200)',
|
||
'required' => true,
|
||
'default' => 0,
|
||
'label' => '首次来源URL',
|
||
'width' => 75,
|
||
'editable' => true,
|
||
'filtertype' => 'yes',
|
||
'filterdefault' => true,
|
||
'in_list' => true,
|
||
'default_in_list' => true,
|
||
)))
|
||
}
|
||
}
|
||
|
||
```
|
||
|
||
class里必须包含get_extend_colums方法,它的返回值跟dbschema里的一样,如果扩展了高级搜索,一般需要在model里重定义_filter方法,以便使用上扩展过滤字段
|
||
|
||
-
|
||
==快捷搜索==
|
||
|
||
有两个地方影响快捷搜索,dbschema中定义的字段中,searchtype这一项,如果有这项则会在快捷搜索里出现,还有就是在model里定义searchOptions函数,返回值的数组就为快速搜索里的项,例如:
|
||
|
||
```
|
||
function searchOptions(){
|
||
$arr = parent::searchOptions();
|
||
return array_merge($arr,array(
|
||
'bn'=>__('货号'),
|
||
'keyword'=>__('商品关键字'),
|
||
));
|
||
}
|
||
```
|
||
|
||
-
|
||
|
||
==finder上的tab==
|
||
|
||
需要在调用了finder的控制器里定义_views方法,_views方法的返回值格式如下:
|
||
|
||
```
|
||
|
||
$sub_menu = array(
|
||
0=>array('label'=>app::get('b2c')->_('全部'),'optional'=>false,'filter'=>"",'addon'=>1,'href'=>'xxx.xxx','finder'=>'xxxx'),
|
||
...
|
||
7=>array('label'=>app::get('b2c')->_('已作废'),'optional'=>false,'filter'=>array('status'=>'dead'),'addon'=>1,'href'=>'xxx.xxx'),
|
||
);
|
||
|
||
```
|
||
|
||
``label:`` tab的标题文字
|
||
|
||
``optional:`` 此tab是否可选
|
||
|
||
``filter:`` 此tab的过滤条件
|
||
|
||
``addon:`` 此过滤条件下有多少条记录
|
||
|
||
``href:`` 此tab的链接地址
|
||
|
||
|
||
|
||
=回收站=
|
||
|
||
如果finder方法第二个参数中使用了use_buildin_recycle,则此finder列表的actions区就有了内置的删除按钮,有时需要在删除前和删除后做一些检测工作,比方记录不准删除,或删除记录时需删除资源文件等。
|
||
实现这一功能机制是在model里定义pre_recycle[删除前执行]和suf_recycle[删除后执行]方法
|
||
|
||
|
||
=桌面=
|
||
|
||
登录后台首先看到的界面,其内容由各个app通过service注册进来,里面每一块都是一个wigets,下面是b2c的service.xml里桌面内容相关的一段
|
||
|
||
```
|
||
<service id="desktop.widgets">
|
||
<class>b2c_desktop_widgets_workcount</class>
|
||
<class>b2c_desktop_widgets_stats</class>
|
||
<class>b2c_desktop_widgets_exstatistics</class>
|
||
</service>
|
||
|
||
```
|
||
|
||
每个class就是一个wigets,每个class里面的内容为以下格式[以b2c_desktop_widgets_workcount为例]:
|
||
|
||
```
|
||
|
||
class b2c_desktop_widgets_workcount implements desktop_interface_widget{
|
||
|
||
|
||
function __construct($app){
|
||
$this->app = $app;
|
||
$this->render = new base_render(app::get('b2c'));
|
||
}
|
||
|
||
function get_title(){
|
||
|
||
return app::get('b2c')->_("统计分析");
|
||
|
||
}
|
||
function get_html(){
|
||
...
|
||
return $render->fetch('desktop/widgets/workcount.html');
|
||
}
|
||
function get_className(){
|
||
|
||
return " valigntop";
|
||
}
|
||
function get_width(){
|
||
|
||
return "l-1";
|
||
|
||
}
|
||
|
||
}
|
||
|
||
```
|
||
|
||
函数说明
|
||
|
||
`` function get_title():`` desktop widgets标题
|
||
|
||
`` function get_title():`` desktop widgets 内容
|
||
|
||
`` function get_className():`` 给desktop widgets 区块添加class name
|
||
|
||
`` function get_width():`` 返回值为l-1显示在左侧,值为l-2显示在左侧
|
||
|
||
|