feat: 初步完成详情生成

This commit is contained in:
augushong
2026-01-08 23:43:21 +08:00
parent 3fdea8b85b
commit 0e92ab2363
22 changed files with 578 additions and 247 deletions

View File

@@ -760,9 +760,9 @@ class BuildCurdServiceBase
$values = '[';
foreach ($array as $k => $v) {
$values .= "'{$k}'=>'{$v}',";
$values .= "'{$k}' => '{$v}', ";
}
$values .= ']';
$values = rtrim($values, ', ') . ']';
$selectCode = $this->replaceTemplate(
$this->getTemplate("model{$this->DS}select"),
[
@@ -774,6 +774,31 @@ class BuildCurdServiceBase
return $selectCode;
}
/**
* 构建获取器模型(用于多图片、多文件字段).
* @param $field
* @param $val
* @return mixed
*/
protected function buildAccessorModel($field, $val)
{
// 获取器名称,如 images -> ImagesListAttr
$accessorName = Str::studly($field) . 'List';
$separator = isset($val['define']) ? $val['define'] : '|';
$accessorCode = $this->replaceTemplate(
$this->getTemplate("model{$this->DS}accessor"),
[
'comment' => $val['comment'],
'accessorName' => $accessorName,
'field' => $field,
'separator' => $separator,
]
);
return $accessorCode;
}
/**
* 构建下拉框视图.
* @param $field
@@ -1179,6 +1204,7 @@ class BuildCurdServiceBase
}
$selectList = '';
$accessorList = '';
$doc_content = '';
@@ -1186,6 +1212,12 @@ class BuildCurdServiceBase
if (isset($val['formType']) && in_array($val['formType'], ['select', 'switch', 'radio', 'checkbox']) && isset($val['define'])) {
$selectList .= $this->buildSelectModel($field, $val['define']);
}
// 为多图片和多文件字段生成获取器
if (in_array($val['formType'], ['images', 'files'])) {
$accessorList .= $this->buildAccessorModel($field, $val);
}
$doc_content .= " * @property {$val['property_type']} \${$val['property_name']} {$val['comment']} {$val['data_list']}\n";
}
@@ -1207,6 +1239,7 @@ class BuildCurdServiceBase
'deleteTime' => $this->delete ? '"delete_time"' : 'false',
'relationList' => $relationList,
'selectList' => $selectList,
'accessorList' => $accessorList,
'doc_content' => $doc_content,
]
);
@@ -1467,97 +1500,7 @@ class BuildCurdServiceBase
continue;
}
$templateFile = "view{$this->DS}module{$this->DS}input";
$value = '{$row.' . $field . '|default=\'\'}';
// 根据字段类型选择不同的模板
if ($val['formType'] == 'image') {
$templateFile = "view{$this->DS}module{$this->DS}image";
} elseif ($val['formType'] == 'images') {
$templateFile = "view{$this->DS}module{$this->DS}images";
} elseif ($val['formType'] == 'file') {
$templateFile = "view{$this->DS}module{$this->DS}file";
} elseif ($val['formType'] == 'files') {
$templateFile = "view{$this->DS}module{$this->DS}files";
} elseif ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') {
$templateFile = "view{$this->DS}module{$this->DS}textarea";
$value = '{$row.' . $field . '|raw|default=\'\'}';
} elseif ($val['formType'] == 'date') {
$templateFile = "view{$this->DS}module{$this->DS}date";
if (isset($val['define']) && !empty($val['define'])) {
$define = $val['define'];
} else {
$define = 'datetime';
}
if (!in_array($define, ['year', 'month', 'date', 'time', 'datetime'])) {
$define = 'datetime';
}
} elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') {
$templateFile = "view{$this->DS}module{$this->DS}radio";
if (isset($val['define']) && !empty($val['define'])) {
$define = $this->buildRadioView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}');
}
} elseif ($val['formType'] == 'checkbox') {
$templateFile = "view{$this->DS}module{$this->DS}checkbox";
if (isset($val['define']) && !empty($val['define'])) {
$define = $this->buildCheckboxView($field, '{in name="k" value="$row.' . $field . '"}checked=""{/in}');
}
} elseif ($val['formType'] == 'select') {
$templateFile = "view{$this->DS}module{$this->DS}select";
if (isset($val['bindRelation'])) {
$define = $this->buildOptionView($val['bindRelation'], '{in name="k" value="$row.' . $field . '"}selected=""{/in}');
} elseif (isset($val['define']) && !empty($val['define'])) {
$define = $this->buildOptionView($field, '{in name="k" value="$row.' . $field . '"}selected=""{/in}');
}
} elseif ($val['formType'] == 'relation') {
$val['define']['type'] = 'radio';
$val['define']['valueField'] = 'id';
$val['define']['fieldName'] = $val['define']['relationBindSelect'];
$templateFile = "view{$this->DS}module{$this->DS}table";
$define = $this->buildTableView($field, $val, $value);
} elseif ($val['formType'] == 'table') {
$templateFile = "view{$this->DS}module{$this->DS}table";
$define = $this->buildTableView($field, $val, $value);
} elseif ($val['formType'] == 'city') {
$templateFile = "view{$this->DS}module{$this->DS}city";
$define = $this->buildCityView($field, $val, $value);
} elseif ($val['formType'] == 'tag') {
$templateFile = "view{$this->DS}module{$this->DS}tag";
}
// 直接生成详情页面的字段展示HTML使用简单的div结构
$fieldContent = '<div class="detail-field-item">';
$fieldContent .= '<div class="detail-field-label">' . $val['comment'] . '</div>';
$fieldContent .= '<div class="detail-field-value">';
// 根据字段类型处理值的显示
if ($val['formType'] == 'editor' || in_array($field, ['remark']) || $val['formType'] == 'textarea') {
$fieldContent .= '{$row.' . $field . '|raw|default=\'\'}';
} elseif ($val['formType'] == 'image') {
$fieldContent .= '<img src="{$row.' . $field . '}" class="detail-image" style="max-width: 200px; max-height: 200px;">';
} elseif ($val['formType'] == 'switch') {
$fieldContent .= '{eq name="row.' . $field . '" value="1"}启用{else/}禁用{/eq}';
} else {
$fieldContent .= '{$row.' . $field . '|default=\'\'}';
}
$fieldContent .= '</div>';
$fieldContent .= '</div>';
// 注释掉表单模板生成逻辑
/*
$fieldContent = $this->replaceTemplate(
$this->getTemplate($templateFile),
[
'comment' => $val['comment'],
'field' => $field,
'required' => '',
'required_text' => '',
'value' => $value,
'define' => $define,
]
);
*/
$fieldContent = $this->buildReadFieldContent($field, $val);
// 根据字段类型分配到不同区域
if (in_array($field, $basicFieldList)) {
@@ -1570,7 +1513,6 @@ class BuildCurdServiceBase
$viewReadValue = $this->replaceTemplate(
$this->getTemplate("view{$this->DS}read"),
[
'mainFields' => $mainFields,
'basicFields' => $basicFields,
]
@@ -1661,7 +1603,22 @@ class BuildCurdServiceBase
}
}
$indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ua.table.tool, operat: [{class: 'layui-btn layui-btn-primary layui-btn-xs', method: 'tab', field: 'id', text: '详情', title: '查看详情', auth: 'read', url: 'read', icon: ''}, 'edit', 'delete'], fixed:'right'},
$indexCols .= $this->formatColsRow("{
width: 250, title: '操作', templet: ua.table.tool, fixed: 'right', operat: [
[{
class: 'layui-btn layui-btn-primary layui-btn-xs',
method: 'tab',
field: 'id',
text: '详情',
title: '查看详情',
auth: 'read',
url: init.readUrl,
icon: ''
}],
'edit',
'delete'
]
},
");
$js_index = $this->replaceTemplate(
@@ -1884,4 +1841,79 @@ class BuildCurdServiceBase
return 'mixed';
}
/**
* 构建详情页字段内容
* @param $field
* @param $val
* @return string
*/
protected function buildReadFieldContent($field, $val)
{
$templateFile = "view{$this->DS}module{$this->DS}readText";
$define = '';
// 根据formType去获取具体的详情页模板
if ($val['formType'] == 'image') {
$templateFile = "view{$this->DS}module{$this->DS}readImage";
} elseif ($val['formType'] == 'images') {
$templateFile = "view{$this->DS}module{$this->DS}readImages";
$define = isset($val['define']) ? $val['define'] : '|';
} elseif ($val['formType'] == 'file') {
$templateFile = "view{$this->DS}module{$this->DS}readFile";
} elseif ($val['formType'] == 'files') {
$templateFile = "view{$this->DS}module{$this->DS}readFiles";
$define = isset($val['define']) ? $val['define'] : '|';
} elseif ($val['formType'] == 'editor') {
$templateFile = "view{$this->DS}module{$this->DS}readEditor";
} elseif (in_array($field, ['remark']) || $val['formType'] == 'textarea') {
$templateFile = "view{$this->DS}module{$this->DS}readTextarea";
} elseif ($val['formType'] == 'date') {
$templateFile = "view{$this->DS}module{$this->DS}readDate";
} elseif ($val['formType'] == 'radio' || $val['formType'] == 'switch') {
$templateFile = "view{$this->DS}module{$this->DS}readSwitch";
if (isset($val['define']) && !empty($val['define'])) {
// 构建下拉选择的显示值
$var_name = $this->getFieldVarName($field);
$define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}<span class="layui-badge">{volist name="' . $var_name . '" id="item"}{eq name="item.value" value="$row.' . $field . '"}{$item.label}{/eq}{/volist}</span>{/eq}{/volist}';
}
} elseif ($val['formType'] == 'checkbox') {
$templateFile = "view{$this->DS}module{$this->DS}readSelect";
if (isset($val['define']) && !empty($val['define'])) {
$var_name = $this->getFieldVarName($field);
$define = '{volist name="row.' . $field . '|explode=\',\'" id="item"><span class="layui-badge layui-badge-rim" style="margin-right: 5px;">{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$item"}{$vo.label}{/eq}{/volist}</span>{/volist}';
}
} elseif ($val['formType'] == 'select') {
$templateFile = "view{$this->DS}module{$this->DS}readSelect";
if (isset($val['bindRelation'])) {
$define = '{$row.' . $field . '}';
} elseif (isset($val['define']) && !empty($val['define'])) {
$var_name = $this->getFieldVarName($field);
$define = '{volist name="' . $var_name . '" id="vo"}{eq name="vo.value" value="$row.' . $field . '"}{$vo.label}{/eq}{/volist}';
}
} elseif ($val['formType'] == 'relation') {
// 关联表字段暂时使用文本显示
$templateFile = "view{$this->DS}module{$this->DS}readText";
} elseif ($val['formType'] == 'table') {
// 表格选择器暂时使用文本显示
$templateFile = "view{$this->DS}module{$this->DS}readText";
} elseif ($val['formType'] == 'city') {
// 城市选择器暂时使用文本显示
$templateFile = "view{$this->DS}module{$this->DS}readText";
} elseif ($val['formType'] == 'tag') {
// 标签暂时使用文本显示
$templateFile = "view{$this->DS}module{$this->DS}readText";
}
$fieldContent = $this->replaceTemplate(
$this->getTemplate($templateFile),
[
'comment' => $val['comment'],
'field' => $field,
'define' => $define,
]
);
return $fieldContent;
}
}

View File

@@ -1,2 +1,6 @@
$this->assign('{{var_name}}', $this->model::{{name}}, true);
${{var_name}}_list = [];
foreach ($this->model::{{name}} as $key => $value) {
${{var_name}}_list[] = ['value' => $key, 'label' => $value];
}
$this->assign('{{var_name}}', ${{var_name}}_list, true);

View File

@@ -4,7 +4,8 @@ var init = {
indexUrl: '{{controllerUrl}}/index',
addUrl: '{{controllerUrl}}/add' + location.search,
editUrl: '{{controllerUrl}}/edit',
readUrl: '{{controllerUrl}}/read',
deleteUrl: '{{controllerUrl}}/delete',
exportUrl: '{{controllerUrl}}/export',
modifyUrl: '{{controllerUrl}}/modify',
};
};

View File

@@ -0,0 +1,12 @@
/**
* {{comment}}获取器
* @param $value
* @return array
*/
public function get{{accessorName}}Attr($value, $data)
{
if (empty($data['{{field}}'])) {
return [];
}
return explode('{{separator}}', $data['{{field}}']);
}

View File

@@ -15,7 +15,7 @@ class {{modelName}} extends TimeModel
protected $deleteTime = {{deleteTime}};
{{selectList}}
{{accessorList}}
{{relationList}}
}
}

View File

@@ -0,0 +1,10 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}"}
{$row.{{field}}|date="Y-m-d H:i:s"}
{else/}
<span class="layui-text-em">暂无数据</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,10 @@
<div class="detail-field-item detail-field-full">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value detail-editor-content">
{notempty name="row.{{field}}"}
{$row.{{field}}|raw}
{else/}
<span class="layui-text-em">暂无内容</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,13 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}"}
<a href="{$row.{{field}}}" target="_blank" class="layui-btn layui-btn-xs layui-btn-normal">
<i class="layui-icon layui-icon-download-circle"></i> 下载文件
</a>
<div style="margin-top: 5px; color: #999; font-size: 12px;">{$row.{{field}}}</div>
{else/}
<span class="layui-text-em">暂无文件</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,17 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}_list"}
{volist name="row.{{field}}_list" id="file"}
<div style="margin-bottom: 8px;">
<a href="{$file}" target="_blank" class="layui-btn layui-btn-xs layui-btn-normal">
<i class="layui-icon layui-icon-download-circle"></i> 文件 {$key + 1}
</a>
<span style="margin-left: 10px; color: #999; font-size: 12px;">{$file}</span>
</div>
{/volist}
{else/}
<span class="layui-text-em">暂无文件</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,10 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}"}
<img src="{$row.{{field}}}" class="detail-image" style="max-width: 300px; max-height: 300px; border-radius: 4px; cursor: pointer;" onclick="layer.photos({photos: {data: [{src: this.src}]}, anim: 5})">
{else/}
<span class="layui-text-em">暂无图片</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,12 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}_list"}
{volist name="row.{{field}}_list" id="img"}
<img src="{$img}" class="detail-image" style="max-width: 150px; max-height: 150px; margin-right: 10px; margin-bottom: 10px; border-radius: 4px; cursor: pointer;" onclick="layer.photos({photos: {data: {volist name='row.{{field}}_list' id='imgItem'}[{src: '{$imgItem}'}{notlast},{/notlast}]{/volist}}, start: {$key}}, anim: 5})">
{/volist}
{else/}
<span class="layui-text-em">暂无图片</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{{define}}
</div>
</div>

View File

@@ -0,0 +1,6 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{{define}}
</div>
</div>

View File

@@ -0,0 +1,10 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value">
{notempty name="row.{{field}}"}
{$row.{{field}}}
{else/}
<span class="layui-text-em">暂无数据</span>
{/notempty}
</div>
</div>

View File

@@ -0,0 +1,10 @@
<div class="detail-field-item">
<div class="detail-field-label">{{comment}}</div>
<div class="detail-field-value" style="white-space: pre-wrap;">
{notempty name="row.{{field}}"}
{$row.{{field}}|raw}
{else/}
<span class="layui-text-em">暂无内容</span>
{/notempty}
</div>
</div>