CRMEB/crmeb/app/services/system/config/SystemConfigServices.php

1771 lines
74 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// +----------------------------------------------------------------------
// | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2016~2026 https://www.crmeb.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
// +----------------------------------------------------------------------
// | Author: CRMEB Team <admin@crmeb.com>
// +----------------------------------------------------------------------
namespace app\services\system\config;
use app\dao\system\config\SystemConfigDao;
use app\services\agent\AgentManageServices;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use crmeb\services\CacheService;
use crmeb\services\FileService;
use crmeb\services\FormBuilder;
use think\facade\Log;
/**
* 系统配置
* Class SystemConfigServices
* @package app\services\system\config
* @method count(array $where = []) 获取指定条件下的count
* @method save(array $data) 保存数据
* @method get(int $id, ?array $field = []) 获取一条数据
* @method update($id, array $data, ?string $key = null) 修改数据
* @method delete(int $id, ?string $key = null) 删除数据
* @method getUploadTypeList(string $configName) 获取上传配置中的上传类型
*/
class SystemConfigServices extends BaseServices
{
/**
* 系统配置数据访问层
* @var SystemConfigDao
*/
protected $dao;
/**
* form表单句柄
* @var FormBuilder
*/
protected $builder;
/**
* 表单数据切割符号
* @var string
*/
protected $cuttingStr = '=>';
/**
* 表单提交url
* @var string[]
*/
protected $postUrl = [
// 基础配置
'setting' => [
'url' => '/setting/config/save_basics',
'auth' => [],
],
// 服务配置
'serve' => [
'url' => '/serve/sms_config/save_basics',
'auth' => ['short_letter_switch'],
],
// 运费配置
'freight' => [
'url' => '/freight/config/save_basics',
'auth' => ['express'],
],
// 分销配置
'agent' => [
'url' => '/agent/config/save_basics',
'auth' => ['fenxiao'],
],
// 积分配置
'marketing' => [
'url' => '/marketing/integral_config/save_basics',
'auth' => ['point'],
]
];
/**
* 子集控制规则联动控制,新版单个配置可以配置联动,此配置为兼容旧版数据配置,不建议使用
* @var array[]
*/
protected $relatedRule = [
'sign_status' => [
'son_type' => [
'sign_mode' => '',
'sign_remind' => [
'son_type' => [
'sign_remind_time' => '',
'sign_remind_type' => '',
],
'show_value' => 1
],
'sign_give_point' => '',
'sign_give_exp' => '',
],
'show_value' => 1
],
'brokerage_func_status' => [
'son_type' => [
'store_brokerage_statu' => [
'son_type' => ['store_brokerage_price' => ''],
'show_value' => 3
],
'brokerage_bindind' => '',
'store_brokerage_binding_status' => [
'son_type' => ['store_brokerage_binding_time' => ''],
'show_value' => 2
],
'spread_banner' => '',
'brokerage_level' => '',
'division_status' => '',
'agent_apply_open' => '',
'brokerage_window_switch' => '',
],
'show_value' => 1
],
'brokerage_user_status' => [
'son_type' => [
'uni_brokerage_price' => '',
'day_brokerage_price_upper' => '',
],
'show_value' => 1
],
'invoice_func_status' => [
'son_type' => [
'special_invoice_status' => '',
],
'show_value' => 1
],
'member_func_status' => [
'son_type' => [
'order_give_exp' => '',
'invite_user_exp' => ''
],
'show_value' => 1
],
'balance_func_status' => [
'son_type' => [
'recharge_attention' => '',
'recharge_switch' => '',
'store_user_min_recharge' => '',
],
'show_value' => 1
],
'pay_wechat_type' => [
'son_type' => [
'pay_weixin_key' => '',
],
'show_value' => 0
],
'pay_wechat_type@' => [
'son_type' => [
'pay_weixin_serial_no' => '',
'v3_transfer_scene_id' => '',
'pay_weixin_key_v3' => '',
'v3_pay_public_key' => '',
'v3_pay_public_pem' => '',
],
'show_value' => 1
],
'image_watermark_status' => [
'son_type' => [
'watermark_type' => [
'son_type' => [
'watermark_image' => '',
'watermark_opacity' => '',
'watermark_rotate' => '',
],
'show_value' => 1
],
'watermark_position' => '',
'watermark_x' => '',
'watermark_y' => '',
'watermark_type@' => [
'son_type' => [
'watermark_text' => '',
'watermark_text_size' => '',
'watermark_text_color' => '',
'watermark_text_angle' => ''
],
'show_value' => 2
],
],
'show_value' => 1
],
'customer_type' => [
'son_type' => [
'service_feedback' => '',
],
'show_value' => 0
],
'customer_type#' => [
'son_type' => [
'customer_phone' => '',
],
'show_value' => 1
],
'customer_type@' => [
'son_type' => [
'customer_url' => '',
'customer_corpId' => '',
],
'show_value' => 2
],
'pay_new_weixin_open' => [
'son_type' => [
'pay_new_weixin_mchid' => ''
],
'show_value' => 1
],
'mer_type' => [
'son_type' => [
'pay_sub_merchant_id' => '',
'sp_appid' => ''
],
'show_value' => 1
],
'member_card_status' => [
'son_type' => [
'member_price_status' => '',
],
'show_value' => 1
],
];
/**
* SystemConfigServices constructor.
* @param SystemConfigDao $dao
* @param FormBuilder $builder
*/
public function __construct(SystemConfigDao $dao, FormBuilder $builder)
{
$this->dao = $dao;
$this->builder = $builder;
}
/**
* 获取单个系统配置
* @param string $configName
* @param null $default
* @return mixed|null
* @throws \ReflectionException
*/
public function getConfigValue(string $configName, $default = null)
{
$value = $this->dao->getConfigValue($configName);
return is_null($value) ? $default : json_decode($value, true);
}
/**
* 获取全部配置
* @param array $configName
* @return array
* @throws \ReflectionException
*/
public function getConfigAll(array $configName = [])
{
return array_map(function ($item) {
return json_decode($item, true);
}, $this->dao->getConfigAll($configName));
}
/**
* 获取配置列表搜索并分页
* @param array $where
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getConfigList(array $where)
{
[$page, $limit] = $this->getPageValue();
$list = $this->dao->getConfigList($where, $page, $limit);
$count = $this->dao->count($where);
$tidy_srr = [];
$configTabList = app()->make(SystemConfigTabServices::class)->getColumn([], 'title', 'id');
foreach ($list as &$item) {
$item['value'] = $item['value'] ? (json_decode($item['value'], true) ?: '') : '';
if ($item['type'] == 'radio' || $item['type'] == 'checkbox') {
$item['value'] = $this->getRadioOrCheckboxValueInfo($item['menu_name'], $item['value']);
}
if ($item['type'] == 'upload' && !empty($item['value'])) {
if ($item['upload_type'] == 1 || $item['upload_type'] == 3) {
$item['value'] = [set_file_url($item['value'])];
} elseif ($item['upload_type'] == 2) {
$tempValue = set_file_url($item['value']);
$item['value'] = is_array($tempValue) ? $tempValue : [];
}
if (is_array($item['value']) && !empty($item['value'])) {
foreach ($item['value'] as $key => $value) {
$tidy_srr[$key]['filepath'] = $value;
$tidy_srr[$key]['filename'] = basename($value);
}
$item['value'] = $tidy_srr;
} else {
$item['value'] = [];
}
}
if ($item['level'] == 1) {
$item['link_data'] = $this->getLinkData($item['link_id'], $item['link_value']);
}
$item['config_tab_name'] = $configTabList[$item['config_tab_id']] ?? '';
}
return compact('count', 'list');
}
/**
* 配置列表页获取关联的值,展示:关联配置名称/关联值
* @param $id
* @param $value
* @return string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
* @author wuhaotian
* @email 442384644@qq.com
* @date 2024/5/31
*/
private function getLinkData($id, $value)
{
$info = $this->dao->get($id);
if (!$info) return '';
$parameter = explode("\n", $info['parameter']);
$result = [];
foreach ($parameter as $item) {
$parts = explode('=>', $item);
$result[$parts[0]] = $parts[1];
}
return $info['info'] . ':' . $result[$value].'(显示)';
}
/**
* 配置列表页获取单选按钮或者多选按钮的显示值
* @param $menu_name
* @param $value
* @return string
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
private function getRadioOrCheckboxValueInfo(string $menu_name, $value): string
{
$option = [];
$config_one = $this->dao->getOne(['menu_name' => $menu_name]);
if (!$config_one) {
return '';
}
$parameter = explode("\n", $config_one['parameter']);
foreach ($parameter as $k => $v) {
if (isset($v) && strlen($v) > 0) {
$data = explode('=>', $v);
$option[$data[0]] = $data[1];
}
}
$str = '';
if (is_array($value)) {
foreach ($value as $v) {
$str .= $option[$v] . ',';
}
} else {
$str .= !empty($value) ? $option[$value] ?? '' : $option[0] ?? '';
}
return $str;
}
/**
* 根据配置tab id获取系统配置信息
* @param int $tabId
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getReadList(int $tabId)
{
$info = $this->dao->getConfigTabAllList($tabId);
foreach ($info as $k => $v) {
if (!is_null(json_decode($v['value'])))
$info[$k]['value'] = json_decode($v['value'], true);
if ($v['type'] == 'upload' && !empty($v['value'])) {
if ($v['upload_type'] == 1 || $v['upload_type'] == 3) $info[$k]['value'] = explode(',', $v['value']);
}
}
return $info;
}
/**
* 修改字段获取form表单
* @param int $id
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function editFieldForm(int $id)
{
$menu = $this->dao->get($id)->getData();
if (!$menu) {
throw new AdminException('数据不存在');
}
/** @var SystemConfigTabServices $service */
$service = app()->make(SystemConfigTabServices::class);
$formbuider = [];
$linkData = $this->linkData($menu['config_tab_id']);
$formbuider[] = $this->builder->radio('level', '联动显示', $menu['level'])->options([['value' => 0, 'label' => '否'], ['value' => 1, 'label' => '是']])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '否:默认正常展示此配置;是:此配置默认隐藏,当选中下方对应配置的值时,此配置才会显示']
])->appendControl(1, [
$this->builder->cascader('link_data', '关联配置/值', [$menu['link_id'], $menu['link_value']])->options($linkData)->props(['props' => ['multiple' => false, 'checkStrictly' => false, 'emitPath' => true]])->style(['width' => '100%']),
])->requiredNum();
$formbuider[] = $this->builder->input('menu_name', '字段变量', $menu['menu_name'])->disabled(1);
$formbuider[] = $this->builder->hidden('type', $menu['type']);
[$configTabList, $data] = $service->getConfigTabListForm((int)($menu['config_tab_id'] ?? 0));
$formbuider[] = $this->builder->cascader('config_tab_id', '分类', $data)->options($configTabList)->filterable(true)->props(['props' => ['multiple' => false, 'checkStrictly' => true, 'emitPath' => true]])->style(['width' => '100%']);
$formbuider[] = $this->builder->input('info', '配置名称', $menu['info'])->required('配置名称不能为空')->autofocus(1);
$formbuider[] = $this->builder->input('desc', '配置简介', $menu['desc']);
switch ($menu['type']) {
case 'text':
$menu['value'] = json_decode($menu['value'], true);
$formbuider[] = $this->createTextInputTypeForm($menu, true);
break;
case 'textarea':
$menu['value'] = json_decode($menu['value'], true);
$formbuider[] = $this->builder->textarea('value', '默认值', $menu['value'])->rows(3);
$formbuider[] = $this->builder->number('width', '文本框宽', (int)$menu['width'])->min(1)->max(24);
$formbuider[] = $this->builder->number('high', '多行文本框高', (int)$menu['high'])->min(1);
break;
case 'radio':
$formbuider = array_merge($formbuider, $this->createRadioForm($menu));
$formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
break;
case 'upload':
$formbuider = array_merge($formbuider, $this->createUploadForm((int)$menu['upload_type'], $menu, true));
break;
case 'checkbox':
$menu['label'] = '默认值';
$formbuider = array_merge($formbuider, $this->createCheckboxForm($menu));
$formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
break;
case 'select':
$formbuider = array_merge($formbuider, $this->createSelectForm($menu));
$formbuider[] = $this->builder->textarea('parameter', '配置参数', $menu['parameter'] ?? '')->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色");
break;
case 'switch':
$formbuider = array_merge($formbuider, $this->createSwitchForm($menu));
break;
}
// 是否必填(支持JSON格式)
$requiredData = json_decode($menu['required'], true);
if ($requiredData && isset($requiredData['required'])) {
$menu['required'] = $requiredData['required'] ? 1 : 0;
} else {
$menu['required'] = $menu['required'] ? 1 : 0;
}
// 非switch类型,添加是否必填字段
if ($menu['type'] != 'switch') {
$formbuider[] = $this->builder->radio('required', '是否必填', $menu['required'] ?? 0)->options([
['value' => 0, 'label' => '否'],
['value' => 1, 'label' => '是'],
])->requiredNum();
}
$formbuider[] = $this->builder->number('sort', '排序', (int)$menu['sort']);
$formbuider[] = $this->builder->radio('status', '状态', $menu['status'] ?? 0)->options([
['value' => 1, 'label' => '显示'],
['value' => 0, 'label' => '隐藏'],
])->requiredNum();
return create_form('编辑字段', $formbuider, $this->url('/setting/config/' . $id), 'PUT');
}
/**
* 创建和编辑文本类型的输入类型表单
* @param array $data 配置数据
* @param bool $isEdit 是否为编辑模式
* @return BaseForm|BaseForm[]
*/
private function createTextInputTypeForm(array $data, bool $isEdit = false)
{
// 拆分必填、格式规则和数字范围(支持JSON格式)
$requiredRules = $data['required'] ?? '';
$requiredData = [];
// 尝试解析JSON格式的验证规则
if ($requiredRules && $requiredData = json_decode($requiredRules, true)) {
$data['required'] = isset($requiredData['required']) && $requiredData['required'] ? 'required:true' : '';
$data['regex'] = $requiredData['regex'] ?? '';
$data['min'] = $requiredData['min'] ?? '';
$data['max'] = $requiredData['max'] ?? '';
} else {
// 兼容旧格式:逗号分隔的字符串格式
$data['required'] = strpos($requiredRules, 'required:true') !== false ? 'required:true' : '';
$data['regex'] = '';
$data['min'] = '';
$data['max'] = '';
// 提取 min 和 max
if (preg_match('/\bmin:(-?\d+)/', $requiredRules, $minMatch)) {
$data['min'] = (int)$minMatch[1];
}
if (preg_match('/\bmax:(-?\d+)/', $requiredRules, $maxMatch)) {
$data['max'] = (int)$maxMatch[1];
}
// 提取正则表达式
if (preg_match('/regex:(\/.+\/[gimsuy]*)/', $requiredRules, $patternMatch)) {
$data['regex'] = $patternMatch[1];
}
}
// 创建输入类型选择器
$inputTypeSelect = $this->builder->select('input_type', '类型', $data['input_type'] ?? 'input')->setOptions([
['value' => 'input', 'label' => '文本框'],
['value' => 'number', 'label' => '数字'],
['value' => 'dateTime', 'label' => '日期时间'],
['value' => 'date', 'label' => '日期'],
['value' => 'time', 'label' => '时间'],
['value' => 'color', 'label' => '颜色']
])->required();
// 正则表达式(输入框)
$regexField = $this->builder->input('regex', '表单验证', $data['regex'] ?? '')
->placeholder('输入正则表达式,如:/^\d+$/')
->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '邮箱:/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/<br>手机号:/^1[3-9]\d{9}$/<br>URL:/^https?:\/\/.+/i<br>电话:/^1[3-9]\d{9}$|^0\d{2,3}-\d{7,8}$|^400-\d{3}-\d{3}$/<br>长度:/^.{6,20}$/']
]);
// 宽度字段
$col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
$widthField = $this->builder->number('width', '表单框宽', $col)->min(4)->max(24);
// 不同类型的默认值
$inputValue = $data['input_type'] == 'input' ? ($data['value'] ?? '') : '';
$inputValueField = $this->builder->input('value', '默认值', $inputValue);
$numberValue = $data['input_type'] == 'number' ? ($data['value'] ?? '0') : '';
$numberValueField = $this->builder->input('value', '默认值', $numberValue);
$dateTimeValue = $data['input_type'] == 'dateTime' ? ($data['value'] ?? date('Y-m-d H:i:s')) : '';
$dateTimeValueField = $this->builder->dateTime('value', '默认值', $dateTimeValue);
$dateValue = $data['input_type'] == 'date' ? ($data['value'] ?? date('Y-m-d')) : '';
$dateValueField = $this->builder->date('value', '默认值', $dateValue);
$timeValue = $data['input_type'] == 'time' ? ($data['value'] ?? date('H:i:s')) : '';
$timeValueField = $this->builder->time('value', '默认值', $timeValue);
$colorValue = $data['input_type'] == 'color' ? ($data['value'] ?? '#000000') : '#000000';
$colorValueField = $this->builder->color('value', '默认值', $colorValue);
// 数字类型的最小值和最大值
$numberMinField = $this->builder->input('min', '最小值', $data['min'] ?? '')->type('number');
$numberMaxField = $this->builder->input('max', '最大值', $data['max'] ?? '')->type('number');
// 根据类型联动显示不同的控件
$inputTypeSelect->appendControl('input', [$regexField, $inputValueField, $widthField]);
$inputTypeSelect->appendControl('number', [$numberMinField, $numberMaxField, $numberValueField, $widthField]);
$inputTypeSelect->appendControl('dateTime', [$dateTimeValueField]);
$inputTypeSelect->appendControl('date', [$dateValueField]);
$inputTypeSelect->appendControl('time', [$timeValueField]);
$inputTypeSelect->appendControl('color', [$colorValueField]);
return $inputTypeSelect;
}
/**
* 创建单行表单
* @param string $type
* @param array $data
* @return array
*/
public function createTextForm(string $type, array $data)
{
$formbuider = [];
$inputRule = '';
switch ($type) {
case 'number':
// 解析验证规则(支持 JSON 格式)
$requiredRules = $data['required'] ?? '';
$requiredData = json_decode($requiredRules, true);
if ($requiredData) {
// JSON 格式
$data['min'] = $requiredData['min'] ?? null;
$data['max'] = $requiredData['max'] ?? null;
} else {
// 兼容旧格式:提取 min 和 max
$data['min'] = null;
$data['max'] = null;
if (preg_match('/\bmin:(-?\d+)/', $requiredRules, $minMatch)) {
$data['min'] = (int)$minMatch[1];
}
if (preg_match('/\bmax:(-?\d+)/', $requiredRules, $maxMatch)) {
$data['max'] = (int)$maxMatch[1];
}
}
$data['value'] = isset($data['value']) ? json_decode($data['value'], true) : 0;
// 最小值和最大值提示(有值才显示)
$minMaxTip = '';
if (isset($data['min']) && $data['min'] !== null) {
$minMaxTip = '<br>最小值:' . $data['min'];
}
if (isset($data['max']) && $data['max'] !== null) {
$minMaxTip .= ($minMaxTip ? ',' : '<br>') . '最大值:' . $data['max'];
}
$col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
$inputRule = $this->builder->number($data['menu_name'], $data['info'], (float)$data['value'])->controls(false)->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc'] . $minMaxTip]
])->col($col);
break;
case 'dateTime':
$inputRule = $this->builder->dateTime($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
]);
break;
case 'date':
$data['value'] = json_decode($data['value'], true) ?: '';
$inputRule = $this->builder->date($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
]);
break;
case 'time':
$data['value'] = json_decode($data['value'], true) ?: '';
$inputRule = $this->builder->time($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
]);
break;
case 'color':
$data['value'] = isset($data['value']) ? json_decode($data['value'], true) : '';
$inputRule = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
]);
break;
default:
$data['value'] = isset($data['value']) ? json_decode($data['value'], true) : '';
// 如果配置项是api或routine_api,需要添加site_url,并且是只读的
if ($data['menu_name'] == 'api' || $data['menu_name'] == 'routine_api') {
$inputRule = $this->builder->input($data['menu_name'], $data['info'], strpos($data['value'], 'http') === false ? sys_config('site_url') . $data['value'] : $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->col($data['width'] ?? 13)->readonly(true);
} else {
// 宽宽度设置
$col = isset($data['width']) && $data['width'] != 0 && $data['width'] >= 4 && $data['width'] <= 24 ? (int)$data['width'] : 13;
$inputRule = $this->builder->input($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->col($col)->placeholder('请输入'.$data['info']);
}
break;
}
// 是否必填项
$this->isRequired($data['required']) && $inputRule = $inputRule->required($data['info'].'不能为空');
$formbuider[] = $inputRule;
return $formbuider;
}
/**
* 创建多行文本框
* @param array $data
* @return mixed
*/
private function createTextareaForm(array $data)
{
$formbuider = [];
$textareaRule = '';
$data['value'] = json_decode($data['value'], true) ?: '';
if ($data['menu_name'] == 'param_filter_data') $data['value'] = base64_decode($data['value']);
// 宽度设置
$col = isset($data['width']) && $data['width'] < 24 && $data['width'] > 4 ? $data['width'] : 13;
$textareaRule = $this->builder->textarea($data['menu_name'], $data['info'], $data['value'])->placeholder($data['desc'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->rows($data['high'] ?? 6)->col($col);
// 是否必填项
$this->isRequired($data['required']) && $textareaRule = $textareaRule->required($data['info'].'不能为空')->placeholder($data['desc']);
$formbuider[] = $textareaRule;
return $formbuider;
}
/**
* 创建单选表单
* @param array $data
* @param array $control
* @param array $control_two
* @return array
*/
private function createRadioForm(array $data, $control = [], $control_two = [], $control_three = [])
{
$formbuider = [];
$data['value'] = json_decode($data['value'], true) ?: '0';
$parameter = explode("\n", $data['parameter']);
$options = [];
if ($parameter) {
foreach ($parameter as $v) {
if (strstr($v, $this->cuttingStr) !== false) {
$pdata = explode($this->cuttingStr, $v);
$res = preg_match('/^[0-9]$/', $pdata[0]);
$options[] = ['label' => $pdata[1], 'value' => $res ? (int)$pdata[0] : $pdata[0]];
}
}
$res = preg_match('/^[0-9]$/', $data['value']);
$formbuider[] = $radio = $this->builder->radio($data['menu_name'], $data['info'], $res ? (int)$data['value'] : $data['value'])->options($options)->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->requiredNum()->col(13);
if ($control) {
$radio->appendControl($data['show_value'] ?? 1, is_array($control) ? $control : [$control]);
}
if ($control_two && isset($data['show_value2'])) {
$radio->appendControl($data['show_value2'] ?? 2, is_array($control_two) ? $control_two : [$control_two]);
}
if ($control_three && isset($data['show_value3'])) {
$radio->appendControl($data['show_value3'] ?? 3, is_array($control_three) ? $control_three : [$control_three]);
}
return $formbuider;
}
}
/**
* 创建上传组件表单
* @param int $type
* @param array $data
* @param bool $showTypeSelect 是否显示上传类型选择器
* @return array
*/
private function createUploadForm(int $type, array $data, bool $showTypeSelect = false)
{
$formbuider = [];
// 单图控件
if($type == 1){
$singleDataValue = json_decode($data['value'], true) ?: '';
if ($singleDataValue != '') $singleDataValue = set_file_url($singleDataValue);
} else{
$singleDataValue = '';
}
$singleImageField = $this->builder->frameImage($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name']], true), $singleDataValue)
->icon('el-icon-picture-outline')->width('950px')->height('560px')->Props(['footer' => false, 'modalTitle' => '预览'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc'] ?? '']
])->col(13);
// 多图控件
if($type == 2){
$multiDataValue = json_decode($data['value'], true) ?: [];
if (!empty($multiDataValue)) {
$multiDataValue = set_file_url($multiDataValue);
}
} else{
$multiDataValue = [];
}
$multiImageField = $this->builder->frameImages($data['menu_name'], $data['info'], $this->url(config('app.admin_prefix', 'admin') . '/widget.images/index', ['fodder' => $data['menu_name'], 'type' => 'many', 'maxLength' => 5], true), $multiDataValue)
->maxLength(5)->icon('el-icon-picture-outline')->width('950px')->height('560px')->Props(['footer' => false, 'modalTitle' => '预览'])
->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc'] ?? '']
])->col(13);
// 文件控件
if($type == 3){
$fileDataValue = json_decode($data['value'], true) ?: '';
if ($fileDataValue != '') $fileDataValue = set_file_url($fileDataValue);
} else{
$fileDataValue = '';
}
$fileField = $this->builder->uploadFile($data['menu_name'], $data['info'], $this->url('/adminapi/file/upload/1', ['type' => 1], false, true), $fileDataValue)
->name('file')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc'] ?? '']
])->col(13)->data(['menu_name' => $data['menu_name']])->headers([
'Authori-zation' => app()->request->header('Authori-zation'),
]);
// 如果需要显示类型选择器(编辑模式)
if ($showTypeSelect) {
// 创建上传类型的radio选择器
$uploadTypeSelect = $this->builder->radio('upload_type', '上传类型', $type)->options($this->uploadType());
// 联动:切换类型时显示对应的上传控件
$uploadTypeSelect->appendControl(1, [$singleImageField]);
$uploadTypeSelect->appendControl(2, [$multiImageField]);
$uploadTypeSelect->appendControl(3, [$fileField]);
$uploadRule = $uploadTypeSelect;
} else {
// 新建模式:根据类型只显示对应的上传控件
switch ($type) {
case 1:
// 是否必填项
$this->isRequired($data['required']) && $singleImageField = $singleImageField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_STRING))->required()->message($data['info'].'请选择图片'));
$uploadRule = $singleImageField;
break;
case 2:
// 是否必填项
$this->isRequired($data['required']) && $multiImageField = $multiImageField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_ARRAY))->required()->message($data['info'].'请选择图片'));
$uploadRule = $multiImageField;
break;
case 3:
// 是否必填项
$this->isRequired($data['required']) && $fileField = $fileField->appendValidate((new \FormBuilder\UI\Elm\Validate(\FormBuilder\UI\Elm\Validate::TYPE_STRING))->required()->message($data['info'].'请选择文件'));
$uploadRule = $fileField;
break;
}
}
$formbuider[] = $uploadRule;
return $formbuider;
}
/**
* 创建单选框
* @param array $data
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
private function createCheckboxForm(array $data)
{
$formbuider = [];
$checkboxRule = null;
$data['value'] = json_decode($data['value'], true) ?: [];
$parameter = explode("\n", $data['parameter']);
$options = [];
if ($parameter) {
foreach ($parameter as $v) {
if (strstr($v, $this->cuttingStr) !== false) {
$pdata = explode($this->cuttingStr, $v);
$options[] = ['label' => $pdata[1], 'value' => $pdata[0]];
}
}
$checkboxRule = $this->builder->checkbox($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->col(13);
}
// 是否必填项
$isRequired = $this->isRequired($data['required']);
if ($isRequired) {
$checkboxRule = $checkboxRule->required($data['info'].'至少选择一个');
}
$formbuider[] = $checkboxRule;
return $formbuider;
}
/**
* 创建选择框表单
* @param array $data
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
private function createSelectForm(array $data)
{
$formbuider = [];
$selectRule = null;
$data['value'] = json_decode($data['value'], true) ?: [];
$parameter = explode("\n", $data['parameter']);
$options = [];
if ($parameter) {
foreach ($parameter as $v) {
if (strstr($v, $this->cuttingStr) !== false) {
$pdata = explode($this->cuttingStr, $v);
$options[] = ['label' => $pdata[1], 'value' => $pdata[0]];
}
}
$selectRule = $this->builder->select($data['menu_name'], $data['info'], $data['value'])->options($options)->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->col(13);
}
// 是否必填项
$this->isRequired($data['required']) && $selectRule = $selectRule->required($data['info'].'请选择');
$formbuider[] = $selectRule;
return $formbuider;
}
/**
* 开关选择
* @param $data
* @return array
* @author: 吴汐
* @email: 442384644@qq.com
* @date: 2023/9/6
*/
private function createSwitchForm($data)
{
$formbuider = [];
$switchRule = null;
$data['value'] = json_decode($data['value'], true) ?: '';
$switchRule = $this->builder->switches($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->required($data['info'].'必选项')->col(13);
$formbuider[] = $switchRule;
return $formbuider;
}
/**
* 创建颜色选择器
* @param array $data
* @return mixed
*/
private function createColorForm(array $data)
{
$data['value'] = json_decode($data['value'], true) ?: '';
$formbuider[] = $this->builder->color($data['menu_name'], $data['info'], $data['value'])->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => $data['desc']]
])->col(13);
return $formbuider;
}
/**
* 上传类型
* @return array
*/
private function uploadType(): array
{
return [
['value' => 1, 'label' => '单图']
, ['value' => 2, 'label' => '多图']
, ['value' => 3, 'label' => '文件']
];
}
/**
* 根据验证规则判断是否必填项
* @param string $required
* @return bool
*/
private function isRequired(string $required)
{
// 支持 JSON 格式
$requiredData = json_decode($required, true);
if ($requiredData) {
return isset($requiredData['required']) && $requiredData['required'] ? true : false;
}
// 兼容旧格式:逗号分隔
return strpos($required, 'required:true') !== false;
}
/**
* 获取系统配置表单
* @param $data
* @param bool $control
* @param array $controle_two
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
*/
public function formTypeShine($data, $control = false, $controle_two = [], $controle_three = [])
{
switch ($data['type']) {
case 'text'://文本框
return $this->createTextForm($data['input_type'], $data);
case 'radio'://单选框
return $this->createRadioForm($data, $control, $controle_two, $controle_three);
case 'textarea'://多行文本框
return $this->createTextareaForm($data);
case 'upload'://文件上传
return $this->createUploadForm((int)$data['upload_type'], $data,false);
case 'checkbox'://多选框
return $this->createCheckboxForm($data);
case 'select'://多选框
return $this->createSelectForm($data);
// case 'color':
// return $this->createColorForm($data);
case 'switch'://开关
return $this->createSwitchForm($data);
}
}
/**
* 根据系统多个配置自动生成form表单页面
* @param array $list
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
private function createForm(array $list)
{
if (!$list) return [];
$list = array_combine(array_column($list, 'menu_name'), $list);
$formbuider = [];
$sonConfig = $this->getSonConfig();
$sonConfig = array_merge($sonConfig, $this->dao->getColumn(['level' => 1], 'menu_name'));
foreach ($list as $key => $data) {
if (in_array($key, $sonConfig)) {
continue;
}
switch ($data['type']) {
case 'text'://文本框
$formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
break;
case 'radio'://单选框
$relateRule = $this->relatedRule;
$builder = [];
if (!isset($relateRule[$key])) {
$relateRule = [];
$sonData = $this->dao->getColumn(['level' => 1, 'link_id' => $data['id']], 'menu_name,link_value');
$sonValue = [];
foreach ($sonData as $sv) {
$sonValue[$sv['link_value']][] = $sv['menu_name'];
}
$i = 0;
foreach ($sonValue as $pk => $pv) {
$label = $data['menu_name'];
if ($i == 1) $label = $data['menu_name'] . '@';
if ($i == 2) $label = $data['menu_name'] . '#';
$relateRule[$label]['show_value'] = (int)$pk;
foreach ($pv as $pvv) {
$relateRule[$label]['son_type'][$pvv] = '';
}
$i++;
}
} else {
$sonData = $this->dao->getColumn(['level' => 1, 'link_id' => $data['id']], 'menu_name,link_value');
if ($sonData) {
$sonValue = [];
foreach ($sonData as $sv) {
$sonValue[$sv['link_value']][] = $sv['menu_name'];
}
$i = 0;
foreach ($sonValue as $pk => $pv) {
$label = $data['menu_name'];
if ($i == 1) $label = $data['menu_name'] . '@';
if ($i == 2) $label = $data['menu_name'] . '#';
if (!isset($relateRule[$label])) {
$relateRule[$label]['show_value'] = (int)$pk;
}
foreach ($pv as $pvv) {
$relateRule[$label]['son_type'][$pvv] = '';
}
$i++;
}
}
}
if (isset($relateRule[$key])) {
$role = $relateRule[$key];
$data['show_value'] = $role['show_value'];
foreach ($role['son_type'] as $sk => $sv) {
if (isset($list[$sk])) {
$son_data = $list[$sk];
$son_data['show_value'] = $role['show_value'];
$son_build = [];
if (isset($sv['son_type'])) {
foreach ($sv['son_type'] as $ssk => $ssv) {
$son_data['show_value'] = $sv['show_value'];
$son_build[] = $this->formTypeShine($list[$ssk])[0];
unset($list[$ssk]);
}
}
$son_build_two = [];
if (isset($role['son_type'][$sk . '@'])) {
$son_type_two = $role['son_type'][$sk . '@'];
$son_data['show_value2'] = $son_type_two['show_value'];
if (isset($son_type_two['son_type'])) {
foreach ($son_type_two['son_type'] as $ssk => $ssv) {
if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color';
$son_build_two[] = $this->formTypeShine($list[$ssk])[0];
unset($list[$ssk]);
}
}
}
$son_build_three = [];
if (isset($role['son_type'][$sk . '#'])) {
$son_type_three = $role['son_type'][$sk . '#'];
$son_data['show_value3'] = $son_type_three['show_value'];
if (isset($son_type_three['son_type'])) {
foreach ($son_type_three['son_type'] as $ssk => $ssv) {
if (isset($list[$ssk]['menu_name']) && $list[$ssk]['menu_name'] == 'watermark_text_color') $list[$ssk]['type'] = 'color';
$son_build_three[] = $this->formTypeShine($list[$ssk])[0];
unset($list[$ssk]);
}
}
}
$builder[] = $this->formTypeShine($son_data, $son_build, $son_build_two, $son_build_three)[0];
unset($list[$sk]);
}
}
$data['show_value'] = $role['show_value'];
}
$builder_two = [];
if (isset($relateRule[$key . '@'])) {
$role = $relateRule[$key . '@'];
$data['show_value2'] = $role['show_value'];
foreach ($role['son_type'] as $sk => $sv) {
$son_data = $list[$sk];
$son_data['show_value'] = $role['show_value'];
$builder_two[] = $this->formTypeShine($son_data)[0];
}
}
$builder_three = [];
if (isset($relateRule[$key . '#'])) {
$role = $relateRule[$key . '#'];
$data['show_value3'] = $role['show_value'];
foreach ($role['son_type'] as $sk => $sv) {
$son_data = $list[$sk];
$son_data['show_value'] = $role['show_value'];
$builder_three[] = $this->formTypeShine($son_data)[0];
}
}
$formbuider = array_merge($formbuider, $this->createRadioForm($data, $builder, $builder_two, $builder_three));
break;
case 'textarea'://多行文本框
$formbuider = array_merge($formbuider, $this->createTextareaForm($data));
break;
case 'upload'://文件上传
$formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data,false));
break;
case 'checkbox'://多选框
$formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
break;
case 'select'://多选框
$formbuider = array_merge($formbuider, $this->createSelectForm($data));
break;
case 'switch'://开关
$formbuider = array_merge($formbuider, $this->createSwitchForm($data));
break;
}
}
return $formbuider;
}
/**
* 根据关联规则获取获取所有子配置
* @return array|int[]|string[]
* @author 吴汐
* @email 442384644@qq.com
* @date 2023/04/12
*/
public function getSonConfig()
{
$sonConfig = [];
$rolateRule = $this->relatedRule;
if ($rolateRule) {
foreach ($rolateRule as $key => $value) {
$sonConfig = array_merge($sonConfig, array_keys($value['son_type']));
foreach ($value['son_type'] as $k => $v) {
if (isset($v['son_type'])) {
$sonConfig = array_merge($sonConfig, array_keys($v['son_type']));
}
}
}
}
return $sonConfig;
}
/**无组件绑定规则
* @param array $list
* @return array|bool
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createNoCrontrolForm(array $list)
{
if (!$list) return false;
$formbuider = [];
foreach ($list as $key => $data) {
switch ($data['type']) {
case 'text'://文本框
$formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
break;
case 'radio'://单选框
$formbuider = array_merge($formbuider, $this->createRadioForm($data));
break;
case 'textarea'://多行文本框
$formbuider = array_merge($formbuider, $this->createTextareaForm($data));
break;
case 'upload'://文件上传
$formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data, true));
break;
case 'checkbox'://多选框
$formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
break;
case 'select'://多选框
$formbuider = array_merge($formbuider, $this->createSelectForm($data));
break;
case 'switch'://开关
$formbuider = array_merge($formbuider, $this->createSwitchForm($data));
break;
}
}
return $formbuider;
}
/**
* 有组件绑定规则
* @param array $list
* @param array $relatedRule
* @return array|bool
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createBindCrontrolForm(array $list, array $relatedRule)
{
if (!$list || !$relatedRule) return false;
$formbuider = [];
$new_data = array();
foreach ($list as $dk => $dv) {
$new_data[$dv['menu_name']] = $dv;
}
foreach ($relatedRule as $rk => $rv) {
if (isset($rv['son_type'])) {
$data = $new_data[$rk];
switch ($data['type']) {
case 'text'://文本框
$formbuider = array_merge($formbuider, $this->createTextForm($data['input_type'], $data));
break;
case 'radio'://单选框
$son_builder = array();
foreach ($rv['son_type'] as $sk => $sv) {
if (isset($sv['son_type'])) {
foreach ($sv['son_type'] as $ssk => $ssv) {
$son_data = $new_data[$sk];
$son_data['show_value'] = $sv['show_value'];
$son_builder[] = $this->formTypeShine($son_data, $this->formTypeShine($new_data[$ssk])[0])[0];
}
} else {
$son_data = $new_data[$sk];
$son_data['show_value'] = $rv['show_value'];
$son_builder[] = $this->formTypeShine($son_data)[0];
}
}
$formbuider = array_merge($formbuider, $this->createRadioForm($data, $son_builder));
break;
case 'textarea'://多行文本框
$formbuider = array_merge($formbuider, $this->createTextareaForm($data));
break;
case 'upload'://文件上传
$formbuider = array_merge($formbuider, $this->createUploadForm((int)$data['upload_type'], $data, false));
break;
case 'checkbox'://多选框
$formbuider = array_merge($formbuider, $this->createCheckboxForm($data));
break;
case 'select'://多选框
$formbuider = array_merge($formbuider, $this->createSelectForm($data));
break;
case 'switch'://开关
$formbuider = array_merge($formbuider, $this->createSwitchForm($data));
break;
}
}
}
return $formbuider;
}
/**
* 根据tabid获取系统配置form表单创建
* @param $url
* @param int $tabId
* @return array
* @throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getConfigForm($url, int $tabId)
{
/** @var SystemConfigTabServices $service */
$service = app()->make(SystemConfigTabServices::class);
$title = $service->value(['id' => $tabId], 'title');
$list = $this->dao->getConfigTabAllList($tabId);
$formbuider = $this->createForm($list);
$name = 'setting';
if ($url) {
$name = explode('/', $url)[2] ?? $name;
}
$postUrl = $this->postUrl[$name]['url'] ?? '/setting/config/save_basics';
return create_form($title, $formbuider, $this->url($postUrl), 'POST');
}
/**
* 新增路由增加设置项验证
* @param $url
* @param $post
* @return bool
*/
public function checkParam($url, $post)
{
$name = '';
if ($url) {
$name = explode('/', $url)[2] ?? $name;
}
$auth = $this->postUrl[$name]['auth'] ?? false;
if ($auth === false) {
throw new AdminException('请求不被允许');
}
if ($auth) {
/** @var SystemConfigTabServices $systemConfigTabServices */
$systemConfigTabServices = app()->make(SystemConfigTabServices::class);
foreach ($post as $key => $value) {
$tab_ids = $systemConfigTabServices->getColumn([['eng_title', 'IN', $auth]], 'id');
if (!$tab_ids || !in_array($key, $this->dao->getColumn([['config_tab_id', 'IN', $tab_ids]], 'menu_name'))) {
throw new AdminException('设置类目不被允许');
}
}
}
return true;
}
/**
* 添加配置字段
* @param int $type
* @param int $tab_id
* @retuarr@throws \FormBuilder\Exception\FormBuilderException
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function addFieldForm(int $type, int $tab_id): array
{
/** @var SystemConfigTabServices $service */
$service = app()->make(SystemConfigTabServices::class);
$formbuider = [];
$form_type = '';
$info_type = [];
$parameter = [];
switch ($type) {
case 0://文本框
$form_type = 'text';
$parameter[] = $this->createTextInputTypeForm(['input_type' => 'input']);
break;
case 1://多行文本框
$form_type = 'textarea';
$parameter[] = $this->builder->textarea('value', '默认值');
$parameter[] = $this->builder->number('width', '文本框宽', 100);
$parameter[] = $this->builder->number('high', '多行文本框高', 5);
break;
case 2://单选框
$form_type = 'radio';
$parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>男\n2=>女\n3=>保密")->rows(3)->placeholder("参数方式例如:\n1=>男\n2=>女\n3=>保密")->required('配置参数不能为空')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>男<br>2=>女<br>3=>保密']
]);
$parameter[] = $this->builder->input('value', '默认值');
break;
case 3://文件上传
$form_type = 'upload';
$parameter = array_merge($parameter, $this->createUploadForm(1, ['menu_name' => 'value', 'info' => '默认值', 'value' => ''], true));
break;
case 4://多选框
$form_type = 'checkbox';
$parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>白色\n2=>红色\n3=>黑色")->rows(3)->placeholder("参数方式例如:\n1=>白色\n2=>红色\n3=>黑色")->required('配置参数不能为空')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>白色<br>2=>红色<br>3=>黑色']
]);
break;
case 5://下拉框
$form_type = 'select';
$parameter[] = $this->builder->textarea('parameter', '配置参数', "1=>分类一\n2=>分类二\n3=>分类三")->rows(3)->placeholder("参数方式例如:\n1=>分类一\n2=>分类二\n3=>分类三")->required('配置参数不能为空')->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '参数说明:=>前面是参数值,后面是参数名称,每行一个参数,=>分割符不能换,例如:<br>1=>分类一<br>2=>分类二<br>3=>分类三']
]);
break;
case 6://开关
$form_type = 'switch';
$parameter[] = $this->builder->switches('value', '默认');
break;
}
if ($form_type) {
$formbuider[] = $this->builder->hidden('type', $form_type);
[$configTabList, $data] = $service->getConfigTabListForm((int)($tab_id ?? 0));
$linkData = $this->linkData($tab_id);
$formbuider[] = $this->builder->radio('level', '联动显示', 0)->options([['value' => 0, 'label' => '否'], ['value' => 1, 'label' => '是']])->requiredNum()->appendRule('suffix', [
'type' => 'div',
'class' => 'tips-info',
'domProps' => ['innerHTML' => '否:默认正常展示此配置;是:此配置默认隐藏,当选中下方对应配置的值时,此配置才会显示']
])->appendControl(1, [
$this->builder->cascader('link_data', '关联配置/值')->options($linkData)->props(['props' => ['multiple' => false, 'checkStrictly' => false, 'emitPath' => true]])->style(['width' => '100%']),
]);
$formbuider[] = $this->builder->cascader('config_tab_id', '分类', $data)->options($configTabList)->filterable(true)->props(['props' => ['multiple' => false, 'checkStrictly' => true, 'emitPath' => false]])->style(['width' => '100%']);
if ($info_type) {
$formbuider[] = $info_type;
}
$formbuider[] = $this->builder->input('info', '配置名称')->required('配置名称不能为空')->autofocus(1);
$formbuider[] = $this->builder->input('menu_name', '字段变量')->required('字段变量不能为空')->placeholder('例如:site_url');
$formbuider[] = $this->builder->input('desc', '配置简介');
$formbuider = array_merge($formbuider, $parameter);
// 是否必填
if ($form_type != 'switch') {
$formbuider[] = $this->builder->radio('required', '是否必填', 0)->options([
['value' => 0, 'label' => '否'],
['value' => 1, 'label' => '是'],
])->requiredNum();
}
$formbuider[] = $this->builder->number('sort', '排序', 0);
$formbuider[] = $this->builder->radio('status', '状态', 1)->options([['value' => 1, 'label' => '显示'], ['value' => 0, 'label' => '隐藏']])->requiredNum();
}
return create_form('添加字段', $formbuider, $this->url('/setting/config'), 'POST');
}
/**
* 联动选择关联配置/值
* 根据指定的标签ID,链接数据并以特定格式返回。
* @param $tab_id
* @return array
* @author wuhaotian
* @email 442384644@qq.com
* @date 2024/5/30
*/
public function linkData($tab_id)
{
$linkData = $this->selectList(['config_tab_id' => $tab_id, 'type' => 'radio', 'level' => 0], 'info as label,id as value,parameter,sort', 0, 0, 'sort DESC')->toArray();
foreach ($linkData as &$item) {
$parameter = [];
$parameter = explode("\n", $item['parameter']);
foreach ($parameter as $pv) {
$pvArr = explode('=>', $pv);
$item['children'][] = [
'label' => $pvArr[1],
'value' => (int)$pvArr[0]
];
}
}
return $linkData;
}
/**
* radio 和 checkbox规则的判断
* @param $data
* @return bool
*/
public function valiDateRadioAndCheckbox($data)
{
$option = [];
$option_new = [];
$data['parameter'] = str_replace("\r\n", "\n", $data['parameter']);//防止不兼容
$parameter = explode("\n", $data['parameter']);
if (count($parameter) < 2) {
throw new AdminException('请输入正确格式的配置参数');
}
foreach ($parameter as $k => $v) {
if (isset($v) && !empty($v)) {
$option[$k] = explode('=>', $v);
}
}
if (count($option) < 2) {
throw new AdminException('请输入正确格式的配置参数');
}
$bool = 1;
foreach ($option as $k => $v) {
$option_new[$k] = $option[$k][0];
foreach ($v as $kk => $vv) {
$vv_num = strlen($vv);
if (!$vv_num) {
$bool = 0;
}
}
}
if (!$bool) {
throw new AdminException('请输入正确格式的配置参数');
}
$num1 = count($option_new);//提取该数组的数目
$arr2 = array_unique($option_new);//合并相同的元素
$num2 = count($arr2);//提取合并后数组个数
if ($num1 > $num2) {
throw new AdminException('请输入正确格式的配置参数');
}
return true;
}
/**
* 验证参数
* @param $data
* @return bool
*/
public function valiDateValue($data)
{
// 检查数据和验证规则是否存在
if (!$data || !isset($data['required']) || !$data['required']) {
return true;
}
$name = $data['info'] ?? '';
$value = $data['value'] ?? '';
// 支持JSON格式的验证规则
$requiredData = json_decode($data['required'], true);
if ($requiredData) {
// JSON格式
if (isset($requiredData['required']) && $requiredData['required']) {
if ($value === '' || $value === null) {
throw new AdminException($name . '不能为空');
}
}
if (isset($requiredData['regex']) && $requiredData['regex']) {
if ($value && !preg_match($requiredData['regex'], $value)) {
throw new AdminException($name . '请输入正确的格式');
}
}
if (isset($requiredData['min']) && $value !== '' && $value !== null) {
if ((float)$value < $requiredData['min']) {
throw new AdminException($name . '不能小于' . $requiredData['min']);
}
}
if (isset($requiredData['max']) && $value !== '' && $value !== null) {
if ((float)$value > $requiredData['max']) {
throw new AdminException($name . '不能大于' . $requiredData['max']);
}
}
} else {
// 兼容旧格式:逗号分隔的字符串
$valids = explode(',', $data['required']);
foreach ($valids as $valid) {
$valid = explode(':', $valid);
if (isset($valid[0]) && isset($valid[1])) {
$k = strtolower(trim($valid[0]));
$v = strtolower(trim($valid[1]));
if ($v != 'true') {
continue;
}
switch ($k) {
case 'required':
if ($value === '' || $value === null) {
throw new AdminException($name . '不能为空');
}
break;
case 'regex':
if ($value && !preg_match($data['regex'], $value)) {
throw new AdminException($name . '请输入正确的格式');
}
break;
}
}
}
}
return true;
}
/**
* 保存平台电子面单打印信息
* @param array $data
* @return bool
*/
public function saveExpressInfo(array $data)
{
if (!is_array($data) || !$data) return false;
// config_export_id 快递公司id
// config_export_temp_id 快递公司模板id
// config_export_com 快递公司编码
// config_export_to_name 发货人姓名
// config_export_to_tel 发货人电话
// config_export_to_address 发货人详细地址
// config_export_siid 电子面单打印机编号
foreach ($data as $key => $value) {
$this->dao->update(['menu_name' => 'config_export_' . $key], ['value' => json_encode($value)]);
}
CacheService::clear();
return true;
}
/**
* 获取分享海报 兼容方法
*/
public function getSpreadBanner()
{
//配置
$banner = sys_config('spread_banner', []);
if (!$banner) {
//组合数据
$banner = sys_data('routine_spread_banner');
if ($banner) {
$banner = array_column($banner, 'pic');
$this->dao->update(['menu_name' => 'spread_banner'], ['value' => json_encode($banner)]);
CacheService::clear();
}
}
return $banner;
}
/**
* 保存wss配置
* @param int $wssOpen
* @param string $wssLocalpk
* @param string $wssLocalCert
*/
public function saveSslFilePath(int $wssOpen, string $wssLocalpk, string $wssLocalCert)
{
$wssFile = root_path() . '.wss';
$content = <<<WSS
wssOpen = $wssOpen
wssLocalpk = $wssLocalpk
wssLocalCert = $wssLocalCert
WSS;
try {
file_put_contents($wssFile, $content);
} catch (\Throwable $e) {
throw new AdminException('保存wss证书失败');
}
}
/**
* 获取wss配置
* @param string $key
* @return array|false|mixed
*/
public function getSslFilePath(string $key = '')
{
$wssFile = root_path() . '.wss';
try {
$content = parse_ini_file($wssFile);
} catch (\Throwable $e) {
$content = [];
}
return $content[$key] ?? $content;
}
/**
* 检测缩略图水印配置是否更改
* @param array $post
* @return bool
*/
public function checkThumbParam(array $post)
{
unset($post['upload_type'], $post['image_watermark_status']);
/** @var SystemConfigTabServices $systemConfigTabServices */
$systemConfigTabServices = app()->make(SystemConfigTabServices::class);
//上传配置->基础配置
$tab_id = $systemConfigTabServices->getColumn(['eng_title' => 'base_config'], 'id');
if ($tab_id) {
$all = $this->dao->getColumn(['config_tab_id' => $tab_id], 'value', 'menu_name');
if (array_intersect(array_keys($all), array_keys($post))) {
foreach ($post as $key => $item) {
//配置更改删除原来生成的缩略图
if (isset($all[$key]) && $item != json_decode($all[$key], true)) {
try {
FileService::delDir(public_path('uploads/thumb_water'));
break;
} catch (\Throwable $e) {
}
}
}
}
}
return true;
}
/**
* 变更分销绑定关系模式
* @param array $post
* @return bool
*/
public function checkBrokerageBinding(array $post)
{
try {
$config_data = $post['store_brokerage_binding_status'];
$config_one = $this->dao->getOne(['menu_name' => 'store_brokerage_binding_status']);
$config_old = json_decode($config_one['value'], true);
if ($config_old != 2 && $config_data == 2) {
//自动解绑上级绑定
/** @var AgentManageServices $agentManage */
$agentManage = app()->make(AgentManageServices::class);
$agentManage->resetSpreadTime();
}
} catch (\Throwable $e) {
Log::error('变更分销绑定模式重置绑定时间失败,失败原因:' . $e->getMessage());
return false;
}
return true;
}
/** 停用
* 根据系统配置分类自动生成form表单页面
* @param int $tabId
* @param array $formData
* @param array $relatedRule
* @return array|bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function createConfigForm(int $tabId, array $relatedRule)
{
$list = $this->dao->getConfigTabAllList($tabId);
if (!$relatedRule) {
$formbuider = $this->createNoCrontrolForm($list);
} else {
$formbuider = $this->createBindCrontrolForm($list, $relatedRule);
}
return $formbuider;
}
/** 停用
* 绑定表单数据
* @param $data
* @param $relatedRule
* @return array
*/
private function bindBuilderData($data, $relatedRule)
{
if (!$data) return false;
$p_list = array();
foreach ($relatedRule as $rk => $rv) {
$p_list[$rk] = $data[$rk];
if (isset($rv['son_type']) && is_array($rv['son_type'])) {
foreach ($rv['son_type'] as $sk => $sv) {
if (is_array($sv) && isset($sv['son_type'])) {
foreach ($sv['son_type'] as $ssk => $ssv) {
$tmp = $data[$sk];
$tmp['console'] = $data[$ssk];
$p_list[$rk]['console'][] = $tmp;
}
} else {
$p_list[$rk]['console'][] = $data[$sk];
}
}
}
}
return array_values($p_list);
}
}