10 Commits

Author SHA1 Message Date
wolfcode
9a0ff912b5 feat(mall):新增表单中多选案例 add simulated multi-select feature
- Add simulated multi-select functionality to goods add and edit pages
- Integrate xm-select library for multi-select implementation
- Add random color theme to the multi-select dropdown
- Include predefined options for demonstration purposes
2025-04-18 15:16:06 +08:00
wolfcode
517fd191d3 refactor(curd): improve relation handling and query methods
- Replace with() with withJoin() for more efficient left joins
- Fix foreign key and primary key assignments in relations
- Update index page queries to use relation index method-Modify relation method generation in model to use belongsTo instead of hasOne- Adjust table column definitions for relation fields
2025-04-17 17:25:06 +08:00
wolfcode
d1dfa8b49b Update app.php 2025-04-16 18:40:37 +08:00
wolfcode
c819751a66 chore: update .gitignore files
- Extend and runtime .gitignore: add space after '!' in .gitignore
- Root .gitignore: remove .project file
2025-04-16 18:38:53 +08:00
wolfcode
3a2ee69d0f feat(curd): 关联表优化支持 add relation support and optimize model associations
- Add support for handling relations in CURD operations
- Optimize model associations to use hasOne instead of belongsTo
- Implement field selection for relations
- Update controller to handle AJAX requests and return JSON data Modify model to include relation methods
2025-04-16 15:28:41 +08:00
wolfcode
d513177c74 feat(easy-admin): improve AI suggestion display and typing effect
- Adjust the width of AI suggestion popup for mobile devices
- Implement a more realistic typing effect for AI-generated content
- Remove the 'fluid' class from the 'AI optimization' button in goods edit page
2025-04-11 15:23:15 +08:00
wolfcode
0705b9a38d Update public.css 2025-04-10 18:30:57 +08:00
wolfcode
feb26660e8 style(admin): adjust table cell height and line height
- Set table cell height to 47px instead of100%
- Set table cell line-height to 40px
2025-04-10 16:51:57 +08:00
wolfcode
b8ccf1542b feat(curd):支持CURD自动生成回收站功能 add recycle functionality for soft deleted items
- Add recycle method to Curd trait for restoring or permanently deleting items
- Implement recycle view and update index view to include recycle button-Add recycle URL and functionality to JavaScript table initialization
- Create new recycle template files for view and JavaScript
2025-04-08 10:43:27 +08:00
wolfcode
74122885f1 feat(mall): 新增回收站功能 add recycle functionality for goods
- Add recycle feature to goods management
- Implement recycle button in toolbar
- Create recycle page for deleted goods
- Add functionality to restore or permanently delete goods
2025-04-07 13:44:12 +08:00
20 changed files with 347 additions and 58 deletions

2
.gitignore vendored
View File

@@ -9,4 +9,4 @@ Thumbs.db
/vendor
/.settings
/.buildpath
/.project
/.project

View File

@@ -355,6 +355,7 @@ class BuildCurd
if (!empty($bindSelectField) && !in_array($bindSelectField, array_column($columns, 'Field'))) {
throw new TableException("关联表{$relationTable}不存在该字段: {$bindSelectField}");
}
$onlyFields = [];
foreach ($columns as $vo) {
if (empty($primaryKey) && $vo['Key'] == 'PRI') {
$primaryKey = $vo['Field'];
@@ -362,6 +363,7 @@ class BuildCurd
if (!empty($onlyShowFields) && !in_array($vo['Field'], $onlyShowFields)) {
continue;
}
if (!empty($onlyShowFields)) $onlyFields[] = $vo['Field'];
$colum = [
'type' => $vo['Type'],
'comment' => $vo['Comment'],
@@ -388,6 +390,7 @@ class BuildCurd
'bindSelectField' => $bindSelectField,
'delete' => $delete,
'tableColumns' => $formatColumns,
'onlyFields' => $onlyFields,
];
if (!empty($bindSelectField)) {
$relationArray = explode('\\', $modelFilename);
@@ -1038,7 +1041,7 @@ class BuildCurd
$relationCode = '';
foreach ($this->relationArray as $key => $val) {
$relation = CommonTool::lineToHump($key);
$relationCode = "->withJoin('{$relation}', 'LEFT')\r";
$relationCode = "withJoin('{$relation}', 'LEFT')";
if (!empty($val['bindSelectField']) && !empty($val['primaryKey'])) {
$constructRelation = '$notes["' . lcfirst($val['foreignKey']) . '"] = \app\admin\model\\' . $val['modelFilename'] . '::column("' . $val['bindSelectField'] . '", "' . $val['primaryKey'] . '");';
}
@@ -1092,16 +1095,17 @@ class BuildCurd
$relationList = '';
if (!empty($this->relationArray)) {
foreach ($this->relationArray as $key => $val) {
$relation = CommonTool::lineToHump($key);
// $relationCode = CommonTool::replaceTemplate(
// $this->getTemplate("model{$this->DS}relation"),
// [
// 'relationMethod' => $relation,
// 'relationModel' => "\app\admin\model\\{$val['modelFilename']}",
// 'foreignKey' => $val['foreignKey'],
// 'primaryKey' => $val['primaryKey'],
// ]);
// $relationList .= $relationCode;
$relation = CommonTool::lineToHump($key);
$relationCode = CommonTool::replaceTemplate(
$this->getTemplate("model{$this->DS}relation"),
[
'relationMethod' => $relation,
'relationModel' => "{$val['modelFilename']}::class",
'foreignKey' => $val['foreignKey'],
'primaryKey' => $val['primaryKey'],
'relationFields' => empty($val['onlyFields']) ? "" : "->field('{$val['primaryKey']}," . implode(',', $val['onlyFields']) . "')",
]);
$relationList .= $relationCode;
}
}
@@ -1343,6 +1347,15 @@ class BuildCurd
);
$this->fileList[$viewEditFile] = $viewEditValue;
$viewRecycleFile = "{$this->rootDir}app{$this->DS}admin{$this->DS}view{$this->DS}{$this->viewFilename}{$this->DS}recycle.html";
$viewRecycleValue = CommonTool::replaceTemplate(
$this->getTemplate("view{$this->DS}recycle"),
[
'controllerUrl' => $this->controllerUrl,
'notesScript' => $this->formatNotesScript(),
]
);
$this->fileList[$viewRecycleFile] = $viewRecycleValue;
return $this;
}
@@ -1363,7 +1376,7 @@ class BuildCurd
$templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.image}";
} elseif ($val['formType'] == 'datetime') {
$templateValue = "{field: '{$field}', search: 'range', title: '{$val['comment']}'}";
} elseif ($val['formType'] == 'images') {
} elseif ($val['formType'] == 'images') {
continue;
} elseif ($val['formType'] == 'file') {
$templateValue = "{field: '{$field}', title: '{$val['comment']}', templet: ea.table.url}";
@@ -1390,13 +1403,12 @@ class BuildCurd
} else {
$templateValue = "{field: '{$field}', title: '{$val['comment']}'}";
}
$indexCols .= $this->formatColsRow("{$templateValue},\r");
}
// 关联表
foreach ($this->relationArray as $table => $tableVal) {
$table = CommonTool::lineToHump($table);
$table = CommonTool::humpToLine($table);
foreach ($tableVal['tableColumns'] as $field => $val) {
if ($val['formType'] == 'image') {
$templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', templet: ea.table.image}";
@@ -1417,20 +1429,22 @@ class BuildCurd
} elseif (in_array($field, $this->sortFields)) {
$templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}', edit: 'text'}";
} else {
$templateValue = "";
$templateValue = "{field: '{$table}.{$field}', title: '{$val['comment']}'}";
}
if ($templateValue) $indexCols .= $this->formatColsRow("{$templateValue},\r");
}
}
$indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ea.table.tool},\r");
$recycleCols = $indexCols;
$indexCols .= $this->formatColsRow("{width: 250, title: '操作', templet: ea.table.tool},\r");
$jsValue = CommonTool::replaceTemplate(
$this->getTemplate("static{$this->DS}js"),
[
'controllerUrl' => $this->controllerUrl,
'indexCols' => $indexCols,
'recycleCols' => $recycleCols,
]
);
$this->fileList[$jsFile] = $jsValue;

View File

@@ -17,8 +17,9 @@ class {{controllerName}} extends AdminController
{
parent::__construct($app);
self::$model = {{modelFilename}}::class;
$this->notes = $notes = self::$model::$notes;
$notes = self::$model::$notes;
{{constructRelation}}
$this->notes =$notes;
$this->assign(compact('notes'));
}

View File

@@ -0,0 +1,21 @@
#[NodeAnnotation(title: '列表', auth: true)]
public function index(\app\Request $request): \think\response\Json|string
{
if ($request->isAjax()) {
if (input('selectFields')) {
return $this->selectList();
}
list($page, $limit, $where) = $this->buildTableParams();
$count = self::$model::where($where)->{{relationIndexMethod}}->count();
$list = self::$model::where($where)->{{relationIndexMethod}}->page($page, $limit)->order($this->sort)->select()->toArray();
$data = [
'code' => 0,
'msg' => '',
'count' => $count,
'data' => $list,
];
return json($data);
}
return $this->fetch();
}

View File

@@ -18,4 +18,6 @@ class {{modelName}} extends TimeModel
public static array $notes = {{selectArrays}};
{{relationList}}
}

View File

@@ -1,5 +1,5 @@
public function {{relationMethod}}()
{
return $this->belongsTo('{{relationModel}}', '{{foreignKey}}', '{{primaryKey}}');
return $this->belongsTo({{relationModel}}, '{{foreignKey}}', '{{primaryKey}}'){{relationFields}};
}

View File

@@ -9,6 +9,7 @@ define(["jquery", "easy-admin"], function ($, ea) {
delete_url: '{{controllerUrl}}/delete',
export_url: '{{controllerUrl}}/export',
modify_url: '{{controllerUrl}}/modify',
recycle_url: '{{controllerUrl}}/recycle',
};
return {
@@ -29,5 +30,62 @@ define(["jquery", "easy-admin"], function ($, ea) {
edit: function () {
ea.listen();
},
recycle: function () {
init.index_url = init.recycle_url;
ea.table.render({
init: init,
toolbar: ['refresh',
[{
class: 'layui-btn layui-btn-sm',
method: 'get',
field: 'id',
icon: 'fa fa-refresh',
text: '全部恢复',
title: '确定恢复?',
auth: 'recycle',
url: init.recycle_url + '?type=restore',
checkbox: true
}, {
class: 'layui-btn layui-btn-danger layui-btn-sm',
method: 'get',
field: 'id',
icon: 'fa fa-delete',
text: '彻底删除',
title: '确定彻底删除?',
auth: 'recycle',
url: init.recycle_url + '?type=delete',
checkbox: true
}], 'export',
],
cols: [[
{{recycleCols}}
{
width: 250,
title: '操作',
templet: ea.table.tool,
operat: [
[{
title: '确认恢复?',
text: '恢复数据',
filed: 'id',
url: init.recycle_url + '?type=restore',
method: 'get',
auth: 'recycle',
class: 'layui-btn layui-btn-xs layui-btn-success',
}, {
title: '想好了吗?',
text: '彻底删除',
filed: 'id',
method: 'get',
url: init.recycle_url + '?type=delete',
auth: 'recycle',
class: 'layui-btn layui-btn-xs layui-btn-normal layui-bg-red',
}]]
}
]],
});
ea.listen();
},
};
});

View File

@@ -4,6 +4,7 @@
data-auth-add="{:auth('{{controllerUrl}}/add')}"
data-auth-edit="{:auth('{{controllerUrl}}/edit')}"
data-auth-delete="{:auth('{{controllerUrl}}/delete')}"
data-auth-recycle="{:auth('{{controllerUrl}}/recycle')}"
lay-filter="currentTable">
<!-- searchTableShow="false" 隐藏搜索框 -->
</table>

View File

@@ -0,0 +1,13 @@
<div class="layuimini-container">
<div class="layuimini-main">
<table id="currentTable" class="layui-table layui-hide"
data-auth-recycle="{:auth('{{controllerUrl}}/recycle')}"
lay-filter="currentTable">
<!-- searchTableShow="false" 隐藏搜索框 -->
</table>
</div>
</div>
<script>
{{notesScript}}
</script>

View File

@@ -5,6 +5,7 @@ namespace app\admin\traits;
use app\admin\service\annotation\NodeAnnotation;
use app\admin\service\tool\CommonTool;
use app\Request;
use think\db\exception\PDOException;
use think\facade\Db;
use think\response\Json;
@@ -154,4 +155,49 @@ trait Curd
$this->success('保存成功');
}
#[NodeAnnotation(title: '回收站', auth: true)]
public function recycle(Request $request): Json|string
{
if (!$request->isAjax()) {
return $this->fetch();
}
$id = $request->param('id', []);
$type = $request->param('type', '');
$deleteTimeField = (new self::$model)->getOption('deleteTime'); // 获取软删除字段
$defaultErrorMsg = 'Model 中未设置软删除 deleteTime 对应字段 或 数据表中不存在该字段';
if (!$deleteTimeField) $this->success($defaultErrorMsg);
switch ($type) {
case 'restore':
self::$model::withTrashed()->whereIn('id', $id)->strict(false)->update([$deleteTimeField => null, 'update_time' => time()]);
$this->success('success');
break;
case 'delete':
self::$model::destroy($id, true);
$this->success('success');
break;
default:
list($page, $limit, $where) = $this->buildTableParams();
try {
$count = self::$model::withTrashed()->where($where)->whereNotNull($deleteTimeField)->count();
$list = self::$model::withTrashed()->where($where)->page($page, $limit)->order($this->sort)->whereNotNull($deleteTimeField)->select()->toArray();
$data = [
'code' => 0,
'msg' => '',
'count' => $count,
'data' => $list,
];
} catch (\Throwable $e) {
$error = $e->getMessage();
if ($e instanceof PDOException) $error .= '<br>' . $defaultErrorMsg;
$data = [
'code' => -1,
'msg' => $error,
'count' => 0,
'data' => [],
];
}
return json($data);
}
}
}

View File

@@ -91,6 +91,14 @@
</div>
</div>
<!-- 文档https://xm-select.com/file/xm-select/v1.2.4/#/basic/use -->
<div class="layui-form-item">
<label class="layui-form-label">模拟多选</label>
<div class="layui-input-block">
<div id="demo1" class="xm-select-demo"></div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注信息</label>
<div class="layui-input-block">

View File

@@ -35,7 +35,7 @@
</div>
</div>
<div class="layui-col-xs2">
<button class="layui-btn layui-bg-purple layui-btn-fluid" type="button" lay-on="AiOptimization">AI优化</button>
<button class="layui-btn layui-bg-purple" type="button" lay-on="AiOptimization">AI优化</button>
</div>
</div>
</div>
@@ -92,6 +92,14 @@
</div>
</div>
<!-- 文档https://xm-select.com/file/xm-select/v1.2.4/#/basic/use -->
<div class="layui-form-item">
<label class="layui-form-label">模拟多选</label>
<div class="layui-input-block">
<div id="demo1" class="xm-select-demo"></div>
</div>
</div>
<div class="layui-form-item layui-form-text">
<label class="layui-form-label">备注信息</label>
<div class="layui-input-block">

View File

@@ -5,6 +5,7 @@
data-auth-edit="{:auth('mall.goods/edit')}"
data-auth-delete="{:auth('mall.goods/delete')}"
data-auth-stock="{:auth('mall.goods/stock')}"
data-auth-recycle="{:auth('mall.goods/recycle')}"
lay-filter="currentTable">
</table>
</div>

View File

@@ -0,0 +1,11 @@
<div class="layuimini-container">
<div class="layuimini-main">
<table id="currentTable" class="layui-table layui-hide"
data-auth-recycle="{:auth('mall.goods/recycle')}"
lay-filter="currentTable">
</table>
</div>
</div>
<script>
let cateSelects = JSON.parse('{$cate|json_encode=256|raw}')
</script>

2
extend/.gitignore vendored
View File

@@ -1,2 +1,2 @@
*
!.gitignore
!.gitignore

View File

@@ -75,8 +75,8 @@ body {
/**重写layui表格自适应*/
.layuimini-container .layui-table-cell {
height: 100%;
max-width: 100%;
height: 50px;
line-height: 42px;
}
/**数据表格-搜索表单样式*/

View File

@@ -10,6 +10,7 @@ define(["jquery", "easy-admin"], function ($, ea) {
export_url: 'mall.goods/export',
modify_url: 'mall.goods/modify',
stock_url: 'mall.goods/stock',
recycle_url: 'mall.goods/recycle',
};
return {
@@ -27,7 +28,7 @@ define(["jquery", "easy-admin"], function ($, ea) {
icon: 'fa fa-plus ',
extend: 'data-width="90%" data-height="95%"',
}],
'delete', 'export'],
'delete', 'export', 'recycle'],
cols: [[
{type: "checkbox"},
{field: 'id', width: 80, title: 'ID', searchOp: '='},
@@ -92,6 +93,25 @@ define(["jquery", "easy-admin"], function ($, ea) {
aiOptimization(data)
},
})
let colors = [
'#f10f0f', // 红色
'#ffaf00', // 橙色
'#FF69B4', // 猛男粉
'#0087ff', // 蓝色
'#00ff00', // 青青草原
];
var demo1 = xmSelect.render({
el: '#demo1',
name: 'xxx', // form表单提交的name
theme: {color: colors[Math.floor(Math.random() * colors.length)]},
data: [
{name: 'Make', value: 1},
{name: 'PHP', value: 2},
{name: 'Great Again', value: 3},
]
})
ea.listen();
},
edit: function () {
@@ -102,11 +122,102 @@ define(["jquery", "easy-admin"], function ($, ea) {
aiOptimization(data)
},
})
let colors = [
'#f10f0f', // 红色
'#ffaf00', // 橙色
'#FF69B4', // 猛男粉
'#0087ff', // 蓝色
'#00ff00', // 青青草原
];
var demo1 = xmSelect.render({
el: '#demo1',
name: 'xxx', // form表单提交的name
theme: {color: colors[Math.floor(Math.random() * colors.length)]},
data: [
{name: 'Make', value: 1},
{name: 'PHP', value: 2, selected: true,},
{name: 'Great Again', value: 3, selected: true,},
]
})
ea.listen();
},
stock: function () {
ea.listen();
},
recycle: function () {
init.index_url = init.recycle_url;
ea.table.render({
init: init,
toolbar: ['refresh',
[{
class: 'layui-btn layui-btn-sm',
method: 'get',
field: 'id',
icon: 'fa fa-refresh',
text: '全部恢复',
title: '确定恢复?',
auth: 'recycle',
url: init.recycle_url + '?type=restore',
checkbox: true
}, {
class: 'layui-btn layui-btn-danger layui-btn-sm',
method: 'get',
field: 'id',
icon: 'fa fa-delete',
text: '彻底删除',
title: '确定彻底删除?',
auth: 'recycle',
url: init.recycle_url + '?type=delete',
checkbox: true
}], 'export',
],
cols: [[
{type: "checkbox"},
{field: 'id', width: 80, title: 'ID', searchOp: '='},
{field: 'sort', width: 80, title: '排序', edit: 'text'},
{field: 'cate_id', minWidth: 80, title: '商品分类', search: 'select', selectList: cateSelects, laySearch: true},
{field: 'title', minWidth: 80, title: '商品名称'},
{field: 'logo', minWidth: 80, title: '分类图片', search: false, templet: ea.table.image},
{field: 'status', title: '状态', width: 85, selectList: {0: '禁用', 1: '启用'}},
// 演示多选,实际数据库并无 status2 字段,搜索后会报错
{
field: 'status2', title: '演示多选', width: 105, search: 'xmSelect', selectList: {1: '模拟选项1', 2: '模拟选项2', 3: '模拟选项3', 4: '模拟选项4', 5: '模拟选项5'},
searchOp: 'in', templet: function (res) {
// 根据自己实际项目进行输出
return res?.status2 || '模拟数据'
}
},
{field: 'create_time', minWidth: 80, title: '创建时间', search: 'range'},
{field: 'delete_time', minWidth: 80, title: '删除时间', search: 'range'},
{
width: 250,
title: '操作',
templet: ea.table.tool,
operat: [
[{
title: '确认恢复?',
text: '恢复数据',
filed: 'id',
url: init.recycle_url + '?type=restore',
method: 'get',
auth: 'recycle',
class: 'layui-btn layui-btn-xs layui-btn-success',
}, {
title: '想好了吗?',
text: '彻底删除',
filed: 'id',
method: 'get',
url: init.recycle_url + '?type=delete',
auth: 'recycle',
class: 'layui-btn layui-btn-xs layui-btn-normal layui-bg-red',
}]]
}
]],
});
ea.listen();
},
};
function aiOptimization(data) {

View File

@@ -253,7 +253,7 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
}
// 初始化表格左上方工具栏
options.toolbar = options.toolbar || ['refresh', 'add', 'delete', 'export'];
options.toolbar = options.toolbar || ['refresh', 'add', 'delete', 'export', 'recycle'];
options.toolbar = admin.table.renderToolbar(options.toolbar, options.elem, options.id, options.init);
// 判断是否有操作列表权限
@@ -312,6 +312,14 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
if (admin.checkAuth('export', elem)) {
toolbarHtml += '<button class="layui-btn layui-btn-sm layui-btn-success easyadmin-export-btn" data-url="' + init.export_url + '" data-table-export="' + tableId + '"><i class="fa fa-file-excel-o"></i> 导出</button>\n';
}
} else if (v === 'recycle') {
if (init.recycle_url === undefined) {
console.warn('未定义回收站地址 init.recycle_url')
return false
}
if (admin.checkAuth('recycle', elem)) {
toolbarHtml += '<button class="layui-btn layui-btn-sm layui-bg-orange" data-open="' + init.recycle_url + '" data-title="回收站"><i class="fa fa-recycle"></i> 回收站</button>\n';
}
} else if (typeof v === "object") {
$.each(v, function (ii, vv) {
vv.class = vv.class || '';
@@ -1785,7 +1793,7 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
layer.open({
'title': options?.title || 'AI建议',
type: 1,
area: options?.area || ['42%', '60%'],
area: options?.area || (admin.checkMobile() ? ['95%', '60%'] : ['50%', '60%']),
shade: options?.shade || 0,
shadeClose: options?.shadeClose || false,
scrollbar: options?.scrollbar || false,
@@ -1795,11 +1803,23 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
success: function (layero, index) {
let elem = document.getElementById(id)
if (options?.stream) {
clearTimeout(aiStreamTimeout)
aiStreamCurrentIndex = 0
setTimeout(() => {
admin.ai.streamOutput(elem, content)
}, 300)
let index = 0;
let lastTime = performance.now();
const interval = options.interval || 100;
function typeCharacter(currentTime) {
if (index < content.length) {
if (currentTime - lastTime >= interval) {
elem.innerHTML += content.charAt(index);
index++;
lastTime = currentTime;
elem.scrollIntoView({behavior: "smooth", block: "end"});
}
requestAnimationFrame(typeCharacter);
}
}
requestAnimationFrame(typeCharacter);
} else {
content = content.replace(/\r\n/g, '<br>').replace(/\n/g, '<br>')
setTimeout(() => {
@@ -1812,28 +1832,8 @@ define(["jquery", "tableSelect", "miniTheme", "xmSelect", "lazyload"], function
}
})
},
streamOutput: function (dom, htmlContent) {
const chunkSize = 1;
let length = htmlContent.length;
if (aiStreamCurrentIndex < length) {
const endIndex = Math.min(aiStreamCurrentIndex + chunkSize, length);
const chunk = htmlContent.slice(aiStreamCurrentIndex, endIndex);
const tempDiv = document.createElement('div');
tempDiv.innerHTML = chunk;
while (tempDiv.firstChild) {
dom.appendChild(tempDiv.firstChild);
}
aiStreamCurrentIndex = endIndex;
aiStreamTimeout = setTimeout(() => {
admin.ai.streamOutput(dom, htmlContent);
dom.scrollIntoView({behavior: "smooth", block: "end"});
}, 60);
}
}
},
};
var aiStreamCurrentIndex = 0;
var aiStreamTimeout = null;
return admin;
});

View File

@@ -10,10 +10,4 @@
// +----------------------------------------------------------------------
use think\facade\Route;
Route::get('think', function () {
return 'hello,ThinkPHP6!';
});
Route::get('hello/:name', 'index/hello');
Route::any('install', '\app\index\controller\Install@index');

2
runtime/.gitignore vendored
View File

@@ -1,2 +1,2 @@
*
!.gitignore
!.gitignore