mirror of
https://gitee.com/ulthon/ulthon_admin.git
synced 2026-07-07 02:22:48 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
008e781d6b | ||
|
|
b04321e380 |
@@ -10,6 +10,7 @@ use app\admin\service\TriggerService;
|
|||||||
use app\common\constants\MenuConstant;
|
use app\common\constants\MenuConstant;
|
||||||
use app\common\controller\AdminController;
|
use app\common\controller\AdminController;
|
||||||
use think\App;
|
use think\App;
|
||||||
|
use think\facade\Db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class Menu.
|
* Class Menu.
|
||||||
@@ -216,4 +217,68 @@ class MenuBase extends AdminController
|
|||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NodeAnotation(title="导出")
|
||||||
|
*/
|
||||||
|
public function export()
|
||||||
|
{
|
||||||
|
$list_menu_json = SystemMenu::select()->hidden([
|
||||||
|
'create_time',
|
||||||
|
'update_time',
|
||||||
|
'delete_time',
|
||||||
|
])->toJson();
|
||||||
|
|
||||||
|
$download = $this->request->param('download');
|
||||||
|
if ($download == 1) {
|
||||||
|
$file_name = 'admin_menu.json';
|
||||||
|
$file_name = $this->request->host() . '_' . $file_name;
|
||||||
|
|
||||||
|
return download($list_menu_json, $file_name, true, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assign('list_menu_json', $list_menu_json);
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @NodeAnotation(title="import")
|
||||||
|
*/
|
||||||
|
public function import()
|
||||||
|
{
|
||||||
|
if ($this->request->isPost()) {
|
||||||
|
$data = $this->request->post('data');
|
||||||
|
$data_arr = json_decode($data, true);
|
||||||
|
|
||||||
|
$rule = [
|
||||||
|
'pid|上级菜单' => 'require',
|
||||||
|
'title|菜单名称' => 'require',
|
||||||
|
'icon|菜单图标' => 'require',
|
||||||
|
];
|
||||||
|
foreach ($data_arr as $data_item) {
|
||||||
|
$this->validate($data_item, $rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
Db::startTrans();
|
||||||
|
try {
|
||||||
|
$list_old_menu = SystemMenu::withTrashed()->select();
|
||||||
|
foreach ($list_old_menu as $menu) {
|
||||||
|
$menu->force()->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($data_arr as $data_item) {
|
||||||
|
$menu = new SystemMenu();
|
||||||
|
$menu->save($data_item);
|
||||||
|
}
|
||||||
|
Db::commit();
|
||||||
|
} catch (\Throwable $th) {
|
||||||
|
Db::rollback();
|
||||||
|
$this->error('导入失败:' . $th->getMessage());
|
||||||
|
}
|
||||||
|
$this->success('导入成功');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->fetch();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
15
extend/base/admin/view/system/menu/export.html
Normal file
15
extend/base/admin/view/system/menu/export.html
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<form id="app-form" class="layui-form layuimini-form">
|
||||||
|
<div class="layui-form-item layui-row layui-col-xs12">
|
||||||
|
<label class="layui-form-label ">数据预览</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea id="data" class="layui-textarea" readonly>{$list_menu_json}</textarea>
|
||||||
|
<div class="layui-btn-container" style="margin-top: 5px;">
|
||||||
|
<div class="layui-btn layui-btn-sm" data-toggle="copy-text" data-clipboard-target="#data">复制</div>
|
||||||
|
<a href="{:url('export',['download'=>1])}" class="layui-btn layui-btn-sm">下载</a>
|
||||||
|
</div>
|
||||||
|
<tip>可以通过复制或下载的方式导出配置,然后在另一个系统中导入。</tip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
3
extend/base/admin/view/system/menu/export.js
Normal file
3
extend/base/admin/view/system/menu/export.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
$(function () {
|
||||||
|
ua.listen();
|
||||||
|
});
|
||||||
22
extend/base/admin/view/system/menu/import.html
Normal file
22
extend/base/admin/view/system/menu/import.html
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<div class="layuimini-container">
|
||||||
|
<form id="app-form" class="layui-form layuimini-form">
|
||||||
|
<div class="layui-form-item layui-row layui-col-xs12">
|
||||||
|
<label class="layui-form-label">数据预览</label>
|
||||||
|
<div class="layui-input-block">
|
||||||
|
<textarea id="data" name="data" class="layui-textarea"></textarea>
|
||||||
|
<div class="layui-btn-container" style="margin-top: 5px;">
|
||||||
|
<div class="layui-btn layui-btn-sm" data-toggle="paste-text" data-paste-target="#data">复制</div>
|
||||||
|
<div class="layui-btn layui-btn-sm " id="process-json-file">上传</div>
|
||||||
|
<input id="json-file-input" type="file" accept=".json" style="display: none;"/>
|
||||||
|
</div>
|
||||||
|
<tip>从另一个系统中复制或下载,导出配置文件,在本页面导入或上传即可。请不要随意编辑内容,否则可能导致出错。</tip>
|
||||||
|
<tip style="color: red;">注意:这将覆盖当前系统的配置文件,请注意导出备份。</tip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="hr-line"></div>
|
||||||
|
<div class="layui-form-item text-center">
|
||||||
|
<button type="submit" class="layui-btn layui-btn-normal layui-btn-sm" lay-submit>确认</button>
|
||||||
|
<button type="reset" class="layui-btn layui-btn-primary layui-btn-sm">重置</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
38
extend/base/admin/view/system/menu/import.js
Normal file
38
extend/base/admin/view/system/menu/import.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
$(function () {
|
||||||
|
var fileInput = document.getElementById('json-file-input');
|
||||||
|
fileInput.addEventListener('change', function (e) {
|
||||||
|
var files = e.target.files;
|
||||||
|
if (files.length > 0) {
|
||||||
|
var file = files[0];
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function (e) {
|
||||||
|
var jsonStr = e.target.result;
|
||||||
|
// 解析json字符串,判断是否出错
|
||||||
|
try {
|
||||||
|
var jsonData = JSON.parse(jsonStr);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
layer.msg('JSON 解析出错,请检查 JSON 格式是否正确。');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
$('#data').val(jsonStr);
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#process-json-file').click(function () {
|
||||||
|
|
||||||
|
|
||||||
|
fileInput.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
ua.listen(function (data) {
|
||||||
|
return data;
|
||||||
|
}, function (res) {
|
||||||
|
ua.msg.success(res.msg, function () {
|
||||||
|
var index = parent.layer.getFrameIndex(window.name);
|
||||||
|
parent.layer.close(index);
|
||||||
|
parent.$('[data-treetable-refresh]').trigger("click");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -21,4 +21,6 @@
|
|||||||
<button class="layui-btn layui-btn-sm layuimini-btn-primary" data-treetable-refresh><i class="fa fa-refresh"></i> </button>
|
<button class="layui-btn layui-btn-sm layuimini-btn-primary" data-treetable-refresh><i class="fa fa-refresh"></i> </button>
|
||||||
<button class="layui-btn layui-btn-normal layui-btn-sm {if !auth('system.menu/add')}layui-hide{/if}" data-open="system.menu/add" data-title="添加" data-full="true"><i class="fa fa-plus"></i> 添加</button>
|
<button class="layui-btn layui-btn-normal layui-btn-sm {if !auth('system.menu/add')}layui-hide{/if}" data-open="system.menu/add" data-title="添加" data-full="true"><i class="fa fa-plus"></i> 添加</button>
|
||||||
<button class="layui-btn layui-btn-sm layui-btn-danger {if !auth('system.menu/del')}layui-hide{/if}" data-url="system.menu/del" data-treetable-delete="currentTableRenderId"><i class="fa fa-trash-o"></i> 删除</button>
|
<button class="layui-btn layui-btn-sm layui-btn-danger {if !auth('system.menu/del')}layui-hide{/if}" data-url="system.menu/del" data-treetable-delete="currentTableRenderId"><i class="fa fa-trash-o"></i> 删除</button>
|
||||||
|
<button class="layui-btn layui-btn-sm {if !auth('system.menu/export')}layui-hide{/if}" data-open="system.menu/export" data-title="导出"> 导出</button>
|
||||||
|
<button class="layui-btn layui-btn-primary layui-btn-sm {if !auth('system.menu/import')}layui-hide{/if}" data-open="system.menu/import" data-title="导入"> 导入</button>
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -12,14 +12,16 @@ use think\console\Output;
|
|||||||
|
|
||||||
class VersionBase extends Command
|
class VersionBase extends Command
|
||||||
{
|
{
|
||||||
public const VERSION = 'v2.0.107';
|
public const VERSION = 'v2.0.109';
|
||||||
|
|
||||||
public const PRODUCT_VERSION = '';
|
public const PRODUCT_VERSION = '';
|
||||||
|
|
||||||
public const LAYUI_VERSION = '2.8.17';
|
public const LAYUI_VERSION = '2.8.17';
|
||||||
|
|
||||||
public const COMMENT = [
|
public const COMMENT = [
|
||||||
'更新版本提示优先自定义的路径',
|
'增加菜单到导出和导入',
|
||||||
|
'增加粘贴全局操作',
|
||||||
|
'优化表单错误表现',
|
||||||
'发布新版本',
|
'发布新版本',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ class MigrateBase extends Command
|
|||||||
->addOption('tableName', '', Option::VALUE_OPTIONAL, '要生成的表名')
|
->addOption('tableName', '', Option::VALUE_OPTIONAL, '要生成的表名')
|
||||||
->addOption('fileName', '', Option::VALUE_OPTIONAL, '要生成的文件名')
|
->addOption('fileName', '', Option::VALUE_OPTIONAL, '要生成的文件名')
|
||||||
->addOption('force', 'f', Option::VALUE_NONE, '强制生成')
|
->addOption('force', 'f', Option::VALUE_NONE, '强制生成')
|
||||||
|
->addOption('update', 'u', Option::VALUE_NONE, '生成新代码')
|
||||||
->setDescription('the curd:migrate command');
|
->setDescription('the curd:migrate command');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,6 +39,7 @@ class MigrateBase extends Command
|
|||||||
$file_name = $input->getOption('fileName');
|
$file_name = $input->getOption('fileName');
|
||||||
$table_name = $input->getOption('tableName');
|
$table_name = $input->getOption('tableName');
|
||||||
$force = $input->getOption('force');
|
$force = $input->getOption('force');
|
||||||
|
$update = $input->hasOption('update');
|
||||||
|
|
||||||
if (empty($table)) {
|
if (empty($table)) {
|
||||||
$output->error('请输入表名');
|
$output->error('请输入表名');
|
||||||
@@ -68,34 +70,33 @@ class MigrateBase extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
$dist_file_path = App::getRootPath() . '/database/migrations/' . date('YmdHis') . '_' . $file_name . '.php';
|
$dist_file_path = App::getRootPath() . '/database/migrations/' . date('YmdHis') . '_' . $file_name . '.php';
|
||||||
|
if(!$update){
|
||||||
|
$patt_path = App::getRootPath() . '/database/migrations/*' . $file_name . '.php';
|
||||||
|
$patt_files = glob($patt_path);
|
||||||
|
$is_extis = false;
|
||||||
|
foreach ($patt_files as $patt_file) {
|
||||||
|
$patt = '/.*database\/migrations\/\d+_' . $file_name . '.php$/';
|
||||||
|
|
||||||
$patt_path = App::getRootPath() . '/database/migrations/*' . $file_name . '.php';
|
$preg_result = preg_match($patt, $patt_file);
|
||||||
|
|
||||||
$patt_files = glob($patt_path);
|
if ($preg_result) {
|
||||||
|
$is_extis = true;
|
||||||
$is_extis = false;
|
|
||||||
foreach ($patt_files as $patt_file) {
|
|
||||||
$patt = '/.*database\/migrations\/\d+_' . $file_name . '.php$/';
|
|
||||||
|
|
||||||
$preg_result = preg_match($patt, $patt_file);
|
|
||||||
|
|
||||||
if ($preg_result) {
|
|
||||||
$is_extis = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($is_extis) {
|
|
||||||
$output->error('文件已存在:' . $patt_files[0]);
|
|
||||||
if (!$force) {
|
|
||||||
$confirm_force = $output->confirm($input, '确定要覆盖文件吗?', false);
|
|
||||||
|
|
||||||
if (!$confirm_force) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$output->highlight('执行覆盖操作');
|
|
||||||
|
|
||||||
$dist_file_path = $patt_files[0];
|
if ($is_extis) {
|
||||||
|
$output->error('文件已存在:' . $patt_files[0]);
|
||||||
|
if (!$force) {
|
||||||
|
$confirm_force = $output->confirm($input, '确定要覆盖文件吗?如果您想生成更新文件请添加-u参数', false);
|
||||||
|
|
||||||
|
if (!$confirm_force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$output->highlight('执行覆盖操作');
|
||||||
|
|
||||||
|
$dist_file_path = $patt_files[0];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$columns = Db::query("SHOW FULL COLUMNS FROM {$this->tablePrefix}{$this->table}");
|
$columns = Db::query("SHOW FULL COLUMNS FROM {$this->tablePrefix}{$this->table}");
|
||||||
@@ -198,6 +199,11 @@ class MigrateBase extends Command
|
|||||||
$data['table_keys'] = $table_keys;
|
$data['table_keys'] = $table_keys;
|
||||||
$data['table_keys_uni'] = $table_keys_uni;
|
$data['table_keys_uni'] = $table_keys_uni;
|
||||||
$data['table_keys_text'] = $table_keys_text;
|
$data['table_keys_text'] = $table_keys_text;
|
||||||
|
$data['method'] = 'create';
|
||||||
|
|
||||||
|
if($update){
|
||||||
|
$data['method'] = 'update';
|
||||||
|
}
|
||||||
|
|
||||||
$migrate_content = View::fetch(app_file_path('common/command/curd/migrate.tpl'), $data);
|
$migrate_content = View::fetch(app_file_path('common/command/curd/migrate.tpl'), $data);
|
||||||
|
|
||||||
@@ -205,5 +211,13 @@ class MigrateBase extends Command
|
|||||||
file_put_contents(__DIR__ . '/migrate_output.php', "<?php\n\n" . $migrate_content);
|
file_put_contents(__DIR__ . '/migrate_output.php', "<?php\n\n" . $migrate_content);
|
||||||
}
|
}
|
||||||
file_put_contents($dist_file_path, "<?php\n\n" . $migrate_content);
|
file_put_contents($dist_file_path, "<?php\n\n" . $migrate_content);
|
||||||
|
|
||||||
|
if($update){
|
||||||
|
$output->info('已为您生成数据库迁移代码的更新代码,但仍然包含了所有的字段,因此您需要删除多余的添加指令,并根据您的表结构修改更新的指令');
|
||||||
|
$output->info('请查看:'. $dist_file_path);
|
||||||
|
}else{
|
||||||
|
$output->info('已为您生成数据库迁移代码');
|
||||||
|
$output->info('请查看:'. $dist_file_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,6 @@ class {$class_name} extends Migrator
|
|||||||
{volist name="table_keys_text" id="vo"}->addIndex('{$vo}',['type'=>'fulltext'])
|
{volist name="table_keys_text" id="vo"}->addIndex('{$vo}',['type'=>'fulltext'])
|
||||||
{/volist}
|
{/volist}
|
||||||
{volist name="table_keys" id="vo"}->addIndex('{$vo}')
|
{volist name="table_keys" id="vo"}->addIndex('{$vo}')
|
||||||
{/volist}->create();
|
{/volist}->{$method}();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -171,7 +171,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
error: function (xhr, textstatus, thrown) {
|
error: function (xhr, textstatus, thrown) {
|
||||||
admin.msg.error('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!', function () {
|
var errorMsg = '';
|
||||||
|
if(xhr.responseJSON.message){
|
||||||
|
errorMsg = xhr.responseJSON.message;
|
||||||
|
}
|
||||||
|
loading.hide();
|
||||||
|
admin.msg.error('Status:' + xhr.status + ',' + xhr.statusText + ',请稍后再试!<br/>'+errorMsg, function () {
|
||||||
ex(this);
|
ex(this);
|
||||||
});
|
});
|
||||||
return false;
|
return false;
|
||||||
@@ -1570,6 +1575,9 @@
|
|||||||
// 监听点击复制
|
// 监听点击复制
|
||||||
admin.api.copyText();
|
admin.api.copyText();
|
||||||
|
|
||||||
|
// 监听点击粘贴
|
||||||
|
admin.api.pasteText();
|
||||||
|
|
||||||
// 监听tab操作
|
// 监听tab操作
|
||||||
miniTab.listen();
|
miniTab.listen();
|
||||||
|
|
||||||
@@ -2414,6 +2422,33 @@
|
|||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
pasteText(elem) {
|
||||||
|
if (elem == undefined) {
|
||||||
|
elem = 'body';
|
||||||
|
}
|
||||||
|
var list = $(elem).find('[data-toggle="paste-text"]');
|
||||||
|
|
||||||
|
$.each(list, function (i, v) {
|
||||||
|
|
||||||
|
if ($(v).hasClass('paste-rendered')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$(v).addClass('paste-rendered');
|
||||||
|
|
||||||
|
var targetElemName = $(v).data('paste-target');
|
||||||
|
$(v).on('click', function () {
|
||||||
|
navigator.clipboard.readText()
|
||||||
|
.then(text => {
|
||||||
|
$(targetElemName).val(text);
|
||||||
|
layer.msg('粘贴成功');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Failed to read clipboard contents: ', err);
|
||||||
|
layer.msg('粘贴失败,请手动粘贴');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getQueryVariable(variable, defaultValue) {
|
getQueryVariable(variable, defaultValue) {
|
||||||
|
|||||||
Reference in New Issue
Block a user