vr-shopxo-plugin/shopxo/app/module/FormTableHandleModule.php

2204 lines
96 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
// | Copyright (c) 2011~2099 http://shopxo.net All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( https://opensource.org/licenses/mit-license.php )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\module;
use think\facade\Db;
use app\service\FormTableService;
use app\service\ResourcesService;
use app\service\UserService;
use app\service\GoodsService;
/**
* 动态表格处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-02
* @desc description
*/
class FormTableHandleModule
{
// 模块对象
public $module_obj;
// form 配置数据
public $form_data;
// 外部参数
public $out_params;
// 条件参数
public $where_params;
// md5key
public $md5_key;
// 搜索条件
public $where;
// 用户选择字段字段
public $user_fields;
// 排序
public $order_by;
// 自定义属性条件
public $condition_base_where;
// 钩子名称
public $hook_name;
// 当前系统操作名称
public $module_name;
public $controller_name;
public $action_name;
// 当前插件操作名称
public $plugins_module_name;
public $plugins_controller_name;
public $plugins_action_name;
// 分页信息
public $page;
public $page_start;
public $page_size;
public $page_total;
public $page_html;
public $page_url;
// 数据db
public $db;
// 列表数据及详情
public $data_total;
public $data_list;
public $data_detail;
// 是否导出excel
public $is_export_excel;
/**
* 运行入口
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-02
* @desc description
* @param [string] $module [模块位置]
* @param [string] $action [模块方法(默认 Index/Run 方法,可自动匹配控制器方法名)]
* @param [mixed] $params [参数数据]
*/
public function Run($module, $action = 'Index', $params = [])
{
// 参数校验
$ret = $this->ParamsCheckHandle($module, $action, $params);
if($ret['code'] != 0)
{
return $ret;
}
// 钩子-开始
$hv = explode('\\', $module);
if(isset($hv[2]))
{
$this->hook_name = '';
if($hv[2] == 'plugins')
{
if(isset($hv[3]) && isset($hv[5]) && isset($hv[6]))
{
// 初始-动态钩子名称 plugins_module_form_{group}_plugins_{plugins}_{controller}_{action}
$this->hook_name = 'plugins_module_form_'.strtolower($hv[5]).'_plugins_'.strtolower($hv[3]).'_'.strtolower($hv[6]).'_'.strtolower($action);
}
} else {
if(isset($hv[4]))
{
// 初始-动态钩子名称 plugins_module_form_{group}_{controller}_{action}
$this->hook_name = 'plugins_module_form_'.strtolower($hv[2]).'_'.strtolower($hv[4]).'_'.strtolower($action);
}
}
if(!empty($this->hook_name))
{
MyEventTrigger($this->hook_name, [
'hook_name' => $this->hook_name,
'is_backend' => true,
'params' => $this->out_params,
'data' => &$this->form_data,
]);
}
}
// 初始化
$this->Init();
// md5key
$this->FromMd5Key($module, $action);
// 基础条件
$this->BaseWhereHandle();
// 表格配置处理
$this->FormConfigHandle();
// 基础数据结尾处理
$this->FormBaseLastHandle();
// 用户字段选择处理
$this->FormFieldsUserSelect();
// 排序字段处理
$this->FormOrderByHandle();
// 数据前-动态钩子名称 plugins_module_form_group_controller_action_data_begin
if(!empty($this->hook_name))
{
$hook_name = $this->hook_name.'_data_begin';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => $this->out_params,
'table' => $this->form_data,
'order_by' => &$this->order_by,
'where' => &$this->where,
]);
}
// 数据读取
$this->FormDataListQuery();
// 数据列表处理
$this->FormDataListHandle();
// 数据后-动态钩子名称 plugins_module_form_group_controller_action_data_end
if(!empty($this->hook_name))
{
$hook_name = $this->hook_name.'_data_end';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => $this->out_params,
'table' => $this->form_data,
'order_by' => $this->order_by,
'where' => $this->where,
'page' => &$this->page,
'page_start' => &$this->page_start,
'page_size' => &$this->page_size,
'page_total' => &$this->page_total,
'data_total' => &$this->data_total,
'data_list' => &$this->data_list,
'data_detail' => &$this->data_detail,
]);
}
// 导出excel处理
$this->FormDataExportExcelHandle();
// 数据返回
$data = [
'table' => $this->form_data,
'where' => $this->where,
'params' => $this->where_params,
'md5_key' => $this->md5_key,
'user_fields' => $this->user_fields,
'order_by' => $this->order_by,
'page' => $this->page,
'page_start' => $this->page_start,
'page_size' => $this->page_size,
'page_total' => $this->page_total,
'page_url' => $this->page_url,
'page_html' => $this->page_html,
'data_total' => $this->data_total,
'data_list' => $this->data_list,
'data_detail' => $this->data_detail,
];
// 钩子-结束
if(!empty($this->hook_name))
{
// 动态钩子名称 plugins_module_form_group_controller_action_end
$hook_name = $this->hook_name.'_end';
MyEventTrigger($hook_name, [
'hook_name' => $hook_name,
'is_backend' => true,
'params' => $this->out_params,
'data' => &$data,
]);
}
return DataReturn('success', 0, $data);
}
/**
* 参数校验
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-12-06
* @desc description
* @param [string] $module [模块位置]
* @param [string] $action [模块方法(默认 Run 方法,可自动匹配控制器方法名)]
* @param [mixed] $params [参数数据]
*/
public function ParamsCheckHandle($module, $action, $params)
{
// 参数
$this->out_params = $params;
// 模块是否存在
if(!class_exists($module))
{
return DataReturn('表格模块未定义['.$module.']', -1);
}
// 指定方法检测
$this->module_obj = new $module($this->out_params);
if(!method_exists($this->module_obj, $action))
{
// 默认方法检测
$action = 'Run';
if(!method_exists($this->module_obj, $action))
{
return DataReturn('表格方法未定义['.$module.'->'.$action.'()]', -1);
}
}
// 获取表格配置数据
$this->form_data = $this->module_obj->$action($this->out_params);
if(empty($this->form_data['base']) || !is_array($this->form_data['base']) || empty($this->form_data['form']) || !is_array($this->form_data['form']))
{
return DataReturn('表格配置有误['.$module.'][base|form]', -1);
}
// 数据唯一主字段
if(empty($this->form_data['base']['key_field']))
{
return DataReturn('表格唯一字段配置有误['.$module.']base->[key_field]', -1);
}
// 是否上下居中0否,1是默认1
if(!isset($this->form_data['base']['is_middle']))
{
$this->form_data['base']['is_middle'] = 1;
}
return DataReturn('success', 0);
}
/**
* 初始化
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-10-29
* @desc description
*/
public function Init()
{
// 排序
$this->order_by['key'] = empty($this->out_params['fp_order_by_key']) ? (empty($this->out_params['order_by_key']) ? '' : $this->out_params['order_by_key']) : $this->out_params['fp_order_by_key'];
$this->order_by['val'] = empty($this->out_params['fp_order_by_val']) ? (empty($this->out_params['order_by_val']) ? '' : $this->out_params['order_by_val']) : $this->out_params['fp_order_by_val'];
$this->order_by['field'] = '';
$this->order_by['data'] = '';
// 分页信息
$this->page = max(1, isset($this->out_params['page']) ? intval($this->out_params['page']) : 1);
$this->page_size = min(empty($this->out_params['page_size']) ? MyC('common_page_size', 10, true) : intval($this->out_params['page_size']), 1000);
// 当前系统操作名称、是否指定模块
$this->module_name = empty($this->out_params['module_name']) ? RequestModule() : $this->out_params['module_name'];
$this->controller_name = empty($this->out_params['controller_name']) ? RequestController() : $this->out_params['controller_name'];
$this->action_name = empty($this->out_params['action_name']) ? RequestAction() : $this->out_params['action_name'];
// 是否开启删除
$is_delete = isset($this->form_data['base']['is_delete']) && $this->form_data['base']['is_delete'] == 1;
// 是否开启全部删除
$is_alldelete = isset($this->form_data['base']['is_alldelete']) && $this->form_data['base']['is_alldelete'] == 1;
// 删除数据key默认ids
if($is_delete && empty($this->form_data['base']['delete_key']))
{
$this->form_data['base']['delete_key'] = 'ids';
}
// 当前插件操作名称, 兼容插件模块名称
if(empty($this->out_params['pluginsname']))
{
// 默认插件模块赋空值
$this->plugins_module_name = '';
$this->plugins_controller_name = '';
$this->plugins_action_name = '';
// 当前页面地址
$this->page_url = MyUrl($this->module_name.'/'.$this->controller_name.'/'.$this->action_name);
// 已开启删除功能未配置删除数据地址
if($is_delete && empty($this->form_data['base']['delete_url']))
{
$this->form_data['base']['delete_url'] = MyUrl($this->module_name.'/'.$this->controller_name.'/delete');
}
// 已开启全部删除功能未配置删除数据地址
if($is_alldelete && empty($this->form_data['base']['alldelete_url']))
{
$this->form_data['base']['alldelete_url'] = MyUrl($this->module_name.'/'.$this->controller_name.'/alldelete');
}
} else {
// 处理插件页面模块
$this->plugins_module_name = $this->out_params['pluginsname'];
$this->plugins_controller_name = empty($this->out_params['pluginscontrol']) ? 'index' : $this->out_params['pluginscontrol'];
$this->plugins_action_name = empty($this->out_params['pluginsaction']) ? 'index' : $this->out_params['pluginsaction'];
// 当前页面地址
if($this->module_name == 'admin')
{
$this->page_url = PluginsAdminUrl($this->plugins_module_name, $this->plugins_controller_name, $this->plugins_action_name);
} else {
$this->page_url = PluginsHomeUrl($this->plugins_module_name, $this->plugins_controller_name, $this->plugins_action_name);
}
// 已开启删除功能未配置删除数据地址
if($is_delete && empty($this->form_data['base']['delete_url']))
{
if($this->module_name == 'admin')
{
$this->form_data['base']['delete_url'] = PluginsAdminUrl($this->plugins_module_name, $this->plugins_controller_name, 'delete');
} else {
$this->form_data['base']['delete_url'] = PluginsHomeUrl($this->plugins_module_name, $this->plugins_controller_name, 'delete');
}
}
// 已开启全部删除功能未配置删除数据地址
if($is_alldelete && empty($this->form_data['base']['alldelete_url']))
{
if($this->module_name == 'admin')
{
$this->form_data['base']['alldelete_url'] = PluginsAdminUrl($this->plugins_module_name, $this->plugins_controller_name, 'alldelete');
} else {
$this->form_data['base']['alldelete_url'] = PluginsHomeUrl($this->plugins_module_name, $this->plugins_controller_name, 'alldelete');
}
}
}
// 是否开启搜索
if(isset($this->form_data['base']['is_search']) && $this->form_data['base']['is_search'] == 1)
{
// 是否设置搜索重置链接
if(empty($this->form_data['base']['search_url']))
{
$this->form_data['base']['search_url'] = $this->page_url;
}
}
// 是否导出excel
$this->is_export_excel = (isset($this->out_params['form_table_is_export_excel']) && $this->out_params['form_table_is_export_excel'] == 1);
// 是否定义基础条件属性
$this->condition_base_where = (property_exists($this->module_obj, 'condition_base') && is_array($this->module_obj->condition_base)) ? $this->module_obj->condition_base : [];
}
/**
* 数据读取
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-01
* @desc description
*/
public function FormDataListQuery()
{
// 已定义读取数据配置,指定读取数据、未指定则默认读取
if(!empty($this->form_data['data']) && (!isset($this->out_params['is_data_query']) || $this->out_params['is_data_query'] == 1))
{
$form_data = $this->form_data['data'];
// 基础数据
$base = $this->FormDataBase($form_data);
// 非列表和详情则不处理
if(!$base['is_list'] && !$base['is_detail'])
{
return false;
}
// 数据库对象
$this->db = null;
if(!empty($form_data['table_obj']) && is_object($form_data['table_obj']))
{
$this->db = $form_data['table_obj'];
} elseif(!empty($form_data['table_name']))
{
$this->db = Db::name($form_data['table_name']);
}
if($this->db === null)
{
return false;
}
// 读取字段
$select_field = empty($form_data['select_field']) ? '*' : $form_data['select_field'];
$this->db->field($select_field);
// 数据读取
if($base['is_list'])
{
// 加入条件
$this->db->where($this->where);
// 总数
// 是否去重
if(empty($form_data['distinct']))
{
$this->data_total = (int) $this->db->count();
} else {
$this->data_total = (int) $this->db->count('DISTINCT '.$form_data['distinct']);
}
if($this->data_total > 0)
{
// 分页总数、分页不能大于总数
$this->page_total = ceil($this->data_total/$this->page_size);
if($this->page > $this->page_total)
{
$this->page = $this->page_total;
}
// 增加排序、未设置则默认[ id desc ]
$order_by = empty($this->order_by['data']) ? (array_key_exists('order_by', $form_data) ? $form_data['order_by'] : 'id desc') : $this->order_by['data'];
if(!empty($order_by))
{
$this->db->order($order_by);
}
// 分组
if(!empty($form_data['group']))
{
$this->db->group($form_data['group']);
}
// 增加分页
if($base['is_page'] && !$this->is_export_excel)
{
$this->page_start = intval(($this->page-1)*$this->page_size);
$this->db->limit($this->page_start, $this->page_size);
}
// 读取数据
$this->data_list = $this->db->select()->toArray();
}
} else {
// 详情不走列表的条件模式
// 1. 传入外部条件和指定详情条件
// 2. 合并指定的属性条件
$this->where = array_merge($this->condition_base_where, empty($this->out_params['detail_where']) ? ((!empty($form_data['detail_where']) && is_array($form_data['detail_where'])) ? $form_data['detail_where'] : []) : $this->out_params['detail_where']);
// 单独处理条件
$detail_dkey = empty($this->out_params['detail_dkey']) ? (empty($form_data['detail_dkey']) ? 'id' : $form_data['detail_dkey']) : $this->out_params['detail_dkey'];
$detail_pkey = empty($this->out_params['detail_pkey']) ? (empty($form_data['detail_pkey']) ? 'id' : $form_data['detail_pkey']) : $this->out_params['detail_pkey'];
$value = empty($this->out_params[$detail_pkey]) ? 0 : $this->out_params[$detail_pkey];
$this->where[] = [$detail_dkey, '=', $value];
$this->db->where($this->where);
// 读取数据、仅读取一条
$this->data_list = $this->db->limit(0, 1)->select()->toArray();
}
}
}
/**
* 数据列表处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-01
* @desc description
*/
public function FormDataListHandle()
{
if(!empty($this->data_list))
{
// 表单配置数据
$form_data = empty($this->form_data['data']) ? [] : $this->form_data['data'];
// 基础数据
$base = $this->FormDataBase($form_data);
// 数据处理
// 合并数据
$data_merge = (!empty($form_data['data_merge']) && is_array($form_data['data_merge'])) ? $form_data['data_merge'] : [];
// 是否处理用户数据
$is_handle_user_field = isset($form_data['is_handle_user_field']) && $form_data['is_handle_user_field'] == 1;
$handle_user_data = [];
$handle_user_ids = [];
if(empty($form_data['handle_user_data']))
{
$handle_user_data[] = [
'key' => 'user_id',
'field' => 'user',
];
$handle_user_ids = array_unique(array_filter(array_column($this->data_list, 'user_id')));
} else {
if(is_array($form_data['handle_user_data']))
{
foreach($form_data['handle_user_data'] as $uv)
{
if(!empty($uv['key']))
{
if(empty($uv['field']))
{
$temp_user_field = (substr($uv['key'], -3) == '_id') ? substr($uv['key'], 0, -3) : $uv['key'].'_user';
} else {
$temp_user_field = $uv['field'];
}
$handle_user_data[] = [
'key' => $uv['key'],
'field' => $temp_user_field,
];
$handle_user_ids = array_unique(array_merge($handle_user_ids, array_filter(array_column($this->data_list, $uv['key']))));
}
}
}
}
// 是否处理地区数据
$is_handle_region_field = isset($form_data['is_handle_region_field']) && $form_data['is_handle_region_field'] == 1;
$handle_region_data = [];
$handle_region_ids = [];
if(empty($form_data['handle_region_data']))
{
$handle_region_data = [
[
'key' => 'province',
'field' => 'province_name',
],
[
'key' => 'city',
'field' => 'city_name',
],
[
'key' => 'county',
'field' => 'county_name',
],
[
'key' => 'province_id',
'field' => 'province_name',
],
[
'key' => 'city_id',
'field' => 'city_name',
],
[
'key' => 'county_id',
'field' => 'county_name',
],
];
foreach($handle_region_data as $rv)
{
$handle_region_ids = array_unique(array_merge($handle_region_ids, array_filter(array_column($this->data_list, $rv['key']))));
}
} else {
if(is_array($form_data['handle_region_data']))
{
foreach($form_data['handle_region_data'] as $rv)
{
if(!empty($rv['key']))
{
if(empty($rv['field']))
{
$temp_region_field = ((substr($rv['key'], -3) == '_id') ? substr($rv['key'], 0, -3) : $rv['key']).'_name';
} else {
$temp_region_field = $rv['field'];
}
$handle_region_data[] = [
'key' => $rv['key'],
'field' => $temp_region_field,
];
$handle_region_ids = array_unique(array_merge($handle_region_ids, array_filter(array_column($this->data_list, $rv['key']))));
}
}
}
}
// 是否处理商品数据
$is_handle_goods_field = isset($form_data['is_handle_goods_field']) && $form_data['is_handle_goods_field'] == 1;
$handle_goods_data = [];
$handle_goods_ids = [];
if(empty($form_data['handle_goods_data']))
{
$handle_goods_data[] = [
'key' => 'goods_id',
'field' => 'goods',
];
$handle_goods_ids = array_unique(array_filter(array_column($this->data_list, 'goods_id')));
} else {
if(is_array($form_data['handle_goods_data']))
{
foreach($form_data['handle_goods_data'] as $gv)
{
if(!empty($gv['key']))
{
if(empty($gv['field']))
{
$temp_goods_field = (substr($gv['key'], -3) == '_id') ? substr($gv['key'], 0, -3) : $gv['key'].'_goods';
} else {
$temp_goods_field = $gv['field'];
}
$handle_goods_data[] = [
'key' => $gv['key'],
'field' => $temp_goods_field,
];
$handle_goods_ids = array_unique(array_merge($handle_goods_ids, array_filter(array_column($this->data_list, $gv['key']))));
}
}
}
}
// 时间字段和格式
$is_handle_time_field = isset($form_data['is_handle_time_field']) && $form_data['is_handle_time_field'] == 1;
$handle_time_format = empty($form_data['handle_time_format']) ? '' : $form_data['handle_time_format'];
// 固定值名称
$is_fixed_name_field = isset($form_data['is_fixed_name_field']) && $form_data['is_fixed_name_field'] == 1;
$fixed_name_data = empty($form_data['fixed_name_data']) ? [] : $form_data['fixed_name_data'];
// 附件字段
$is_handle_annex_field = isset($form_data['is_handle_annex_field']) && $form_data['is_handle_annex_field'] == 1;
$handle_annex_fields = empty($form_data['handle_annex_fields']) ? ['avatar', 'cover', 'logo', 'icon', 'images', 'images_url', 'video', 'video_url'] : (is_array($form_data['handle_annex_fields']) ? $form_data['handle_annex_fields'] : explode(',', $form_data['handle_annex_fields']));
// 附件字节转单位
$is_handle_annex_size_unit = isset($form_data['is_handle_annex_size_unit']) && $form_data['is_handle_annex_size_unit'] == 1;
$handle_annex_size_unit_fields = empty($form_data['handle_annex_size_unit_fields']) ? ['size', 'file_size', 'images_size', 'image_size', 'video_size'] : (is_array($form_data['handle_annex_size_unit_fields']) ? $form_data['handle_annex_size_unit_fields'] : explode(',', $form_data['handle_annex_size_unit_fields']));
// json数据
$is_json_data_handle = isset($form_data['is_json_data_handle']) && $form_data['is_json_data_handle'] == 1;
$json_config_data = empty($form_data['json_config_data']) ? [] : $form_data['json_config_data'];
// 换行数据转数组
$is_ln_to_array_handle = isset($form_data['is_ln_to_array_handle']) && $form_data['is_ln_to_array_handle'] == 1;
$ln_to_array_fields = empty($form_data['ln_to_array_fields']) ? [] : $form_data['ln_to_array_fields'];
// 1. 展示字段指定数组转换处理
// 2. 状态字段按照搜索列表转换处理
$field_show_data = [];
$field_status_data = [];
foreach($this->form_data['form'] as $fv)
{
switch($fv['view_type'])
{
// 展示字段
case 'field' :
if(!empty($fv['view_data']))
{
$field_show_data[$fv['view_key']] = $fv;
}
break;
// 状态字段
case 'status' :
if(!empty($fv['search_config']) && !empty($fv['search_config']['data']))
{
$field_status_data[$fv['view_key']] = $fv;
}
break;
}
}
// 数据处理
if(!empty($field_show_data) || !empty($field_status_data) || !empty($data_merge) || $is_handle_user_field || $is_handle_region_field || $is_handle_goods_field || $is_handle_time_field || $is_fixed_name_field || $is_handle_annex_field || $is_handle_annex_size_unit || $is_json_data_handle || $is_ln_to_array_handle)
{
// 获取用户数据
$user_data = [];
if($is_handle_user_field && !empty($handle_user_ids))
{
$user_data = UserService::GetUserViewInfo($handle_user_ids);
}
// 获取地区数据
$region_data = [];
if($is_handle_region_field && !empty($handle_region_ids))
{
$region_data = Db::name('Region')->where(['id'=>$handle_region_ids])->column('name', 'id');
}
// 获取商品数据
$goods_data = [];
if($is_handle_goods_field && !empty($handle_goods_ids))
{
$goods_data = Db::name('Goods')->where(['id'=>$handle_goods_ids])->column('id,title,images,price,min_price,max_price,original_price,min_original_price,max_original_price,inventory,inventory_unit', 'id');
if(!empty($goods_data))
{
$goods_data = array_map(function($item)
{
$item['goods_url'] = GoodsService::GoodsUrlCreate($item['id']);
$item['images'] = ResourcesService::AttachmentPathViewHandle($item['images']);
return $item;
}, $goods_data);
}
}
// 处理列表数据
foreach($this->data_list as &$v)
{
if(!empty($v) && is_array($v))
{
// 合并数据
if(!empty($data_merge))
{
$v = array_merge($v, $data_merge);
}
// 用户信息处理
if($is_handle_user_field && !empty($handle_user_data))
{
foreach($handle_user_data as $uv)
{
if(!empty($uv['key']) && !empty($uv['field']) && array_key_exists($uv['key'], $v))
{
$v[$uv['field']] = (empty($user_data) || empty($v[$uv['key']]) || !array_key_exists($v[$uv['key']], $user_data)) ? null : $user_data[$v[$uv['key']]];
}
}
}
// 地区处理
if($is_handle_region_field && !empty($handle_region_data))
{
foreach($handle_region_data as $rv)
{
if(!empty($rv['key']) && !empty($rv['field']) && array_key_exists($rv['key'], $v))
{
$v[$rv['field']] = (empty($region_data) || empty($v[$rv['key']]) || !array_key_exists($v[$rv['key']], $region_data)) ? null : $region_data[$v[$rv['key']]];
}
}
}
// 商品信息处理
if($is_handle_goods_field && !empty($handle_goods_data))
{
foreach($handle_goods_data as $gv)
{
if(!empty($gv['key']) && !empty($gv['field']) && array_key_exists($gv['key'], $v))
{
$v[$gv['field']] = (empty($goods_data) || empty($v[$gv['key']]) || !array_key_exists($v[$gv['key']], $goods_data)) ? null : $goods_data[$v[$gv['key']]];
}
}
}
// 其他单独字段数据处理
foreach($v as $ks=>&$vs)
{
// json数据处理
if($is_json_data_handle && !empty($json_config_data) && array_key_exists($ks, $json_config_data) && !empty($vs) && !is_array($vs))
{
$temp_json_data = json_decode($vs, true);
if(!empty($temp_json_data))
{
// 是否为附件处理地址
$temm_json_config = $json_config_data[$ks];
if(!empty($temm_json_config) && isset($temm_json_config['type']) && $temm_json_config['type'] == 'annex')
{
foreach($temp_json_data as &$jsonv)
{
if(!empty($jsonv))
{
// 是否指定多个字段
if(empty($temm_json_config['key']))
{
if(!is_array($jsonv))
{
$jsonv = ResourcesService::AttachmentPathViewHandle($jsonv);
}
} else {
// 多个字段处理,必须存在值
if(is_array($jsonv))
{
// key是否数组
if(is_array($temm_json_config['key']))
{
foreach($temm_json_config['key'] as $jckv)
{
if(!empty($jsonv[$jckv]) && !is_array($jsonv[$jckv]))
{
$jsonv[$jckv] = ResourcesService::AttachmentPathViewHandle($jsonv[$jckv]);
}
}
} else {
// key单个字段
if(!empty($jsonv[$temm_json_config['key']]) && !is_array($jsonv[$temm_json_config['key']]))
{
$jsonv[$temm_json_config['key']] = ResourcesService::AttachmentPathViewHandle($jsonv[$temm_json_config['key']]);
}
}
}
}
}
}
}
}
$vs = $temp_json_data;
}
// 时间处理
if($is_handle_time_field && (substr($ks, -5) == '_time' || (!empty($handle_time_format) && is_array($handle_time_format) && array_key_exists($ks, $handle_time_format))))
{
$format = empty($handle_time_format) ? 'Y-m-d H:i:s' : (is_array($handle_time_format) ? (empty($handle_time_format[$ks]) ? 'Y-m-d H:i:s' : $handle_time_format[$ks]) : $handle_time_format);
$vs = empty($vs) ? '' : (is_numeric($vs) ? date($format, $vs) : $vs);
}
// 固定值名称处理
if($is_fixed_name_field && !empty($fixed_name_data) && is_array($fixed_name_data) && array_key_exists($ks, $fixed_name_data) && !empty($fixed_name_data[$ks]['data']))
{
$temp_data = $fixed_name_data[$ks]['data'];
$temp_field = empty($fixed_name_data[$ks]['field']) ? $ks.'_name' : $fixed_name_data[$ks]['field'];
$temp_key = empty($fixed_name_data[$ks]['key']) ? 'name' : $fixed_name_data[$ks]['key'];
// 是否数组
if(is_array($vs))
{
$temp_arr = [];
foreach($vs as $fixed_v)
{
if(!is_array($fixed_v) && array_key_exists($fixed_v, $temp_data))
{
$temp = $temp_data[$fixed_v];
if(is_array($temp))
{
if(isset($temp[$temp_key]))
{
$temp_arr[] = $temp[$temp_key];
}
} else {
$temp_arr[] = $temp;
}
}
}
$v[$temp_field] = empty($temp_arr) ? '' : implode(', ', $temp_arr);
} else {
$temp = (!empty($temp_data) && is_array($temp_data) && array_key_exists($vs, $temp_data)) ? $temp_data[$vs] : '';
$v[$temp_field] = empty($temp) ? '' : (is_array($temp) ? (isset($temp[$temp_key]) ? $temp[$temp_key] : '') : $temp);
}
}
// 附件字段处理
if($is_handle_annex_field && !empty($handle_annex_fields) && in_array($ks, $handle_annex_fields) && !empty($vs))
{
$vs = ResourcesService::AttachmentPathViewHandle($vs);
}
// 附件字节转单位
if($is_handle_annex_size_unit && !empty($handle_annex_size_unit_fields) && in_array($ks, $handle_annex_size_unit_fields) && !empty($vs))
{
$vs = AnnexSizeToUnit($vs);
}
// 展示字段指定数组转换处理、默认增加 _name 后缀
if(!empty($field_show_data) && array_key_exists($ks, $field_show_data))
{
$temp = $field_show_data[$ks];
$value = array_key_exists($vs, $temp['view_data']) ? $temp['view_data'][$vs] : null;
$key = $ks.'_name';
if($value === null)
{
$v[$key] = '';
} else {
if(is_array($value))
{
$v[$key] = (!empty($temp['view_data_key']) && array_key_exists($temp['view_data_key'], $value)) ? $value[$temp['view_data_key']] : '';
} else {
$v[$key] = $value;
}
}
}
// 状态字段按照搜索列表转换处理、默认增加 _name 后缀
if(!empty($field_status_data) && array_key_exists($ks, $field_status_data) && !empty($field_status_data[$ks]['search_config']) && !empty($field_status_data[$ks]['search_config']['data']))
{
$temp = $field_status_data[$ks]['search_config'];
$value = array_key_exists($vs, $temp['data']) ? $temp['data'][$vs] : null;
$key = $ks.'_name';
if($value === null)
{
$v[$key] = '';
} else {
if(is_array($value))
{
$v[$key] = (!empty($temp['data_name']) && array_key_exists($temp['data_name'], $value)) ? $value[$temp['data_name']] : '';
} else {
$v[$key] = $value;
}
}
}
// 换行转数组
if($is_ln_to_array_handle && !empty($ln_to_array_fields) && in_array($ks, $ln_to_array_fields))
{
$vs = empty($vs) ? [] : (is_array($vs) ? $vs : explode("\n", $vs));
}
}
}
}
}
// 是否已定义数据处理、必须存在双冒号
$m = $this->ServiceActionModule($form_data, 'data_handle');
if(!empty($m))
{
$module = $m['module'];
$action = $m['action'];
// 数据请求参数
$data_params = (!empty($form_data['data_params']) && is_array($form_data['data_params'])) ? $form_data['data_params'] : [];
// 列表和详情自定义参数合并
$data_params_field = $base['is_detail'] ? 'detail_params' : 'list_params';
if(!empty($form_data[$data_params_field]))
{
$data_params = array_merge($data_params, $form_data[$data_params_field]);
}
$res = $module::$action($this->data_list, $data_params);
// 是否按照数据返回格式方法放回的数据
if(isset($res['code']) && isset($res['msg']) && isset($res['data']))
{
$this->data_list = $res['data'];
} else {
$this->data_list = $res;
}
}
// 数据字段层级合并处理
$is_field_level_merge = isset($form_data['is_field_level_merge']) && $form_data['is_field_level_merge'] == 1;
$handle_field_level_merge_data = empty($form_data['handle_field_level_merge_data']) ? [] : $form_data['handle_field_level_merge_data'];
// 字段数据合并处理
if($is_field_level_merge && !empty($handle_field_level_merge_data) && is_array($handle_field_level_merge_data))
{
foreach($this->data_list as &$v2)
{
foreach($handle_field_level_merge_data as $fmdk=>$fmdv)
{
if(!empty($fmdk) && !empty($fmdv))
{
// 数组则处理多级拼接
if(is_array($fmdv))
{
$temp_fmdv_value = '';
foreach($fmdv as $fmdvs)
{
// 循环找出数据
$temp_fmdvs_value = null;
foreach(explode('.', $fmdvs) as $fmdvss)
{
if($temp_fmdvs_value === null)
{
if(isset($v2[$fmdvss]))
{
$temp_fmdvs_value = $v2[$fmdvss];
}
} else {
if(isset($temp_fmdvs_value[$fmdvss]))
{
$temp_fmdvs_value = $temp_fmdvs_value[$fmdvss];
}
}
}
if($temp_fmdvs_value !== null && !is_array($temp_fmdvs_value))
{
$temp_fmdv_value .= $temp_fmdvs_value;
}
}
$v2[$fmdk] = $temp_fmdv_value;
} else {
// 循环找出数据
$temp_fmdv_value = null;
foreach(explode('.', $fmdv) as $fmdvs)
{
if($temp_fmdv_value === null)
{
if(isset($v2[$fmdvs]))
{
$temp_fmdv_value = $v2[$fmdvs];
}
} else {
if(isset($temp_fmdv_value[$fmdvs]))
{
$temp_fmdv_value = $temp_fmdv_value[$fmdvs];
}
}
}
$v2[$fmdk] = $temp_fmdv_value;
}
}
}
}
}
// 分页处理
if($base['is_page'] && $base['is_list'] && !$this->is_export_excel)
{
// 是否定义分页提示信息
$tips_msg = '';
$m = $this->ServiceActionModule($form_data, 'page_tips_handle');
if(!empty($m))
{
$module = $m['module'];
$action = $m['action'];
$tips_msg = $module::$action($this->where);
}
// 分页统计数据
if(isset($form_data['is_page_stats']) && $form_data['is_page_stats'] == 1 && !empty($form_data['page_stats_data']) && is_array($form_data['page_stats_data']))
{
// 当前数据字段列
$data_item_fields = (empty($this->data_list) || empty($this->data_list[0])) ? [] : array_keys($this->data_list[0]);
// 统计数据集合
$stats_data = [];
foreach($form_data['page_stats_data'] as $pv)
{
if(!empty($pv['name']))
{
// 数据字段
$field = empty($pv['field']) ? 'id' : $pv['field'];
$stats_fun = empty($pv['fun']) ? 'sum' : $pv['fun'];
$res = $this->db->field($stats_fun.'('.$field.') as value')->find();
$value = (empty($res) || empty($res['value'])) ? 0 : $res['value'];
$stats_data[] = $pv['name'].$value.(empty($pv['unit']) ? '' : $pv['unit']);
}
}
if(!empty($stats_data))
{
$tips_msg .= implode('&nbsp;&nbsp;&nbsp;', $stats_data);
}
}
// 分页组件
$page_params = [
'number' => $this->page_size,
'total' => $this->data_total,
'where' => $this->out_params,
'page' => $this->page,
'url' => $this->page_url,
'tips_msg' => $tips_msg,
];
$page = new \base\Page($page_params);
$this->page_html = $page->GetPageHtml();
}
// 是否详情页
if($base['is_detail'] && isset($this->data_list[0]))
{
$this->data_detail = $this->data_list[0];
$this->data_list = [];
}
}
}
/**
* 数据列表基础
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2024-04-08
* @desc description
* @param [array] $form_data [表格数据]
*/
public function FormDataBase($form_data)
{
// 列表方法
$list_action = isset($form_data['list_action']) ? (is_array($form_data['list_action']) ? $form_data['list_action'] : [$form_data['list_action']]) : ['index'];
// 如果方法后缀为list则认为是列表组合方法
if(!empty($this->action_name) && substr($this->action_name, -4) == 'list')
{
$list_action[] = $this->action_name;
}
// 详情方法
$detail_action = isset($form_data['detail_action']) ? (is_array($form_data['detail_action']) ? $form_data['detail_action'] : [$form_data['detail_action']]) : ['detail', 'saveinfo', 'save', 'editinfo', 'edit', 'delete', 'del', 'statusupdate', 'status'];
// 如果方法后缀为detail则认为是详情组合方法
if(!empty($this->action_name) && substr($this->action_name, -6) == 'detail')
{
$detail_action[] = $this->action_name;
}
if(empty($this->plugins_module_name))
{
$is_list = in_array($this->action_name, $list_action);
$is_detail = in_array($this->action_name, $detail_action);
} else {
$is_list = in_array($this->plugins_action_name, $list_action);
$is_detail = in_array($this->plugins_action_name, $detail_action);
}
// 是否使用分页
$is_page = (!isset($form_data['is_page']) || $form_data['is_page'] == 1);
return [
'is_list' => $is_list,
'is_detail' => $is_detail,
'is_page' => $is_page,
];
}
/**
* excel导出处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-09-20
* @desc description
*/
public function FormDataExportExcelHandle()
{
if($this->is_export_excel)
{
// 错误提示
$error_msg = '';
if(empty($this->form_data['data']))
{
$error_msg = '请先定义数据配置';
}
// 是否存在数据
if(empty($error_msg) && empty($this->data_list) && empty($this->data_detail))
{
$error_msg = '没有相关数据、请重新输入搜索条件再试!';
}
// 根据表单配置标题处理
// 仅获取[ field、status、images ]类型的配置项
$title = [];
foreach($this->form_data['form'] as $v)
{
if(isset($v['view_type']) && in_array($v['view_type'], ['field', 'images', 'status', 'qrcode']) && !empty($v['label']) && !empty($v['view_key']))
{
// key避免多数组
$key = is_array($v['view_key']) ? $v['view_key'][0] : $v['view_key'];
// 数据转换字段再加 _name 后缀
// 1. field是否指定转换数据
// 2. 状态类型
if(($v['view_type'] == 'field' && !empty($v['view_data'])) || $v['view_type'] == 'status')
{
$key .= '_name';
}
//加入可导出容器
$title[$key] = [
'name' => $v['label'],
'type' => 'string',
];
}
}
if(empty($error_msg) && empty($title))
{
$error_msg = '没有相关field类型的表单配置';
}
// 提示错误
if(!empty($error_msg))
{
die('<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>错误提示</title>
</head>
<body style="text-align:center;">
<p style="color:#666;font-size:14px;margin-top:10%;margin-bottom:30px;">'.$error_msg.'</p>
<a href="javascript:;" onClick="WindowClose()" style="text-decoration:none;color:#fff;background:#f00;padding:5px 15px;border-radius:2px;font-size:12px;">关闭页面</a>
</body>
<script type="text/javascript">
function WindowClose()
{
var user_agent = navigator.userAgent;
if(user_agent.indexOf("Firefox") != -1 || user_agent.indexOf("Chrome") != -1)
{
location.href = "about:blank";
} else {
window.opener = null;
window.open("", "_self");
}
window.close();
}
</script>
</html>');
}
// 列表或详情数据
$list = empty($this->data_list) ? [$this->data_detail] : $this->data_list;
// 是否存在详情列表数据定义
$data = [];
if(!empty($this->form_data['detail_form_list']))
{
$is_table_title = true;
$detail_form_count = count($this->form_data['detail_form_list']);
foreach($list as $v)
{
// 当前详情数据最大数记录
$detail_data_row_max = 0;
foreach($this->form_data['detail_form_list'] as $dv)
{
// 追加表头
if($is_table_title && !empty($dv) && !empty($dv['label']) && !empty($dv['field']) && !empty($dv['data']))
{
foreach($dv['data'] as $dvk=>$dvv)
{
$title[$dv['field'].'_'.$dvk] = [
'name' => $dv['label'].' - '.$dvv,
'type' => 'string',
];
}
}
// 当前详情数据最大数记录
if(isset($v[$dv['field']]) && is_array($v[$dv['field']]))
{
$temp_max = (count($v[$dv['field']]) == count($v[$dv['field']], 1)) ? 1 : count($v[$dv['field']]);
if($temp_max > $detail_data_row_max)
{
$detail_data_row_max = $temp_max;
}
}
}
$is_table_title = false;
// 根据详情数据追加数据
for($i=0; $i<$detail_data_row_max; $i++)
{
$temp = $v;
for($t=0; $t<$detail_form_count; $t++)
{
$dv = $this->form_data['detail_form_list'][$t];
if(!empty($v[$dv['field']]))
{
$dv_data = array_keys($dv['data']);
foreach($dv_data as $df)
{
$fk = $dv['field'];
$field = $dv['field'].'_'.$df;
// 非二维数组则转二维数组
if(isset($v[$fk]) && is_array($v[$fk]) && count($v[$fk]) == count($v[$fk], 1))
{
$v[$fk] = [$v[$fk]];
}
// 存在数据则追加数据字段
if(isset($v[$fk][$i]) && isset($v[$fk][$i][$df]))
{
$temp[$field] = $v[$fk][$i][$df];
}
}
}
}
$data[] = $temp;
}
}
}
if(empty($data) && !empty($list))
{
$data = $list;
unset($list);
}
// Excel驱动导出数据
$excel = new \base\Excel(['title'=>$title, 'data'=>$data]);
$excel->Export();
}
}
/**
* 服务层方法模块
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-02
* @desc description
* @param [string] $data [模块数据]
* @param [string] $field [字段]
*/
public function ServiceActionModule($data, $field)
{
return (!empty($data) && !empty($data[$field])) ? $this->ServiceActionModuleHandle($data[$field]) : [];
}
/**
* 服务层方法模块处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2022-08-02
* @desc description
* @param [string] $value [字符数据]
*/
public function ServiceActionModuleHandle($value)
{
$result = [];
if(!empty($value) && stripos($value, '::') !== false)
{
$arr = explode('::', $value);
$action = $arr[1];
// 是否存在命名空间反斜杠
if(stripos($arr[0], '\\') === false)
{
// 是插件则优先走插件的服务层处理
$module = '';
if(!empty($this->plugins_module_name))
{
$module = 'app\plugins\\'.$this->plugins_module_name.'\service\\'.$arr[0];
if(!class_exists($module) || !method_exists($module, $action))
{
$module = '';
}
}
// 再走系统服务层处理
if(empty($module))
{
$module = 'app\service\\'.$arr[0];
}
} else {
$module = $arr[0];
}
if(class_exists($module))
{
if(method_exists($module, $action))
{
$result = [
'module' => $module,
'action' => $action,
];
}
}
}
return $result;
}
/**
* 排序字段处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-10-24
* @desc description
*/
public function FormOrderByHandle()
{
if(!empty($this->order_by['field']) && !empty($this->order_by['val']))
{
$this->order_by['data'] = $this->order_by['field'].' '.$this->order_by['val'];
}
}
/**
* 字段用户选择处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-10-09
* @desc description
*/
public function FormFieldsUserSelect()
{
// 用户选择字段数据
$user_choice_fields = $this->UserChoiceFieldsData();
$temp_user_choice_fields = array_column($user_choice_fields, null, 'key');
// 当前用户选择的字段
$ret = FormTableService::FieldsSelectData(['md5_key'=>$this->md5_key]);
if(empty($ret['data']))
{
// 未设置则读取所有带label的字段、默认显示
$this->user_fields = $user_choice_fields;
} else {
$this->user_fields = $ret['data'];
// 将每项的数据增加进去
foreach($this->user_fields as &$fv)
{
$fv['data'] = (!empty($fv['key']) && array_key_exists($fv['key'], $temp_user_choice_fields)) ? $temp_user_choice_fields[$fv['key']] : '';
}
}
// 如用户已选择字段则排除数据
if(!empty($this->user_fields))
{
$data = [];
// 无标题元素放在前面
foreach($this->form_data['form'] as $v)
{
if(empty($v['label']))
{
$data[] = $v;
}
}
// 根据用户选择顺序追加数据
foreach($this->user_fields as $k=>$v)
{
// 字段不存在数据中则移除
if(!empty($v['key']) && array_key_exists($v['key'], $temp_user_choice_fields) && !empty($temp_user_choice_fields[$v['key']]['data']))
{
$temp = $temp_user_choice_fields[$v['key']]['data'];
// 是否存在设置不展示列表、则移除字段
if(isset($temp['is_list']) && $temp['is_list'] == 0)
{
unset($this->user_fields[$k]);
}
// 避免已定义了列表是否显示字段、导致覆盖成为展示
if(!isset($temp['is_list']))
{
$temp['is_list'] = $v['checked'];
}
$data[] = $temp;
} else {
unset($this->user_fields[$k]);
}
}
// 操作元素放在最后面
foreach($this->form_data['form'] as $v)
{
if(isset($v['view_type']) && $v['view_type'] == 'operate')
{
$data[] = $v;
}
}
$this->form_data['form'] = $data;
}
}
/**
* 用户选择字段数据
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2023-06-29
* @desc description
*/
public function UserChoiceFieldsData()
{
return array_filter(array_map(function($value)
{
if(!empty($value['label']) && $value['view_type'] != 'operate' && !empty($value['view_key']))
{
$key = is_array($value['view_key']) ? implode('-', $value['view_key']) : str_replace(['../', './', '.', '/'], ['', '', '', '-'], $value['view_key']);
return [
// 基础数据
'label' => $value['label'],
'key' => $key,
// 默认选中数据
'checked' => 1,
// 原始数据
'data' => $value,
];
}
}, $this->form_data['form']));
}
/**
* 表单md5key值
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-10-08
* @desc description
* @param [string] $module [模块位置]
* @param [string] $action [模块方法(默认 Run 方法,可自动匹配控制器方法名)]
*/
public function FromMd5Key($module, $action)
{
$this->md5_key = md5($module.'\\'.$action);
}
/**
* 表格配置处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-02
* @desc description
*/
public function FormConfigHandle()
{
$lang = MyLang('form_table_search_first');
foreach($this->form_data['form'] as $k=>&$v)
{
// 基础字段处理
// 是否上下居中0否,1是默认1
if(!isset($v['is_middle']))
{
$v['is_middle'] = isset($this->form_data['base']['is_middle']) ? $this->form_data['base']['is_middle'] : 1;
}
// 基础数据类型处理
if(!empty($v['view_type']))
{
switch($v['view_type'])
{
// 状态操作
// 复选框
// 单选框
case 'status' :
case 'checkbox' :
case 'radio' :
// 未指定唯一字段名称则使用基础中的唯一字段
if(empty($v['key_field']))
{
$v['key_field'] = $this->form_data['base']['key_field'];
}
// 复选框
if($v['view_type'] == 'checkbox')
{
// 选择/未选中文本
if(empty($v['checked_text']))
{
$v['checked_text'] = MyLang('reverse_select_title');
}
if(empty($v['not_checked_text']))
{
$v['not_checked_text'] = MyLang('select_all_title');
}
// 是否选中 默认否
$v['is_checked'] = isset($v['is_checked']) ? intval($v['is_checked']) : 0;
// view key 默认 form_ids_checkbox
if(empty($v['view_key']))
{
$v['view_key'] = 'form_checkbox_value';
}
}
// 单选框
if($v['view_type'] == 'radio')
{
// 单选标题
if(empty($v['label']))
{
$v['label'] = MyLang('single_select_title');
}
// view key 默认 form_ids_radio
if(empty($v['view_key']))
{
$v['view_key'] = 'form_radio_value';
}
}
// 复选+单选
if(in_array($v['view_type'], ['checkbox', 'radio']))
{
// 是否部分不显示控件
// 可配置 not_show_type 字段指定类型0 eq 等于、 1 gt 大于、 2 lt 小于)
if(isset($v['not_show_data']) && !is_array($v['not_show_data']))
{
// 存在英文逗号则转数组
if(stripos($v['not_show_data'], ',') !== false)
{
$v['not_show_data'] = explode(',', $v['not_show_data']);
}
}
// 数据 key 字段默认主键 id [base->key_field]
if(!empty($v['not_show_data']) && empty($v['not_show_key']))
{
$v['not_show_key'] = $this->form_data['base']['key_field'];
}
}
break;
// 字段
case 'field' :
// 是否开启弹出提示
if(isset($v['is_popover']) && $v['is_popover'] == 1)
{
// 是否指定弹出提示数据字段
if(empty($v['popover_field']) && !empty($v['view_key']) && !is_array($v['view_key']))
{
$v['popover_field'] = $v['view_key'];
}
}
break;
// 图片
case 'images' :
if(empty($v['images_shape']))
{
$v['images_shape'] = 'radius';
}
break;
// 视频
case 'video' :
if(empty($v['video_shape']))
{
$v['video_shape'] = 'radius';
}
break;
}
}
// 表单key
$fk = 'f'.$k;
// 表单标识
if($v['view_type'] == 'module')
{
$view_key = (empty($v['search_config']) || empty($v['search_config']['form_name'])) ? '' : $v['search_config']['form_name'];
} else {
$view_key = empty($v['view_key']) ? '' : $v['view_key'];
}
// 表单标识为数组则取第一个
if(!empty($view_key) && is_array($view_key) && isset($view_key[0]))
{
$view_key = $view_key[0];
}
// 表单名称
$form_name = (!empty($v['search_config']) && !empty($v['search_config']['form_name'])) ? $v['search_config']['form_name'] : $view_key;
// 条件处理
if(!empty($v['search_config']) && !empty($v['search_config']['form_type']))
{
// 搜索 key 未指定则使用显示数据的字段名称
if(empty($v['search_config']['form_name']))
{
$v['search_config']['form_name'] = $form_name;
}
// 基础数据处理
if(!empty($v['search_config']['form_name']))
{
// 显示名称
$label = empty($v['label']) ? '' : $v['label'];
// 唯一 formkey
$form_key = $fk.'p';
$v['form_key'] = $form_key;
// 是否指定了数据/表单唯一key作为条件、则复制当前key数据
// 用于根据key指定条件指定不宜使用这里拼接的key
$params_where_name = empty($v['params_where_name']) ? $view_key : $v['params_where_name'];
if(array_key_exists($params_where_name, $this->out_params) && $this->out_params[$params_where_name] !== null && $this->out_params[$params_where_name] !== '')
{
$this->out_params[$form_key] = $this->out_params[$params_where_name];
// min字段
} elseif(array_key_exists($params_where_name.'_min', $this->out_params) && $this->out_params[$params_where_name.'_min'] !== null && $this->out_params[$params_where_name.'_min'] !== '')
{
$this->out_params[$form_key.'_min'] = $this->out_params[$params_where_name.'_min'];
// max字段
} elseif(array_key_exists($params_where_name.'_max', $this->out_params) && $this->out_params[$params_where_name.'_max'] !== null && $this->out_params[$params_where_name.'_max'] !== '')
{
$this->out_params[$form_key.'_max'] = $this->out_params[$params_where_name.'_max'];
// start字段
} elseif(array_key_exists($params_where_name.'_start', $this->out_params) && $this->out_params[$params_where_name.'_start'] !== null && $this->out_params[$params_where_name.'_start'] !== '')
{
$this->out_params[$form_key.'_start'] = $this->out_params[$params_where_name.'_start'];
// end字段
} elseif(array_key_exists($params_where_name.'_end', $this->out_params) && $this->out_params[$params_where_name.'_end'] !== null && $this->out_params[$params_where_name.'_end'] !== '')
{
$this->out_params[$form_key.'_end'] = $this->out_params[$params_where_name.'_end'];
}
// 根据组件类型处理
switch($v['search_config']['form_type'])
{
// 单个输入
case 'input' :
// 提示信息处理
if(empty($v['search_config']['placeholder']))
{
$v['search_config']['placeholder'] = $lang['input'].$label;
}
break;
// 选择
case 'select' :
// 提示信息处理
if(empty($v['search_config']['placeholder']))
{
$v['search_config']['placeholder'] = $lang['select'].$label;
}
// 选择数据 key=>name
$temp_data_keys = empty($v['search_config']['data']) ? [] : ArrayKeys($v['search_config']['data']);
if(empty($v['search_config']['data_key']))
{
$v['search_config']['data_key'] = in_array('value', $temp_data_keys) ? 'value' : 'id';
}
if(empty($v['search_config']['data_name']))
{
$v['search_config']['data_name'] = in_array('title', $temp_data_keys) ? 'title' : 'name';
}
break;
// 区间
case 'section' :
// 提示信息处理
if(empty($v['search_config']['placeholder_min']))
{
$v['search_config']['placeholder_min'] = $lang['section_min'];
}
if(empty($v['search_config']['placeholder_max']))
{
$v['search_config']['placeholder_max'] = $lang['section_max'];
}
break;
// 时间
case 'datetime' :
case 'date' :
// 提示信息处理
if(empty($v['search_config']['placeholder_start']))
{
$v['search_config']['placeholder_start'] = $lang['date_start'];
}
if(empty($v['search_config']['placeholder_end']))
{
$v['search_config']['placeholder_end'] = $lang['date_end'];
}
break;
// 年月Ym
case 'ym' :
// 提示信息处理
if(empty($v['search_config']['placeholder']))
{
$v['search_config']['placeholder'] = $lang['ym'];
}
break;
}
// 搜索条件数据处理
// 表单字段名称
$where_name = $form_name;
// 条件类型
$where_type = isset($v['search_config']['where_type']) ? $v['search_config']['where_type'] : $v['search_config']['form_type'];
// 条件默认值处理
$where_type_default_arr = [
'input' => '=',
'select' => 'in',
'ym' => '=',
];
if(array_key_exists($where_type, $where_type_default_arr))
{
$where_type = $where_type_default_arr[$where_type];
}
// 是否自定义条件处理
$where_custom = isset($v['search_config']['where_type_custom']) ? $v['search_config']['where_type_custom'] : '';
// 条件类型
$where_symbol = $this->WhereSymbolHandle($form_key, $where_custom, $where_type);
// 是否自定义条件处理方法
$value_custom = isset($v['search_config']['where_value_custom']) ? $v['search_config']['where_value_custom'] : '';
// 是否自定义条件处理类对象(默认表格定义文件的对象)
$object_custom = isset($v['search_config']['where_object_custom']) ? $v['search_config']['where_object_custom'] : null;
// 根据条件类型处理
switch($where_type)
{
// 单个值
case '=' :
case '<' :
case '>' :
case '<=' :
case '>=' :
case 'like' :
if(array_key_exists($form_key, $this->out_params) && $this->out_params[$form_key] !== null && $this->out_params[$form_key] !== '' && !is_array($this->out_params[$form_key]))
{
// 参数值
$value = urldecode($this->out_params[$form_key]);
$this->where_params[$form_key] = $value;
// 条件值处理
$value = $this->WhereValueHandle($value, $value_custom, $object_custom);
if($value !== null && $value !== '')
{
// 是否 like 条件
if($where_type == 'like' && is_string($value))
{
$value = '%'.$value.'%';
}
// 年月Ym、去掉横杠
if($v['search_config']['form_type'] == 'ym')
{
$value = str_replace(['-', '/', '|'], '', $value);
}
// id字段则判断数据值是否包含半角逗号则条件类型强制为in
if(!is_array($value) && ($where_name == 'id' || stripos($where_name, '.id') !== false) && stripos($value, ',') !== false)
{
$where_symbol = 'in';
$value = explode(',', $value);
}
// 条件
$this->where[] = [$where_name, $where_symbol, $value];
}
}
break;
// in
case 'in' :
if(array_key_exists($form_key, $this->out_params) && $this->out_params[$form_key] !== null && $this->out_params[$form_key] !== '')
{
// 参数值
$value = $this->out_params[$form_key];
if(!empty($value) && !is_array($value))
{
$value = urldecode($value);
}
if(!is_array($value))
{
$value = explode(',', $value);
}
$this->where_params[$form_key] = $value;
// 条件
$value = $this->WhereValueHandle($value, $value_custom, $object_custom);
// in条件必须存在值也必须是数组
if($where_symbol == 'in')
{
if(!empty($value) && is_array($value))
{
$this->where[] = [$where_name, $where_symbol, $value];
}
} else {
if($value !== null && $value !== '')
{
$this->where[] = [$where_name, $where_symbol, $value];
}
}
}
break;
// 区间值
case 'section' :
$key_min = $form_key.'_min';
$key_max = $form_key.'_max';
if(array_key_exists($key_min, $this->out_params) && $this->out_params[$key_min] !== null && $this->out_params[$key_min] !== '')
{
// 参数值
$value = urldecode($this->out_params[$key_min]);
$this->where_params[$key_min] = $value;
// 条件
$value = $this->WhereValueHandle($value, $value_custom, $object_custom, ['is_min'=>1]);
if($value !== null && $value !== '')
{
$this->where[] = [$where_name, '>=', $value];
}
}
if(array_key_exists($key_max, $this->out_params) && $this->out_params[$key_max] !== null && $this->out_params[$key_max] !== '')
{
// 参数值
$value = urldecode($this->out_params[$key_max]);
$this->where_params[$key_max] = $value;
// 条件
$value = $this->WhereValueHandle($value, $value_custom, $object_custom, ['is_end'=>1]);
if($value !== null && $value !== '')
{
$this->where[] = [$where_name, '<=', $value];
}
}
break;
// 时间
case 'datetime' :
case 'date' :
$key_start = $form_key.'_start';
$key_end = $form_key.'_end';
if(array_key_exists($key_start, $this->out_params) && $this->out_params[$key_start] !== null && $this->out_params[$key_start] !== '')
{
// 参数值
$value = urldecode($this->out_params[$key_start]);
$this->where_params[$key_start] = $value;
// 条件
$value = $this->WhereValueHandle(strtotime($value), $value_custom, $object_custom, ['is_start'=>1]);
if($value !== null && $value !== '')
{
$this->where[] = [$where_name, '>=', $value];
}
}
if(array_key_exists($key_end, $this->out_params) && $this->out_params[$key_end] !== null && $this->out_params[$key_end] !== '')
{
// 参数值
$value = urldecode($this->out_params[$key_end]);
$this->where_params[$key_end] = $value;
// 条件
$value = $this->WhereValueHandle(strtotime($value), $value_custom, $object_custom, ['is_end'=>1]);
if($value !== null && $value !== '')
{
$this->where[] = [$where_name, '<=', $value];
}
}
break;
}
}
}
// 排序key与字段、自动拼接的字段 或者 指定的form_key和form_name字段
$v['sort_key'] = $fk.'o';
if($v['sort_key'] == $this->order_by['key'] || $form_name == $this->order_by['key'])
{
$this->order_by['field'] = empty($v['sort_field']) ? $form_name : $v['sort_field'];
}
// 唯一key避免是模块路径、直接取最后一段
$unique_key = '';
if(!empty($v['view_key']))
{
// 多字段情况下
if(is_array($v['view_key']))
{
$unique_key = isset($v['view_key'][0]) ? $v['view_key'][0] : '';
} else {
// 字段名称、模块路径
$temp = explode('/', $v['view_key']);
$unique_key = empty($temp) ? '' : end($temp);
}
}
$v['unique_key'] = $unique_key;
}
}
/**
* 基础数据结尾处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-06
* @desc description
*/
public function FormBaseLastHandle()
{
// 异步请求超时时间
if(empty($this->form_data['base']['timeout']))
{
$this->form_data['base']['timeout'] = 30000;
}
// 是否开启删除
if(isset($this->form_data['base']['is_delete']) && $this->form_data['base']['is_delete'] == 1)
{
// 是否指定选择列字段名称
// 默认一(第一个复选框)
// 默认二(第一个单选框)
if(empty($this->form_data['base']['delete_form']))
{
// 所有 form 类型
$form_type = array_column($this->form_data['form'], 'view_type');
if(!empty($form_type))
{
// 是否存在复选框
if(in_array('checkbox', $form_type))
{
$index = array_search('checkbox', $form_type);
if($index !== false)
{
$this->form_data['base']['delete_form'] = $this->form_data['form'][$index]['view_key'];
}
}
// 是否存在单选框
if(empty($this->form_data['base']['delete_form']) && in_array('radio', $form_type))
{
$index = array_search('radio', $form_type);
if($index !== false)
{
$this->form_data['base']['delete_form'] = $this->form_data['form'][$index]['view_key'];
}
}
}
// 未匹配到则默认 ids
if(empty($this->form_data['base']['delete_form']))
{
$this->form_data['base']['delete_form'] = 'ids';
}
}
// 提交数据的字段名称
if(empty($this->form_data['base']['delete_key']))
{
$this->form_data['base']['delete_key'] = $this->form_data['base']['delete_form'];
}
// 确认框信息 标题/描述
if(empty($this->form_data['base']['confirm_title']))
{
$this->form_data['base']['confirm_title'] = '温馨提示';
}
if(empty($this->form_data['base']['confirm_msg']))
{
$this->form_data['base']['confirm_msg'] = '删除后不可恢复、确认操作吗?';
}
}
}
/**
* 条件符号处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-08-20
* @desc description
* @param [string] $form_key [表单key]
* @param [stribg] $where_custom [自定义条件值]
* @param [stribg] $where_type [条件类型]
*/
public function WhereSymbolHandle($form_key, $where_custom, $where_type)
{
// 是否已定义自定义条件符号
if(!empty($where_custom))
{
// 模块是否自定义条件方法处理条件
if(method_exists($this->module_obj, $where_custom))
{
$value = $this->module_obj->$where_custom($form_key, $this->out_params);
if(!empty($value))
{
return $value;
}
} else {
return $where_custom;
}
}
// 默认条件类型
return $where_type;
}
/**
* 条件值处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-04
* @desc description
* @param [mixed] $value [条件值]
* @param [string] $action_custom [自定义处理方法名称]
* @param [object] $object_custom [自定义处理类对象]
* @param [array] $params [输入参数]
*/
public function WhereValueHandle($value, $action_custom = '', $object_custom = null, $params = [])
{
// 根据方法名称处理条件
switch($action_custom)
{
// 系统用户条件处理
case 'SystemModuleUserWhereHandle' :
if(!empty($value))
{
// 获取用户id
$ids = Db::name('User')->where('number_code|username|nickname|mobile|email', 'like', '%'.$value.'%')->column('id');
// 避免空条件造成无效的错觉
return empty($ids) ? [0] : $ids;
}
break;
// 系统商品条件处理
case 'SystemModuleGoodsWhereHandle' :
if(!empty($value))
{
// 获取商品id
$ids = Db::name('Goods')->alias('g')->join('goods_spec_base gb', 'g.id=gb.goods_id')->where('g.title|g.simple_desc|g.seo_title|g.seo_keywords|g.seo_keywords|gb.coding|gb.barcode', 'like', '%'.$value.'%')->column('g.id');
// 避免空条件造成无效的错觉
return empty($ids) ? [0] : $ids;
}
break;
// 默认走自定义模块处理
default :
// 是否自定义类方法处理
$m = $this->ServiceActionModuleHandle($action_custom);
if(!empty($m))
{
$module = $m['module'];
$action = $m['action'];
return $module::$action($value, $params);
}
// 模块是否自定义条件值方法处理条件
$obj = is_object($object_custom) ? $object_custom : $this->module_obj;
if(!empty($action_custom) && method_exists($obj, $action_custom))
{
return $obj->$action_custom($value, $params);
}
}
// 默认直接返回值
return $value;
}
/**
* 基础条件处理
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-06-05
* @desc description
*/
public function BaseWhereHandle()
{
$this->where = $this->condition_base_where;
}
/**
* 表格数据列表处理(仅供外部调用、非当前文件调用)
* @author Devil
* @blog http://gong.gg/
* @version 1.0.0
* @date 2020-12-06
* @desc 参数说明 params
* group 模块组、默认自动读取
* control 系统控制器、默认自动读取
* action 系统方法、默认自动读取
* pluginsname 插件、默认空非插件
* pluginscontrol 插件控制器、默认自动读取
* pluginsaction 插件方法、默认自动读取
* is_module_api_to_index api模块的情况不存在form是否转index模块找form、默认否
* return_data_struct all 返回整体的数据结构
* @param [array] $data [数据列表]
* @param [array] $params [参数数据]
*/
public function FormTableDataListHandle($data, $params = [])
{
// 数据为空则不处理
if(empty($data) || !is_array($data))
{
return $data;
}
$this->data_list = $data;
// 获取表格模型处理表格列表数据、支持使用后端模块form配置结构
$module = FormModulePath(array_merge(input(), $params, ['is_admin_module'=>1]));
if(!empty($module))
{
// 参数校验
$ret = $this->ParamsCheckHandle($module['module'], $module['action'], $params);
if($ret['code'] == 0)
{
// 数据处理
$this->FormDataListHandle();
}
}
// 返回处理的数据
if(isset($params['return_data_struct']) && $params['return_data_struct'] == 'all')
{
return [
'table' => $this->form_data,
'where' => $this->where,
'params' => $this->where_params,
'md5_key' => $this->md5_key,
'user_fields' => $this->user_fields,
'order_by' => $this->order_by,
'page' => $this->page,
'page_start' => $this->page_start,
'page_size' => $this->page_size,
'page_total' => $this->page_total,
'page_url' => $this->page_url,
'page_html' => $this->page_html,
'data_total' => $this->data_total,
'data_list' => $this->data_list,
'data_detail' => $this->data_detail,
];
}
return $this->data_list;
}
}
?>