浏览代码

新增系统配置扩展参数替换功能
优化系统配置添加逻辑
修复系统配置无法添加的BUG

Karson 6 年之前
父节点
当前提交
193f33f11a

+ 28 - 1
application/admin/controller/general/Config.php

@@ -21,7 +21,7 @@ class Config extends Backend
      * @var \app\common\model\Config
      */
     protected $model = null;
-    protected $noNeedRight = ['check'];
+    protected $noNeedRight = ['check', 'rulelist'];
 
     public function _initialize()
     {
@@ -62,6 +62,7 @@ class Config extends Backend
         }
         $this->view->assign('siteList', $siteList);
         $this->view->assign('typeList', ConfigModel::getTypeList());
+        $this->view->assign('ruleList', ConfigModel::getRegexList());
         $this->view->assign('groupList', ConfigModel::getGroupList());
         return $this->view->fetch();
     }
@@ -202,6 +203,32 @@ class Config extends Backend
     }
 
     /**
+     * 规则列表
+     * @internal
+     */
+    public function rulelist()
+    {
+        //主键
+        $primarykey = $this->request->request("keyField");
+        //主键值
+        $keyValue = $this->request->request("keyValue", "");
+
+        $keyValueArr = array_filter(explode(',', $keyValue));
+        $regexList = \app\common\model\Config::getRegexList();
+        $list = [];
+        foreach ($regexList as $k => $v) {
+            if ($keyValueArr) {
+                if (in_array($k, $keyValueArr)) {
+                    $list[] = ['id' => $k, 'name' => $v];
+                }
+            } else {
+                $list[] = ['id' => $k, 'name' => $v];
+            }
+        }
+        return json(['list' => $list]);
+    }
+
+    /**
      * 发送测试邮件
      * @internal
      */

+ 3 - 0
application/admin/lang/zh-cn/general/config.php

@@ -33,6 +33,7 @@ return [
     'Array'                       => '数组',
     'Array key'                   => '键名',
     'Array value'                 => '键值',
+    'Custom'                      => '自定义',
     'Content'                     => '数据列表',
     'Rule'                        => '校验规则',
     'Site name'                   => '站点名称',
@@ -45,6 +46,8 @@ return [
     'Fixed page'                  => '后台固定页',
     'Category type'               => '分类类型',
     'Config group'                => '配置分组',
+    'Rule tips'                   => '校验规则使用请参考Nice-validator文档',
+    'Extend tips'                 => '扩展属性支持{id}、{name}、{group}、{title}、{value}、{content}、{rule}替换',
     'Mail type'                   => '邮件发送方式',
     'Mail smtp host'              => 'SMTP服务器',
     'Mail smtp port'              => 'SMTP端口',

+ 144 - 120
application/admin/view/general/config/index.html

@@ -1,17 +1,23 @@
 <style type="text/css">
     @media (max-width: 375px) {
-        .edit-form tr td input{width:100%;}
-        .edit-form tr th:first-child,.edit-form tr td:first-child{
-            width:20%;
+        .edit-form tr td input {
+            width: 100%;
         }
-        .edit-form tr th:nth-last-of-type(-n+2),.edit-form tr td:nth-last-of-type(-n+2){
+
+        .edit-form tr th:first-child, .edit-form tr td:first-child {
+            width: 20%;
+        }
+
+        .edit-form tr th:nth-last-of-type(-n+2), .edit-form tr td:nth-last-of-type(-n+2) {
             display: none;
         }
     }
-    .edit-form table > tbody > tr td a.btn-delcfg{
+
+    .edit-form table > tbody > tr td a.btn-delcfg {
         visibility: hidden;
     }
-    .edit-form table > tbody > tr:hover td a.btn-delcfg{
+
+    .edit-form table > tbody > tr:hover td a.btn-delcfg {
         visibility: visible;
     }
 </style>
@@ -19,132 +25,136 @@
     <div class="panel-heading">
         {:build_heading(null, false)}
         <ul class="nav nav-tabs">
-            {foreach $siteList as $index=>$vo} 
+            {foreach $siteList as $index=>$vo}
             <li class="{$vo.active?'active':''}"><a href="#{$vo.name}" data-toggle="tab">{:__($vo.title)}</a></li>
             {/foreach}
-            <li>
-                <a href="#addcfg" data-toggle="tab" title="{:__('Add new config')}"><i class="fa fa-plus"></i></a>
+            <li data-toggle="tooltip" title="{:__('Add new config')}">
+                <a href="#addcfg" data-toggle="tab"><i class="fa fa-plus"></i></a>
             </li>
         </ul>
     </div>
 
     <div class="panel-body">
         <div id="myTabContent" class="tab-content">
-            {foreach $siteList as $index=>$vo} 
+            {foreach $siteList as $index=>$vo}
             <div class="tab-pane fade {$vo.active ? 'active in' : ''}" id="{$vo.name}">
                 <div class="widget-body no-padding">
                     <form id="{$vo.name}-form" class="edit-form form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/edit')}">
                         {:token()}
                         <table class="table table-striped">
                             <thead>
-                                <tr>
-                                    <th width="15%">{:__('Title')}</th>
-                                    <th width="68%">{:__('Value')}</th>
-                                    <th width="15%">{:__('Name')}</th>
-                                    <th width="2%"></th>
-                                </tr>
+                            <tr>
+                                <th width="15%">{:__('Title')}</th>
+                                <th width="68%">{:__('Value')}</th>
+                                <th width="15%">{:__('Name')}</th>
+                                <th width="2%"></th>
+                            </tr>
                             </thead>
                             <tbody>
-                                {foreach $vo.list as $item}
-                                <tr>
-                                    <td>{$item.title}</td>
-                                    <td>
-                                        <div class="row">
-                                            <div class="col-sm-8 col-xs-12">
-                                                {switch $item.type}
-                                                {case string}
-                                                <input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}" />
-                                                {/case}
-                                                {case text}
-                                                <textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
-                                                {/case}
-                                                {case editor}
-                                                <textarea {$item.extend} name="row[{$item.name}]" id="editor-{$item.name}" class="form-control editor" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
-                                                {/case}
-                                                {case array}
-                                                <dl class="fieldlist" data-name="row[{$item.name}]">
-                                                    <dd>
-                                                        <ins>{:__('Array key')}</ins>
-                                                        <ins>{:__('Array value')}</ins>
-                                                    </dd>
-                                                    <dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
-                                                    <textarea name="row[{$item.name}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
-                                                </dl>
-                                                {/case}
-                                                {case datetime}
-                                                <input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-tip="{$item.tip}" data-rule="{$item.rule}" />
-                                                {/case}
-                                                {case number}
-                                                <input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}" />
-                                                {/case}
-                                                {case checkbox}
+                            {foreach $vo.list as $item}
+                            <tr>
+                                <td>{$item.title}</td>
+                                <td>
+                                    <div class="row">
+                                        <div class="col-sm-8 col-xs-12">
+                                            {switch $item.type}
+                                            {case string}
+                                            <input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value|htmlentities}" class="form-control" data-rule="{$item.rule}" data-tip="{$item.tip}"/>
+                                            {/case}
+                                            {case text}
+                                            <textarea {$item.extend} name="row[{$item.name}]" class="form-control" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
+                                            {/case}
+                                            {case editor}
+                                            <textarea {$item.extend} name="row[{$item.name}]" id="editor-{$item.name}" class="form-control editor" data-rule="{$item.rule}" rows="5" data-tip="{$item.tip}">{$item.value|htmlentities}</textarea>
+                                            {/case}
+                                            {case array}
+                                            <dl class="fieldlist" data-name="row[{$item.name}]">
+                                                <dd>
+                                                    <ins>{:__('Array key')}</ins>
+                                                    <ins>{:__('Array value')}</ins>
+                                                </dd>
+                                                <dd><a href="javascript:;" class="btn btn-sm btn-success btn-append"><i class="fa fa-plus"></i> {:__('Append')}</a></dd>
+                                                <textarea name="row[{$item.name}]" class="form-control hide" cols="30" rows="5">{$item.value|htmlentities}</textarea>
+                                            </dl>
+                                            {/case}
+                                            {case datetime}
+                                            <input {$item.extend} type="text" name="row[{$item.name}]" value="{$item.value}" class="form-control datetimepicker" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
+                                            {/case}
+                                            {case number}
+                                            <input {$item.extend} type="number" name="row[{$item.name}]" value="{$item.value}" class="form-control" data-tip="{$item.tip}" data-rule="{$item.rule}"/>
+                                            {/case}
+                                            {case checkbox}
+                                            {foreach name="item.content" item="vo"}
+                                            <label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
+                                            {/foreach}
+                                            {/case}
+                                            {case radio}
+                                            {foreach name="item.content" item="vo"}
+                                            <label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value" }checked{/in} /> {$vo}</label>
+                                            {/foreach}
+                                            {/case}
+                                            {case value="select" break="0"}{/case}
+                                            {case value="selects"}
+                                            <select {$item.extend} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
                                                 {foreach name="item.content" item="vo"}
-                                                <label for="row[{$item.name}][]-{$key}"><input id="row[{$item.name}][]-{$key}" name="row[{$item.name}][]" type="checkbox" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value"}checked{/in} /> {$vo}</label>
+                                                <option value="{$key}" {in name="key" value="$item.value" }selected{
+                                                /in}>{$vo}</option>
                                                 {/foreach}
-                                                {/case}
-                                                {case radio}
-                                                {foreach name="item.content" item="vo"}
-                                                <label for="row[{$item.name}]-{$key}"><input id="row[{$item.name}]-{$key}" name="row[{$item.name}]" type="radio" value="{$key}" data-tip="{$item.tip}" {in name="key" value="$item.value"}checked{/in} /> {$vo}</label>
-                                                {/foreach}
-                                                {/case}
-                                                {case value="select" break="0"}{/case}
-                                                {case value="selects"}
-                                                <select {$item.extend} name="row[{$item.name}]{$item.type=='selects'?'[]':''}" class="form-control selectpicker" data-tip="{$item.tip}" {$item.type=='selects'?'multiple':''}>
-                                                    {foreach name="item.content" item="vo"}
-                                                    <option value="{$key}" {in name="key" value="$item.value"}selected{/in}>{$vo}</option>
-                                                    {/foreach}
-                                                </select>
-                                                {/case}
-                                                {case value="image" break="0"}{/case}
-                                                {case value="images"}
-                                                <div class="form-inline">
-                                                    <input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
-                                                    <span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
-                                                    <span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
-                                                    <span class="msg-box n-right" for="c-{$item.name}"></span>
-                                                    <ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
-                                                </div>
-                                                {/case}
-                                                {case value="file" break="0"}{/case}
-                                                {case value="files"}
-                                                <div class="form-inline">
-                                                    <input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
-                                                    <span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
-                                                    <span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
-                                                    <span class="msg-box n-right" for="c-{$item.name}"></span>
-                                                </div>
-                                                {/case}
-                                                {case switch}
-                                                <input id="c-{$item.name}" name="row[{$item.name}]" type="hidden" value="{:$item.value?1:0}">
-                                                <a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name}" data-yes="1" data-no="0" >
-                                                    <i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
-                                                </a>
-                                                {/case}
-                                                {case bool}
-                                                <label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label> 
-                                                <label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
-                                                {/case}
-                                                {/switch}
+                                            </select>
+                                            {/case}
+                                            {case value="image" break="0"}{/case}
+                                            {case value="images"}
+                                            <div class="form-inline">
+                                                <input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
+                                                <span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}" data-preview-id="p-{$item.name}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                                                <span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-mimetype="image/*" data-multiple="{$item.type=='image'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                                                <span class="msg-box n-right" for="c-{$item.name}"></span>
+                                                <ul class="row list-inline plupload-preview" id="p-{$item.name}"></ul>
                                             </div>
-                                            <div class="col-sm-4"></div>
+                                            {/case}
+                                            {case value="file" break="0"}{/case}
+                                            {case value="files"}
+                                            <div class="form-inline">
+                                                <input id="c-{$item.name}" class="form-control" size="50" name="row[{$item.name}]" type="text" value="{$item.value|htmlentities}" data-tip="{$item.tip}">
+                                                <span><button type="button" id="plupload-{$item.name}" class="btn btn-danger plupload" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-upload"></i> {:__('Upload')}</button></span>
+                                                <span><button type="button" id="fachoose-{$item.name}" class="btn btn-primary fachoose" data-input-id="c-{$item.name}" data-multiple="{$item.type=='file'?'false':'true'}"><i class="fa fa-list"></i> {:__('Choose')}</button></span>
+                                                <span class="msg-box n-right" for="c-{$item.name}"></span>
+                                            </div>
+                                            {/case}
+                                            {case switch}
+                                            <input id="c-{$item.name}" name="row[{$item.name}]" type="hidden" value="{:$item.value?1:0}">
+                                            <a href="javascript:;" data-toggle="switcher" class="btn-switcher" data-input-id="c-{$item.name}" data-yes="1" data-no="0">
+                                                <i class="fa fa-toggle-on text-success {if !$item.value}fa-flip-horizontal text-gray{/if} fa-2x"></i>
+                                            </a>
+                                            {/case}
+                                            {case bool}
+                                            <label for="row[{$item.name}]-yes"><input id="row[{$item.name}]-yes" name="row[{$item.name}]" type="radio" value="1" {$item.value?'checked':''} data-tip="{$item.tip}" /> {:__('Yes')}</label>
+                                            <label for="row[{$item.name}]-no"><input id="row[{$item.name}]-no" name="row[{$item.name}]" type="radio" value="0" {$item.value?'':'checked'} data-tip="{$item.tip}" /> {:__('No')}</label>
+                                            {/case}
+                                            {case custom}
+                                            {$item.extend}
+                                            {/case}
+                                            {/switch}
                                         </div>
+                                        <div class="col-sm-4"></div>
+                                    </div>
 
-                                    </td>
-                                    <td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
-                                    <td><a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name}"><i class="fa fa-times"></i></a></td>
-                                </tr>
-                                {/foreach}
+                                </td>
+                                <td>{php}echo "{\$site.". $item['name'] . "}";{/php}</td>
+                                <td><a href="javascript:;" class="btn-delcfg text-muted" data-name="{$item.name}"><i class="fa fa-times"></i></a></td>
+                            </tr>
+                            {/foreach}
                             </tbody>
                             <tfoot>
-                                <tr>
-                                    <td></td>
-                                    <td>
-                                        <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
-                                        <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
-                                    </td>
-                                    <td></td>
-                                    <td></td>
-                                </tr>
+                            <tr>
+                                <td></td>
+                                <td>
+                                    <button type="submit" class="btn btn-success btn-embossed">{:__('OK')}</button>
+                                    <button type="reset" class="btn btn-default btn-embossed">{:__('Reset')}</button>
+                                </td>
+                                <td></td>
+                                <td></td>
+                            </tr>
                             </tfoot>
                         </table>
                     </form>
@@ -153,22 +163,25 @@
             {/foreach}
             <div class="tab-pane fade" id="addcfg">
                 <form id="add-form" class="form-horizontal" role="form" data-toggle="validator" method="POST" action="{:url('general.config/add')}">
+                    {:token()}
                     <div class="form-group">
-                        <label for="type" class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
+                        <label class="control-label col-xs-12 col-sm-2">{:__('Type')}:</label>
                         <div class="col-xs-12 col-sm-4">
                             <select name="row[type]" class="form-control selectpicker">
                                 {foreach name="typeList" item="vo"}
-                                <option value="{$key}" {in name="key" value="string"}selected{/in}>{$vo}</option>
+                                <option value="{$key}" {in name="key" value="string" }selected{
+                                /in}>{$vo}</option>
                                 {/foreach}
                             </select>
                         </div>
                     </div>
                     <div class="form-group">
-                        <label for="group" class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
+                        <label class="control-label col-xs-12 col-sm-2">{:__('Group')}:</label>
                         <div class="col-xs-12 col-sm-4">
                             <select name="row[group]" class="form-control selectpicker">
                                 {foreach name="groupList" item="vo"}
-                                <option value="{$key}" {in name="key" value="basic"}selected{/in}>{$vo}</option>
+                                <option value="{$key}" {in name="key" value="basic" }selected{
+                                /in}>{$vo}</option>
                                 {/foreach}
                             </select>
                         </div>
@@ -176,44 +189,55 @@
                     <div class="form-group">
                         <label for="name" class="control-label col-xs-12 col-sm-2">{:__('Name')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required; length(3~30); remote(general/config/check)" />
+                            <input type="text" class="form-control" id="name" name="row[name]" value="" data-rule="required; length(3~30); remote(general/config/check)"/>
                         </div>
                     </div>
                     <div class="form-group">
                         <label for="title" class="control-label col-xs-12 col-sm-2">{:__('Title')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required" />
+                            <input type="text" class="form-control" id="title" name="row[title]" value="" data-rule="required"/>
                         </div>
                     </div>
                     <div class="form-group">
                         <label for="value" class="control-label col-xs-12 col-sm-2">{:__('Value')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <input type="text" class="form-control" id="value" name="row[value]" value="" data-rule="" />
+                            <input type="text" class="form-control" id="value" name="row[value]" value="" data-rule=""/>
                         </div>
                     </div>
                     <div class="form-group hide" id="add-content-container">
                         <label for="content" class="control-label col-xs-12 col-sm-2">{:__('Content')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <textarea name="row[content]" id="content" cols="30" rows="5" class="form-control" data-rule="required">value1|title1
+                            <textarea name="row[content]" id="content" cols="30" rows="5" class="form-control" data-rule="required(content)">value1|title1
 value2|title2</textarea>
                         </div>
                     </div>
                     <div class="form-group">
                         <label for="tip" class="control-label col-xs-12 col-sm-2">{:__('Tip')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <input type="text" class="form-control" id="tip" name="row[tip]" value="" data-rule="" />
+                            <input type="text" class="form-control" id="tip" name="row[tip]" value="" data-rule=""/>
                         </div>
                     </div>
                     <div class="form-group">
                         <label for="rule" class="control-label col-xs-12 col-sm-2">{:__('Rule')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <input type="text" class="form-control" id="rule" name="row[rule]" value="" />
+                            <div class="input-group pull-left">
+                                <input type="text" class="form-control" id="rule" name="row[rule]" value="" data-tip="{:__('Rule tips')}"/>
+                                <span class="input-group-btn">
+                                    <button class="btn btn-primary dropdown-toggle" data-toggle="dropdown" type="button">{:__('Choose')}</button>
+                                    <ul class="dropdown-menu pull-right rulelist">
+                                        {volist name="ruleList" id="item"}
+                                        <li><a href="javascript:;" data-value="{$key}">{$item}<span class="text-muted">({$key})</span></a></li>
+                                        {/volist}
+                                    </ul>
+                                </span>
+                            </div>
+                            <span class="msg-box n-right" for="rule"></span>
                         </div>
                     </div>
                     <div class="form-group">
                         <label for="extend" class="control-label col-xs-12 col-sm-2">{:__('Extend')}:</label>
                         <div class="col-xs-12 col-sm-4">
-                            <textarea name="row[extend]" id="extend" cols="30" rows="5" class="form-control" data-rule=""></textarea>
+                            <textarea name="row[extend]" id="extend" cols="30" rows="5" class="form-control" data-tip="{:__('Extend tips')}" data-rule="required(extend)" data-msg-extend="当类型为自定义时,扩展属性不能为空"></textarea>
                         </div>
                     </div>
                     <div class="form-group">

+ 10 - 0
application/common/model/Config.php

@@ -72,6 +72,16 @@ class Config extends Model
         return $regexList;
     }
 
+    public function getExtendAttr($value, $data)
+    {
+        $result = preg_replace_callback("/\{([a-zA-Z]+)\}/", function ($matches) use ($data) {
+            if (isset($data[$matches[1]])) {
+                return $data[$matches[1]];
+            }
+        }, $data['extend']);
+        return $result;
+    }
+
     /**
      * 读取分类分组列表
      * @return array

+ 33 - 4
public/assets/js/backend/general/config.js

@@ -51,9 +51,21 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
             Form.api.bindevent($("form.edit-form"));
 
             //不可见的元素不验证
-            $("form#add-form").data("validator-options", {ignore: ':hidden'});
-            Form.api.bindevent($("form#add-form"), null, function (ret) {
-                location.reload();
+            $("form#add-form").data("validator-options", {
+                ignore: ':hidden',
+                rules: {
+                    content: function () {
+                        return ['radio', 'checkbox', 'select', 'selects'].indexOf($("#add-form select[name='row[type]']").val()) > -1;
+                    },
+                    extend: function () {
+                        return $("#add-form select[name='row[type]']").val() == 'custom';
+                    }
+                }
+            });
+            Form.api.bindevent($("form#add-form"), function (ret) {
+                setTimeout(function () {
+                    location.reload();
+                }, 1500);
             });
 
             //切换显示隐藏变量字典列表
@@ -61,6 +73,20 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                 $("#add-content-container").toggleClass("hide", ['select', 'selects', 'checkbox', 'radio'].indexOf($(this).val()) > -1 ? false : true);
             });
 
+            //选择规则
+            $(document).on("click", ".rulelist > li > a", function () {
+                var ruleArr = $("#rule").val() == '' ? [] : $("#rule").val().split(";");
+                var rule = $(this).data("value");
+                var index = ruleArr.indexOf(rule);
+                if (index > -1) {
+                    ruleArr.splice(index, 1);
+                } else {
+                    ruleArr.push(rule);
+                }
+                $("#rule").val(ruleArr.join(";"));
+                $(this).parent().toggleClass("active");
+            });
+
             //添加向发件人发送测试邮件按钮和方法
             $('input[name="row[mail_from]"]').parent().next().append('<a class="btn btn-info testmail">' + __('Send a test message') + '</a>');
             $(document).on("click", ".testmail", function () {
@@ -77,7 +103,10 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
             //删除配置
             $(document).on("click", ".btn-delcfg", function () {
                 var that = this;
-                Layer.confirm(__('Are you sure you want to delete this item?'), {icon: 3, title:'提示'}, function (index) {
+                Layer.confirm(__('Are you sure you want to delete this item?'), {
+                    icon: 3,
+                    title: '提示'
+                }, function (index) {
                     Backend.api.ajax({
                         url: "general/config/del",
                         data: {name: $(that).data("name")}

+ 116 - 97
public/assets/js/require-backend.min.js

@@ -7295,6 +7295,9 @@ define('upload',['jquery', 'bootstrap', 'plupload', 'template'], function ($, un
             elem = el.name && _checkable(el) ? me.$el.find('input[name="'+ el.name +'"]').get(0) : el;
             // Get field
             if (!(field = me.getField(elem)) || !field.rule) {
+                if(!field.rule){
+                    me.hideMsg(el);
+                }
                 return;
             }
             // Cache event type
@@ -9355,7 +9358,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
                     complete: function (xhr) {
                         var token = xhr.getResponseHeader('__token__');
                         if (token) {
-                            $("input[name='__token__']", form).val(token);
+                            $("input[name='__token__']").val(token);
                         }
                     }
                 }, function (data, ret) {
@@ -9363,7 +9366,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
                     if (data && typeof data === 'object') {
                         //刷新客户端token
                         if (typeof data.token !== 'undefined') {
-                            $("input[name='__token__']", form).val(data.token);
+                            $("input[name='__token__']").val(data.token);
                         }
                         //调用客户端事件
                         if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
@@ -9377,7 +9380,7 @@ define('form',['jquery', 'bootstrap', 'upload', 'validator'], function ($, undef
                     }
                 }, function (data, ret) {
                     if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
-                        $("input[name='__token__']", form).val(data.token);
+                        $("input[name='__token__']").val(data.token);
                     }
                     if (typeof error === 'function') {
                         if (false === error.call(form, data, ret)) {
@@ -11365,7 +11368,7 @@ define("addtabs", function(){});
         selectToCloseList: false,
         /**
          * Init selected item key, the result will match to option.keyField option
-         * @type string 
+         * @type string
          */
         initRecord: undefined,
         /**
@@ -11474,7 +11477,7 @@ define("addtabs", function(){});
          * @param data {object} server side return data
          * @param self {object} plugin object
          * @return {object} return data format:
-         * @example 
+         * @example
          * {
          *   list : [{name:'aa',sex:1},{name:'bb',sex:1}...],
          *   totalRow : 100
@@ -11638,7 +11641,7 @@ define("addtabs", function(){});
                     max_selected: 'You can only select up to max_selected_limit items'
                 };
                 break;
-                // 中文
+            // 中文
             case 'cn':
             default:
                 message = {
@@ -11784,7 +11787,7 @@ define("addtabs", function(){});
         restore = function () {
             // restore origin style values
             $hidden.each(function (i) {
-                var $this = $(this), _tmp = tmp[ i ];
+                var $this = $(this), _tmp = tmp[i];
 
                 if (_tmp === undefined)
                     $this.removeAttr('style');
@@ -11798,8 +11801,8 @@ define("addtabs", function(){});
         // it can be 'width', 'height', 'outerWidth', 'innerWidth'... etc
         // configs.includeMargin only works for 'outerWidth' and 'outerHeight'
         var actual = /(outer)/.test(method) ?
-                $target[ method ](configs.includeMargin) :
-                $target[ method ]();
+            $target[method](configs.includeMargin) :
+            $target[method]();
 
         restore();
         // IMPORTANT, this plugin only return the value of the first element
@@ -11813,13 +11816,17 @@ define("addtabs", function(){});
     SelectPage.prototype.setElem = function (combo_input) {
         // 1. build Dom object
         var elem = {}, p = this.option, css = this.css_class, msg = this.message, input = $(combo_input);
+        var cssWidth = input.css("width");
         var orgWidth = input.outerWidth();
-        // fix input width in hidden situation
-        if (orgWidth <= 0)
-            orgWidth = this.elementRealSize(input, 'outerWidth');
-        if (orgWidth < 150)
-            orgWidth = 150;
-
+        if (cssWidth.indexOf("%") > -1 || input.parent().size() > 0 && input.parent().width() == orgWidth) {
+            orgWidth = "100%";
+        } else {
+            // fix input width in hidden situation
+            if (orgWidth <= 0)
+                orgWidth = this.elementRealSize(input, 'outerWidth');
+            if (orgWidth < 150)
+                orgWidth = 150;
+        }
         elem.combo_input = input.attr({'autocomplete': 'off'}).addClass(css.input).wrap('<div>');
         if (p.selectOnly)
             elem.combo_input.prop('readonly', true);
@@ -11854,10 +11861,10 @@ define("addtabs", function(){});
         elem.results = $('<ul>').addClass(css.results);
 
         var namePrefix = '_text',
-                input_id = elem.combo_input.attr('id') || elem.combo_input.attr('name'),
-                input_name = elem.combo_input.attr('name') || 'selectPage',
-                hidden_name = input_name,
-                hidden_id = input_id;
+            input_id = elem.combo_input.attr('id') || elem.combo_input.attr('name'),
+            input_name = elem.combo_input.attr('name') || 'selectPage',
+            hidden_name = input_name,
+            hidden_id = input_id;
 
         //switch the id and name attributes of input/hidden element
         elem.hidden = $('<input type="hidden" class="sp_hidden" />').attr({
@@ -11865,7 +11872,7 @@ define("addtabs", function(){});
             id: hidden_id
         }).val('');
         elem.combo_input.attr({
-            name: input_name + namePrefix,
+            name: typeof input.data('name') !== 'undefined' ? input.data('name') : input_name + namePrefix,
             id: input_id + namePrefix
         });
 
@@ -11961,20 +11968,32 @@ define("addtabs", function(){});
                     data = [data[0]];
                 self.afterInit(self, data);
             } else {//ajax data source mode to init selected item
+                var _paramsFunc = p.params, _params = {}, searchKey = p.searchField;
+                var _orgParams = {
+                    searchTable: p.dbTable,
+                    searchKey: p.keyField,
+                    searchValue: key,
+                    orderBy: p.orderBy,
+                    showField: p.showField,
+                    keyField: p.keyField,
+                    keyValue: key,
+                    searchField: p.searchField
+                };
+                if (_paramsFunc) {
+                    var result = $.isFunction(_paramsFunc) ? _paramsFunc(self) : _paramsFunc;
+                    if (result && $.isPlainObject(result)) {
+                        _params = $.extend({}, _orgParams, result);
+                    } else {
+                        _params = _orgParams;
+                    }
+                } else {
+                    _params = _orgParams;
+                }
                 $.ajax({
                     dataType: 'json',
                     type: 'POST',
                     url: p.data,
-                    data: {
-                        searchTable: p.dbTable,
-                        searchKey: p.keyField,
-                        searchValue: key,
-                        orderBy: p.orderBy,
-                        showField: p.showField,
-                        keyField: p.keyField,
-                        keyValue: key,
-                        searchField: p.searchField
-                    },
+                    data: _params,
                     success: function (json) {
                         var d = null;
                         if (p.eAjaxSuccess && $.isFunction(p.eAjaxSuccess))
@@ -12226,14 +12245,14 @@ define("addtabs", function(){});
         $(window).on('scroll.SelectPage', function (e) {
             $('div.' + css.container + '.' + css.container_open).each(function () {
                 var $this = $(this), d = $this.find('input.' + css.input).data(SelectPage.dataKey),
-                        offset = d.elem.result_area.offset(),
-                        screenScrollTop = $(window).scrollTop(),
-                        docHeight = $(document).height(),
-                        viewHeight = $(window).height(),
-                        listHeight = d.elem.result_area.outerHeight(),
-                        listBottom = offset.top + listHeight,
-                        hasOverflow = docHeight > viewHeight,
-                        down = d.elem.result_area.hasClass('shadowDown');
+                    offset = d.elem.result_area.offset(),
+                    screenScrollTop = $(window).scrollTop(),
+                    docHeight = $(document).height(),
+                    viewHeight = $(window).height(),
+                    listHeight = d.elem.result_area.outerHeight(),
+                    listBottom = offset.top + listHeight,
+                    hasOverflow = docHeight > viewHeight,
+                    down = d.elem.result_area.hasClass('shadowDown');
                 if (hasOverflow) {
                     if (down) {//open down
                         if (listBottom > (viewHeight + screenScrollTop))
@@ -12312,15 +12331,15 @@ define("addtabs", function(){});
      */
     SelectPage.prototype.scrollWindow = function (self, enforce) {
         var current_result = self.getCurrentLine(self),
-                target_top = (current_result && !enforce) ? current_result.offset().top : self.elem.container.offset().top,
-                target_size;
+            target_top = (current_result && !enforce) ? current_result.offset().top : self.elem.container.offset().top,
+            target_size;
 
         self.prop.size_li = self.elem.results.children('li:first').outerHeight();
         target_size = self.prop.size_li;
 
         var gap, client_height = $(window).height(),
-                scroll_top = $(window).scrollTop(),
-                scroll_bottom = scroll_top + client_height - target_size;
+            scroll_top = $(window).scrollTop(),
+            scroll_bottom = scroll_top + client_height - target_size;
         if (current_result.length) {
             if (target_top < scroll_top || target_size > client_height) {
                 //scroll to top
@@ -12419,7 +12438,7 @@ define("addtabs", function(){});
      */
     SelectPage.prototype.processControl = function (self, e) {
         if (($.inArray(e.keyCode, [37, 38, 39, 40, 27, 9]) > -1 && self.elem.result_area.is(':visible')) ||
-                ($.inArray(e.keyCode, [13, 9]) > -1 && self.getCurrentLine(self))) {
+            ($.inArray(e.keyCode, [13, 9]) > -1 && self.getCurrentLine(self))) {
             e.preventDefault();
             e.stopPropagation();
             e.cancelBubble = true;
@@ -12543,14 +12562,15 @@ define("addtabs", function(){});
         };
         _orgParams[searchKey] = q_word[0];
         if (_paramsFunc) {
-            var result = $.isFunction(_paramsFunc) ? _paramsFunc() : _paramsFunc;
+            var result = $.isFunction(_paramsFunc) ? _paramsFunc(self) : _paramsFunc;
             if (result && $.isPlainObject(result)) {
                 _params = $.extend({}, _orgParams, result);
             } else {
                 _params = _orgParams;
             }
-        } else
+        } else {
             _params = _orgParams;
+        }
         self.prop.xhr = $.ajax({
             dataType: 'json',
             url: p.data,
@@ -12571,10 +12591,10 @@ define("addtabs", function(){});
                     self.showMessage(self, self.message.ajax_error);
                     return;
                 }
-                if(self.elem.navi) {
+                if (self.elem.navi) {
                     $(self.elem.navi).toggleClass("hide", json.cnt_whole <= json.originalResult.length);
                 }
-                
+
                 json.candidate = [];
                 json.keyField = [];
                 if (typeof json.originalResult != 'object') {
@@ -12648,8 +12668,8 @@ define("addtabs", function(){});
 
         // (CASE WHEN ...) then く order some column
         var reg1 = new RegExp('^' + esc_q[0] + '$', 'gi'),
-                reg2 = new RegExp('^' + esc_q[0], 'gi'),
-                matched1 = [], matched2 = [], matched3 = [];
+            reg2 = new RegExp('^' + esc_q[0], 'gi'),
+            matched1 = [], matched2 = [], matched3 = [];
         for (i = 0; i < matched.length; i++) {
             var orderField = p.orderBy[0][0];
             var orderValue = String(matched[i][orderField]);
@@ -12818,9 +12838,9 @@ define("addtabs", function(){});
             if (pagebar.find('li').size() === 0) {
                 pagebar.hide().empty();
                 var iconFist = 'spfont sp-first',
-                        iconPrev = 'spfont sp-previous',
-                        iconNext = 'spfont sp-next',
-                        iconLast = 'spfont sp-last';
+                    iconPrev = 'spfont sp-previous',
+                    iconNext = 'spfont sp-next',
+                    iconLast = 'spfont sp-last';
 
                 pagebar.append('<li class="csFirstPage" title="' + msg.first_title + '" ><a href="javascript:void(0);"> <i class="' + iconFist + '"></i> </a></li>');
                 pagebar.append('<li class="csPreviousPage" title="' + msg.prev_title + '" ><a href="javascript:void(0);"><i class="' + iconPrev + '"></i></a></li>');
@@ -12836,7 +12856,7 @@ define("addtabs", function(){});
         };
 
         var pagebar = self.elem.navi.find('ul'),
-                last_page = Math.ceil(cnt_whole / self.option.pageSize); //calculate total page
+            last_page = Math.ceil(cnt_whole / self.option.pageSize); //calculate total page
         if (last_page === 0)
             page_num = 0;
         else {
@@ -12851,10 +12871,10 @@ define("addtabs", function(){});
 
         //update paging status
         var dClass = 'disabled',
-                first = pagebar.find('li.csFirstPage'),
-                previous = pagebar.find('li.csPreviousPage'),
-                next = pagebar.find('li.csNextPage'),
-                last = pagebar.find('li.csLastPage');
+            first = pagebar.find('li.csFirstPage'),
+            previous = pagebar.find('li.csPreviousPage'),
+            next = pagebar.find('li.csNextPage'),
+            last = pagebar.find('li.csLastPage');
         //first and previous
         if (page_num === 1 || page_num === 0) {
             if (!first.hasClass(dClass))
@@ -12904,10 +12924,10 @@ define("addtabs", function(){});
 
         if (json.candidate.length) {
             var arr_candidate = json.candidate,
-                    arr_primary_key = json.keyField,
-                    keystr = el.hidden.val(),
-                    keyArr = keystr ? keystr.split(',') : new Array(),
-                    itemText = '';
+                arr_primary_key = json.keyField,
+                keystr = el.hidden.val(),
+                keyArr = keystr ? keystr.split(',') : new Array(),
+                itemText = '';
             for (var i = 0; i < arr_candidate.length; i++) {
                 if (p.formatItem && $.isFunction(p.formatItem)) {
                     try {
@@ -12934,7 +12954,7 @@ define("addtabs", function(){});
             }
         } else {
             var li = '<li class="' + self.css_class.message_box + '"><i class="spfont sp-warning"></i> ' +
-                    self.message.not_found + '</li>';
+                self.message.not_found + '</li>';
             el.results.append(li);
         }
         el.results.show();
@@ -12972,7 +12992,7 @@ define("addtabs", function(){});
             } else {
                 if (!p.pagination) {
                     var itemHeight = el.results.find('li:first').outerHeight(true),
-                            listHeight = itemHeight * p.listSize;
+                        listHeight = itemHeight * p.listSize;
                     el.results.css({
                         'max-height': listHeight,
                         'overflow-y': 'auto'
@@ -12981,30 +13001,30 @@ define("addtabs", function(){});
 
                 //handle result list show up side(left, right, up or down)
                 var docWidth = $(document).width(),
-                        docHeight = $(document).height(), //the document full height
-                        viewHeight = $(window).height(), //browser visible area height
-                        offset = el.container.offset(),
-                        screenScrollTop = $(window).scrollTop(),
-                        listWidth = el.result_area.outerWidth(),
-                        //result list height
-                        listHeight = el.result_area.outerHeight(),
-                        //default left used input element left
-                        defaultLeft = offset.left, //p.multiple ? -1 : 0;
-                        //input element height
-                        inputHeight = el.container.outerHeight(),
-                        left = (offset.left + listWidth) > docWidth ?
+                    docHeight = $(document).height(), //the document full height
+                    viewHeight = $(window).height(), //browser visible area height
+                    offset = el.container.offset(),
+                    screenScrollTop = $(window).scrollTop(),
+                    listWidth = el.result_area.outerWidth(),
+                    //result list height
+                    listHeight = el.result_area.outerHeight(),
+                    //default left used input element left
+                    defaultLeft = offset.left, //p.multiple ? -1 : 0;
+                    //input element height
+                    inputHeight = el.container.outerHeight(),
+                    left = (offset.left + listWidth) > docWidth ?
                         defaultLeft - (listWidth - el.container.outerWidth()) :
                         defaultLeft,
-                        //the actual top coordinate of input element(outer div)
-                        screenTop = offset.top, //$(el.container).scrollTop();//offset.top - screenScrollTop;
-                        top = 0, dist = 5, //set distance between input element and result list
-                        //the actual top coordinate of result list
-                        listBottom = screenTop + inputHeight + listHeight + dist,
-                        hasOverflow = docHeight > viewHeight;
+                    //the actual top coordinate of input element(outer div)
+                    screenTop = offset.top, //$(el.container).scrollTop();//offset.top - screenScrollTop;
+                    top = 0, dist = 5, //set distance between input element and result list
+                    //the actual top coordinate of result list
+                    listBottom = screenTop + inputHeight + listHeight + dist,
+                    hasOverflow = docHeight > viewHeight;
 
                 if ((screenTop - screenScrollTop - dist > listHeight) &&
-                        (hasOverflow && listBottom > (viewHeight + screenScrollTop)) ||
-                        (!hasOverflow && listBottom > viewHeight)) {
+                    (hasOverflow && listBottom > (viewHeight + screenScrollTop)) ||
+                    (!hasOverflow && listBottom > viewHeight)) {
                     //open up
                     top = offset.top - listHeight - dist;
                     el.result_area.removeClass('shadowUp shadowDown').addClass('shadowUp');
@@ -13205,8 +13225,8 @@ define("addtabs", function(){});
             jsonarr.push($row.data('dataObj'));
             //limited max selected items
             if ($.type(p.maxSelectLimit) === 'number' &&
-                    p.maxSelectLimit > 0 &&
-                    p.maxSelectLimit === self.elem.element_box.find('li.selected_tag').size()) {
+                p.maxSelectLimit > 0 &&
+                p.maxSelectLimit === self.elem.element_box.find('li.selected_tag').size()) {
                 return false;
             }
         });
@@ -13319,7 +13339,7 @@ define("addtabs", function(){});
         var keys = self.elem.hidden.val();
         if ($.type(key) != 'undefined' && keys) {
             var keyarr = keys.split(','),
-                    index = $.inArray(key.toString(), keyarr);
+                index = $.inArray(key.toString(), keyarr);
             if (index != -1) {
                 keyarr.splice(index, 1);
                 self.elem.hidden.val(keyarr.toString());
@@ -13358,11 +13378,11 @@ define("addtabs", function(){});
         if (!self.option.multiple)
             return;
         var width = '',
-                inputLi = self.elem.combo_input.closest('li');
+            inputLi = self.elem.combo_input.closest('li');
         var setDefaultSize = function (self, inputLi) {
             inputLi.removeClass('full_width');
             var minimumWidth = self.elem.combo_input.val().length + 1,
-                    width = (minimumWidth * 0.75) + 'em';
+                width = (minimumWidth * 0.75) + 'em';
             self.elem.combo_input.css('width', width).removeAttr('placeholder');
         };
         if (self.elem.element_box.find('li.selected_tag').size() === 0) {
@@ -13429,8 +13449,8 @@ define("addtabs", function(){});
     function Plugin(option) {
         return this.each(function () {
             var $this = $(this),
-                    data = $this.data(SelectPage.dataKey),
-                    params = $.extend({}, defaults, $this.data(), data && data.option, typeof option === 'object' && option);
+                data = $this.data(SelectPage.dataKey),
+                params = $.extend({}, defaults, $this.data(), data && data.option, typeof option === 'object' && option);
             if (!data)
                 $this.data(SelectPage.dataKey, (data = new SelectPage(this, params)));
         });
@@ -13438,8 +13458,8 @@ define("addtabs", function(){});
 
     /**
      * Get plugin object
-     * @param {object} obj 
-     * @returns 
+     * @param {object} obj
+     * @returns
      */
     function getPlugin(obj) {
         return $(obj).closest('div.sp_container').find('input.sp_input');
@@ -13451,7 +13471,7 @@ define("addtabs", function(){});
     function ClearSelected() {
         return this.each(function () {
             var $this = getPlugin(this),
-                    data = $this.data(SelectPage.dataKey);
+                data = $this.data(SelectPage.dataKey);
             if (data) {
                 data.prop.init_set = true;
                 data.clearAll(data);
@@ -13469,7 +13489,7 @@ define("addtabs", function(){});
     function SelectedRefresh() {
         return this.each(function () {
             var $this = getPlugin(this),
-                    data = $this.data(SelectPage.dataKey);
+                data = $this.data(SelectPage.dataKey);
             if (data && data.elem.hidden.val())
                 data.setInitRecord(true);
         });
@@ -13485,7 +13505,7 @@ define("addtabs", function(){});
         return this.each(function () {
             if (data && $.isArray(data)) {
                 var $this = getPlugin(this),
-                        plugin = $this.data(SelectPage.dataKey);
+                    plugin = $this.data(SelectPage.dataKey);
                 if (plugin) {
                     plugin.clearAll(plugin);
                     plugin.option.data = data;
@@ -13502,7 +13522,7 @@ define("addtabs", function(){});
         var status = false;
         this.each(function () {
             var $this = getPlugin(this),
-                    plugin = $this.data(SelectPage.dataKey);
+                plugin = $this.data(SelectPage.dataKey);
             if (plugin) {
                 if ($.type(disabled) !== 'undefined')
                     plugin.disabled(plugin, disabled);
@@ -13553,6 +13573,5 @@ define("addtabs", function(){});
         return this;
     };
 })(window.jQuery);
-
 define("selectpage", function(){});
 

+ 3 - 3
public/assets/js/require-form.js

@@ -431,7 +431,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
                     complete: function (xhr) {
                         var token = xhr.getResponseHeader('__token__');
                         if (token) {
-                            $("input[name='__token__']", form).val(token);
+                            $("input[name='__token__']").val(token);
                         }
                     }
                 }, function (data, ret) {
@@ -439,7 +439,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
                     if (data && typeof data === 'object') {
                         //刷新客户端token
                         if (typeof data.token !== 'undefined') {
-                            $("input[name='__token__']", form).val(data.token);
+                            $("input[name='__token__']").val(data.token);
                         }
                         //调用客户端事件
                         if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
@@ -453,7 +453,7 @@ define(['jquery', 'bootstrap', 'upload', 'validator'], function ($, undefined, U
                     }
                 }, function (data, ret) {
                     if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
-                        $("input[name='__token__']", form).val(data.token);
+                        $("input[name='__token__']").val(data.token);
                     }
                     if (typeof error === 'function') {
                         if (false === error.call(form, data, ret)) {