feat: 更新微应用菜单配置,统一使用类型字段替代URL类型字段

This commit is contained in:
kuaifan 2025-12-18 02:44:37 +00:00
parent 8c23192eeb
commit d77406951d
6 changed files with 111 additions and 16 deletions

View File

@ -309,13 +309,13 @@ class Setting extends AbstractModel
}
$location = trim($menu['location'] ?? 'application');
$label = trim($menu['label'] ?? $fallbackLabel);
$urlType = strtolower(trim($menu['url_type'] ?? 'iframe'));
$type = strtolower(trim($menu['type'] ?? 'iframe'));
$payload = [
'location' => $location,
'label' => $label,
'icon' => Base::newTrim($menu['icon'] ?? ''),
'url' => $url,
'url_type' => $urlType,
'type' => $type,
'keep_alive' => isset($menu['keep_alive']) ? (bool)$menu['keep_alive'] : true,
'disable_scope_css' => (bool)($menu['disable_scope_css'] ?? false),
'auto_dark_theme' => isset($menu['auto_dark_theme']) ? (bool)$menu['auto_dark_theme'] : true,

View File

@ -0,0 +1,79 @@
<?php
use App\Module\Base;
use App\Models\Setting;
use Illuminate\Database\Migrations\Migration;
class UpdateSettingMicroappMenuType extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
$row = Setting::whereName('microapp_menu')->first();
if (!$row) {
return;
}
$data = Base::string2array($row->setting);
if (empty($data) || !is_array($data)) {
return;
}
$changed = false;
foreach ($data as $appIndex => $app) {
if (!is_array($app)) {
continue;
}
$menuItems = [];
if (isset($app['menu_items']) && is_array($app['menu_items'])) {
$menuItems = $app['menu_items'];
} elseif (isset($app['menu']) && is_array($app['menu'])) {
$menuItems = [$app['menu']];
}
if (empty($menuItems)) {
continue;
}
$newMenuItems = [];
foreach ($menuItems as $menu) {
if (!is_array($menu)) {
$newMenuItems[] = $menu;
continue;
}
if (!isset($menu['type']) && isset($menu['url_type'])) {
$menu['type'] = $menu['url_type'];
unset($menu['url_type']);
$changed = true;
} elseif (isset($menu['url_type'])) {
unset($menu['url_type']);
$changed = true;
}
$newMenuItems[] = $menu;
}
if (isset($app['menu_items']) && is_array($app['menu_items'])) {
$data[$appIndex]['menu_items'] = $newMenuItems;
} elseif (isset($app['menu']) && is_array($app['menu'])) {
$data[$appIndex]['menu'] = $newMenuItems[0] ?? $app['menu'];
}
}
if ($changed) {
$row->updateInstance(['setting' => $data]);
$row->save();
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
// No-op: do not revert settings payload.
}
}

View File

@ -235,7 +235,7 @@ export default {
name: app.name,
url: app.url,
urlType: app.url_type,
type: app.type,
userId: this.userId,
userToken: this.userToken,
@ -405,13 +405,13 @@ export default {
}
// blank
if (/_blank$/i.test(config.url_type)) {
if (/_blank$/i.test(config.type)) {
await this.inlineBlank(config)
return
}
//
if (config.url_type === 'external') {
if (config.type === 'external') {
await this.externalWindow(config)
return
}
@ -461,7 +461,7 @@ export default {
...config,
//
url_type: config.url_type.replace(/_blank$/, ''),
type: config.type.replace(/_blank$/, ''),
transparent: true,
keep_alive: false,
};
@ -621,7 +621,7 @@ export default {
return
}
if (this.isIframe(app.url_type)) {
if (this.isIframe(app.type)) {
const before = app.onBeforeClose();
if (before && before.then) {
before.then(() => {
@ -685,7 +685,7 @@ export default {
if (!app) {
return
}
if (this.isIframe(app.url_type)) {
if (this.isIframe(app.type)) {
app.postMessage({
type: 'MICRO_APP_MENU_CLICK',
message: action
@ -743,7 +743,7 @@ export default {
* @returns {boolean}
*/
shouldRenderIFrame(app) {
return app.url && this.isIframe(app.url_type) && (app.isOpen || app.keep_alive);
return app.url && this.isIframe(app.type) && (app.isOpen || app.keep_alive);
},
/**
@ -752,7 +752,7 @@ export default {
* @returns {boolean}
*/
shouldRenderMicro(app) {
return app.url && !this.isIframe(app.url_type) && (app.isOpen || this.closings.includes(app.name));
return app.url && !this.isIframe(app.type) && (app.isOpen || this.closings.includes(app.name));
},
/**

View File

@ -184,8 +184,8 @@
</FormItem>
<Row :gutter="16">
<Col :sm="12" :xs="24">
<FormItem :label="$L('URL 类型')">
<Select v-model="item.menu.url_type" transfer>
<FormItem :label="$L('类型')">
<Select v-model="item.menu.type" transfer>
<Option value="iframe">iframe</Option>
<Option value="iframe_blank">iframe_blank</Option>
<Option value="inline">inline</Option>
@ -439,7 +439,7 @@ const createCustomMicroMenu = () => ({
version: 'custom',
menu: {
location: 'application',
url_type: 'iframe',
type: 'iframe',
visible_to: 'admin',
keep_alive: true,
auto_dark_theme: true,

View File

@ -43,7 +43,7 @@ export default {
id: 'iframe-test',
name: 'iframe-test',
url: url,
url_type: 'iframe',
type: 'iframe',
transparent: true,
keep_alive: false,
})

View File

@ -5064,7 +5064,7 @@ export default {
* - id 应用ID必须
* - name 应用名称必须
* - url 应用地址必须
* - url_type 地址类型可选
* - type 打开类型可选string {mobile,desktop,default}default 用于补齐 mobile/desktop缺省为 iframe
* - background 背景颜色可选
* - capsule 应用胶囊配置可选
* - transparent 是否透明模式 (true/false)默认 false
@ -5094,11 +5094,27 @@ export default {
}
})
.replace(/\{system_base_url}/g, serverLocation.origin)
const resolveType = () => {
if (typeof data.type === 'string') {
return data.type
}
if ($A.isJson(data.type)) {
const defaultType = typeof data.type.default === 'string' ? data.type.default : 'iframe'
const mobileType = typeof data.type.mobile === 'string'
? data.type.mobile
: (typeof data.type.app === 'string' ? data.type.app : defaultType)
const desktopType = typeof data.type.desktop === 'string' ? data.type.desktop : defaultType
return $A.platformType() === 'desktop' ? desktopType : mobileType
}
return 'inline'
}
const config = {
id: data.id,
name: data.name,
url: $A.mainUrl(data.url),
url_type: data.url_type || 'inline',
type: resolveType(),
background: data.background || null,
capsule: $A.isJson(data.capsule) ? data.capsule : {},
transparent: typeof data.transparent == 'boolean' ? data.transparent : false,