mirror of
https://github.com/kuaifan/dootask.git
synced 2025-12-12 11:19:56 +00:00
no message
This commit is contained in:
parent
0c34df290e
commit
ef696391d8
@ -81,43 +81,46 @@ class AppsController extends AbstractController
|
||||
}
|
||||
|
||||
/**
|
||||
* @api {get} api/apps/stats 04. 获取应用状况
|
||||
* @api {get} api/apps/status 04. 获取应用状态
|
||||
*
|
||||
* @apiDescription 获取应用状况,包括已安装的应用和应用入口点
|
||||
* @apiDescription 获取应用状态,包括已安装的应用和应用菜单
|
||||
* @apiVersion 1.0.0
|
||||
* @apiGroup apps
|
||||
* @apiName stats
|
||||
* @apiName status
|
||||
*
|
||||
* @apiSuccess {Number} ret 返回状态码(1正确、0错误)
|
||||
* @apiSuccess {String} msg 返回信息(错误描述)
|
||||
* @apiSuccess {Object} data 应用入口点信息
|
||||
* @apiSuccess {Object} data 应用和菜单信息
|
||||
* @apiSuccess {Array} data.installed 已安装应用列表
|
||||
* @apiSuccess {Array} data.menus 应用菜单列表
|
||||
*/
|
||||
public function stats()
|
||||
public function status()
|
||||
{
|
||||
User::auth();
|
||||
|
||||
// 获取已安装应用列表
|
||||
$res = Apps::appList();
|
||||
if (Base::isError($res)) {
|
||||
return $res;
|
||||
}
|
||||
$installedName = ['appstore'];
|
||||
foreach ($res['data'] as $app) {
|
||||
if ($app['config']['status'] == 'installed') {
|
||||
$installedName[] = $app['name'];
|
||||
}
|
||||
$appList = Apps::appList();
|
||||
if (Base::isSuccess($appList)) {
|
||||
$installedName = array_merge(
|
||||
$installedName,
|
||||
array_column(
|
||||
array_filter($appList['data'], fn($app) => $app['config']['status'] === 'installed'),
|
||||
'name'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// 获取应用入口点
|
||||
$res = Apps::getAppEntryPoints();
|
||||
if (Base::isError($res)) {
|
||||
return $res;
|
||||
// 获取应用菜单
|
||||
$menusData = [];
|
||||
$res = Apps::getAppMenuItems();
|
||||
if (Base::isSuccess($res)) {
|
||||
$menusData = $res['data'];
|
||||
}
|
||||
$entriesData = $res['data'];
|
||||
|
||||
return Base::retSuccess('success', [
|
||||
'installed' => $installedName,
|
||||
'entries' => $entriesData,
|
||||
'menus' => $menusData,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@ -344,41 +344,41 @@ class Apps
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用的入口点配置
|
||||
* 获取应用的菜单配置
|
||||
*
|
||||
* @param string|null $appName 应用名称,为null时获取所有已安装应用的入口点
|
||||
* @param string|null $appName 应用名称,为null时获取所有已安装应用的菜单
|
||||
* @return array
|
||||
*/
|
||||
public static function getAppEntryPoints(?string $appName = null): array
|
||||
public static function getAppMenuItems(?string $appName = null): array
|
||||
{
|
||||
if ($appName !== null) {
|
||||
return self::entryGetSingle($appName);
|
||||
return self::menuGetSingle($appName);
|
||||
}
|
||||
return self::entryGetAll();
|
||||
return self::menuGetAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单个应用的入口点配置
|
||||
* 获取单个应用的菜单配置
|
||||
*
|
||||
* @param string $appName 应用名称
|
||||
* @return array
|
||||
*/
|
||||
private static function entryGetSingle(string $appName): array
|
||||
private static function menuGetSingle(string $appName): array
|
||||
{
|
||||
$baseDir = base_path('docker/appstore/apps/' . $appName);
|
||||
$entryPoints = [];
|
||||
$menuItems = [];
|
||||
|
||||
if (!file_exists($baseDir . '/config.yml')) {
|
||||
return Base::retSuccess("success", $entryPoints);
|
||||
return Base::retSuccess("success", $menuItems);
|
||||
}
|
||||
|
||||
try {
|
||||
$configData = Yaml::parseFile($baseDir . '/config.yml');
|
||||
if (isset($configData['entry_points']) && is_array($configData['entry_points'])) {
|
||||
foreach ($configData['entry_points'] as $entry) {
|
||||
$normalizedEntry = self::entryNormalize($entry, $appName);
|
||||
if ($normalizedEntry) {
|
||||
$entryPoints[] = $normalizedEntry;
|
||||
if (isset($configData['menu_items']) && is_array($configData['menu_items'])) {
|
||||
foreach ($configData['menu_items'] as $menu) {
|
||||
$normalizedMenu = self::menuNormalize($menu, $appName);
|
||||
if ($normalizedMenu) {
|
||||
$menuItems[] = $normalizedMenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,21 +386,21 @@ class Apps
|
||||
return Base::retError('配置文件解析失败:' . $e->getMessage());
|
||||
}
|
||||
|
||||
return Base::retSuccess("success", $entryPoints);
|
||||
return Base::retSuccess("success", $menuItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已安装应用的入口点配置
|
||||
* 获取所有已安装应用的菜单配置
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private static function entryGetAll(): array
|
||||
private static function menuGetAll(): array
|
||||
{
|
||||
$allEntryPoints = [];
|
||||
$allMenuItems = [];
|
||||
$baseDir = base_path('docker/appstore/apps');
|
||||
|
||||
if (!is_dir($baseDir)) {
|
||||
return Base::retSuccess("success", $allEntryPoints);
|
||||
return Base::retSuccess("success", $allMenuItems);
|
||||
}
|
||||
|
||||
$dirs = scandir($baseDir);
|
||||
@ -413,48 +413,48 @@ class Apps
|
||||
continue;
|
||||
}
|
||||
|
||||
$appEntryPoints = self::entryGetSingle($dir);
|
||||
if (Base::isSuccess($appEntryPoints)) {
|
||||
$allEntryPoints = array_merge($allEntryPoints, $appEntryPoints['data']);
|
||||
$appMenuItems = self::menuGetSingle($dir);
|
||||
if (Base::isSuccess($appMenuItems)) {
|
||||
$allMenuItems = array_merge($allMenuItems, $appMenuItems['data']);
|
||||
}
|
||||
}
|
||||
|
||||
return Base::retSuccess("success", $allEntryPoints);
|
||||
return Base::retSuccess("success", $allMenuItems);
|
||||
}
|
||||
|
||||
/**
|
||||
* 标准化入口点配置
|
||||
* 标准化菜单配置
|
||||
*
|
||||
* @param array $entry 原始入口点配置
|
||||
* @param array $menu 原始菜单配置
|
||||
* @param string $appName 应用名称
|
||||
* @return array|null 标准化后的入口点配置,配置无效时返回null
|
||||
* @return array|null 标准化后的菜单配置,配置无效时返回null
|
||||
*/
|
||||
private static function entryNormalize(array $entry, string $appName): ?array
|
||||
private static function menuNormalize(array $menu, string $appName): ?array
|
||||
{
|
||||
// 检查必需的字段
|
||||
if (!isset($entry['location']) || !isset($entry['url'])) {
|
||||
if (!isset($menu['location']) || !isset($menu['url'])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 基础配置
|
||||
$normalizedEntry = [
|
||||
$normalizedMenu = [
|
||||
'app_name' => $appName,
|
||||
'location' => $entry['location'],
|
||||
'url' => $entry['url'],
|
||||
'key' => $entry['key'] ?? substr(md5($entry['url']), 0, 16),
|
||||
'icon' => self::processAppIcon($appName, [$entry['icon'] ?? '']),
|
||||
'label' => self::getMultiLanguageField($entry['label'] ?? ''),
|
||||
'location' => $menu['location'],
|
||||
'url' => $menu['url'],
|
||||
'key' => $menu['key'] ?? substr(md5($menu['url']), 0, 16),
|
||||
'icon' => self::processAppIcon($appName, [$menu['icon'] ?? '']),
|
||||
'label' => self::getMultiLanguageField($menu['label'] ?? ''),
|
||||
];
|
||||
|
||||
// 处理可选的UI配置
|
||||
$optionalConfigs = ['transparent', 'keepAlive'];
|
||||
foreach ($optionalConfigs as $config) {
|
||||
if (isset($entry[$config])) {
|
||||
$normalizedEntry[$config] = $entry[$config];
|
||||
if (isset($menu[$config])) {
|
||||
$normalizedMenu[$config] = $menu[$config];
|
||||
}
|
||||
}
|
||||
|
||||
return $normalizedEntry;
|
||||
return $normalizedMenu;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -830,7 +830,7 @@ class Apps
|
||||
// 处理应用名称
|
||||
$appName = Base::camel2snake(Base::cn2pinyin($configData['name'], '_'));
|
||||
if (in_array($appName, self::$protectedServiceNames)) {
|
||||
return Base::retError('服务名称 "' . $name . '" 被保护,不能使用');
|
||||
return Base::retError('服务名称 "' . $appName . '" 被保护,不能使用');
|
||||
}
|
||||
$targetDir = base_path('docker/appstore/apps/' . $appName);
|
||||
$targetConfigFile = $targetDir . '/config.json';
|
||||
|
||||
@ -424,7 +424,7 @@ export default {
|
||||
microApp.forceSetData(name, {type: 'beforeClose'}, array => {
|
||||
if (!array?.find(item => item === true)) {
|
||||
if (name === 'appstore') {
|
||||
this.$store.dispatch("updateMicroAppsStats");
|
||||
this.$store.dispatch("updateMicroAppsStatus");
|
||||
}
|
||||
if ($A.isSubElectron) {
|
||||
$A.Electron.sendMessage('windowDestroy');
|
||||
|
||||
@ -120,6 +120,10 @@
|
||||
<div class="menu-title">{{$L('应用')}}</div>
|
||||
<Badge class="menu-badge" :overflow-count="999" :text="String((reportUnreadNumber + approveUnreadNumber) || '')"/>
|
||||
</li>
|
||||
<li v-for="(item, key) in filterMicroAppsMenusMain" :key="key" @click="onTabbarClick('microApp', item)">
|
||||
<div class="apply-icon no-dark-content" :style="{backgroundImage: `url(${item.icon})`}"></div>
|
||||
<div class="menu-title">{{item.label}}</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div ref="menuProject" class="menu-project">
|
||||
@ -515,7 +519,7 @@ export default {
|
||||
'longpressData',
|
||||
]),
|
||||
|
||||
...mapGetters(['dashboardTask']),
|
||||
...mapGetters(['dashboardTask', "filterMicroAppsMenusMain"]),
|
||||
|
||||
/**
|
||||
* page className
|
||||
@ -1167,7 +1171,7 @@ export default {
|
||||
})
|
||||
},
|
||||
|
||||
onTabbarClick(act) {
|
||||
onTabbarClick(act, params = '') {
|
||||
switch (act) {
|
||||
case 'createGroup':
|
||||
this.onAddMenu('group')
|
||||
@ -1183,6 +1187,9 @@ export default {
|
||||
case 'workReport':
|
||||
this.settingRoute(act)
|
||||
break;
|
||||
case 'microApp':
|
||||
this.$store.dispatch("openMicroApp", params);
|
||||
break;
|
||||
case 'appstore':
|
||||
this.$store.dispatch("openMicroApp", {
|
||||
name: 'appstore',
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
{{ t == 'base' ? $L('常用') : $L('管理员') }}
|
||||
</div>
|
||||
<Row :gutter="16">
|
||||
<Col v-for="item in (t == 'base' ? filterMicroAppsEntries : filterMicroAppsEntriesAdmin)" :key="item.key"
|
||||
<Col v-for="(item, key) in (t == 'base' ? filterMicroAppsMenus : filterMicroAppsMenusAdmin)" :key="key"
|
||||
:xs="{ span: 6 }"
|
||||
:sm="{ span: 6 }"
|
||||
:lg="{ span: 6 }"
|
||||
@ -26,7 +26,7 @@
|
||||
<div class="logo">
|
||||
<div class="apply-icon no-dark-content" :style="{backgroundImage: `url(${item.icon})`}"></div>
|
||||
</div>
|
||||
<p>{{ $L(item.label) }}</p>
|
||||
<p>{{ item.label }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</Col>
|
||||
@ -364,6 +364,7 @@ export default {
|
||||
},
|
||||
activated() {
|
||||
this.initList()
|
||||
this.$store.dispatch("updateMicroAppsStatus")
|
||||
},
|
||||
computed: {
|
||||
...mapState([
|
||||
@ -378,8 +379,8 @@ export default {
|
||||
'routeLoading',
|
||||
]),
|
||||
...mapGetters([
|
||||
'filterMicroAppsEntries',
|
||||
'filterMicroAppsEntriesAdmin',
|
||||
'filterMicroAppsMenus',
|
||||
'filterMicroAppsMenusAdmin',
|
||||
]),
|
||||
isExistAdminList() {
|
||||
return this.applyList.map(h => h.type).indexOf('admin') !== -1;
|
||||
@ -449,11 +450,8 @@ export default {
|
||||
return item.value == type && num > 0
|
||||
},
|
||||
// 点击应用
|
||||
applyClick(item, area = '') {
|
||||
applyClick(item, params = '') {
|
||||
switch (item.value) {
|
||||
case 'microApp':
|
||||
this.$store.dispatch("openMicroApp", area);
|
||||
return
|
||||
case 'approve':
|
||||
case 'calendar':
|
||||
case 'file':
|
||||
@ -461,27 +459,27 @@ export default {
|
||||
this.goForward({ name: 'manage-' + item.value });
|
||||
break;
|
||||
case 'report':
|
||||
emitter.emit('openReport', area == 'badge' ? 'receive' : 'my');
|
||||
emitter.emit('openReport', params == 'badge' ? 'receive' : 'my');
|
||||
break;
|
||||
case 'mybot':
|
||||
this.getMybot();
|
||||
this.mybotShow = true;
|
||||
break;
|
||||
case 'mybot-chat':
|
||||
this.chatMybot(area.id);
|
||||
this.chatMybot(params.id);
|
||||
break;
|
||||
case 'mybot-add':
|
||||
this.addMybot(area);
|
||||
this.addMybot(params);
|
||||
break;
|
||||
case 'mybot-del':
|
||||
this.delMybot(area);
|
||||
this.delMybot(params);
|
||||
break;
|
||||
case 'robot':
|
||||
this.getAITags();
|
||||
this.aibotShow = true;
|
||||
break;
|
||||
case 'robot-setting':
|
||||
this.aibotTabAction = area;
|
||||
this.aibotTabAction = params;
|
||||
this.aibotSettingShow = true;
|
||||
break;
|
||||
case 'signin':
|
||||
@ -510,7 +508,7 @@ export default {
|
||||
break;
|
||||
|
||||
}
|
||||
this.$emit("on-click", item.value)
|
||||
this.$emit("on-click", item.value, params);
|
||||
},
|
||||
// 获取我的机器人
|
||||
getMybot() {
|
||||
|
||||
@ -2619,7 +2619,7 @@ export default {
|
||||
});
|
||||
},
|
||||
|
||||
openOkr(id) {
|
||||
openOkrDetails(id) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
@ -3150,7 +3150,7 @@ export default {
|
||||
break;
|
||||
|
||||
case 'okr':
|
||||
this.openOkr(this.dialogData.link_id)
|
||||
this.openOkrDetails(this.dialogData.link_id)
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3758,7 +3758,7 @@ export default {
|
||||
this.$store.dispatch("openTask", $A.runNum(target.getAttribute("data-id")));
|
||||
}
|
||||
if (target.classList.contains('mention') && target.classList.contains('okr')) {
|
||||
this.openOkr($A.runNum(target.getAttribute("data-id")));
|
||||
this.openOkrDetails($A.runNum(target.getAttribute("data-id")));
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
17
resources/assets/js/store/actions.js
vendored
17
resources/assets/js/store/actions.js
vendored
@ -623,7 +623,7 @@ export default {
|
||||
dispatch("getProjectByQueue");
|
||||
dispatch("getTaskForDashboard");
|
||||
dispatch("dialogMsgRead");
|
||||
dispatch("updateMicroAppsStats");
|
||||
dispatch("updateMicroAppsStatus");
|
||||
//
|
||||
const allIds = Object.values(state.userAvatar).map(({userid}) => userid);
|
||||
[...new Set(allIds)].some(userid => dispatch("getUserBasic", {userid}))
|
||||
@ -1116,6 +1116,8 @@ export default {
|
||||
'callAt',
|
||||
'cacheEmojis',
|
||||
'cacheDialogs',
|
||||
'microAppsInstalled',
|
||||
'microAppsMenus',
|
||||
],
|
||||
json: [
|
||||
'userInfo'
|
||||
@ -4640,17 +4642,16 @@ export default {
|
||||
/** *****************************************************************************************/
|
||||
|
||||
/**
|
||||
* 更新微应用状况(已安装、入口菜单)
|
||||
* @param state
|
||||
* 更新微应用状态(已安装应用、菜单项)
|
||||
* @param commit
|
||||
* @param dispatch
|
||||
* @param appName
|
||||
*/
|
||||
updateMicroAppsStats({state, dispatch}) {
|
||||
updateMicroAppsStatus({commit, dispatch}) {
|
||||
dispatch("call", {
|
||||
url: 'apps/stats',
|
||||
url: 'apps/status',
|
||||
}).then(({data}) => {
|
||||
state.microAppsInstalled = data.installed
|
||||
state.microAppsEntries = data.entries
|
||||
commit("microApps/installed", data.installed)
|
||||
commit("microApps/menu", data.menus)
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
18
resources/assets/js/store/getters.js
vendored
18
resources/assets/js/store/getters.js
vendored
@ -279,35 +279,35 @@ export default {
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取应用菜单入口
|
||||
* 获取应用菜单
|
||||
* 过滤出location为application的菜单项
|
||||
*
|
||||
* @param {Object} state
|
||||
* @returns {Array}
|
||||
*/
|
||||
filterMicroAppsEntries: (state) => {
|
||||
return state.microAppsEntries.filter(item => item.location === 'application')
|
||||
filterMicroAppsMenus: (state) => {
|
||||
return state.microAppsMenus.filter(item => item.location === 'application')
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取应用管理菜单入口
|
||||
* 获取应用管理菜单
|
||||
* 过滤出location为application/admin的菜单项
|
||||
*
|
||||
* @param {Object} state
|
||||
* @returns {Array}
|
||||
*/
|
||||
filterMicroAppsEntriesAdmin: (state) => {
|
||||
return state.microAppsEntries.filter(item => item.location === 'application/admin')
|
||||
filterMicroAppsMenusAdmin: (state) => {
|
||||
return state.microAppsMenus.filter(item => item.location === 'application/admin')
|
||||
},
|
||||
|
||||
/**
|
||||
* 获取主导航菜单入口
|
||||
* 获取主导航菜单
|
||||
* 过滤出location为main/menu的菜单项
|
||||
*
|
||||
* @param {Object} state
|
||||
* @returns {Array}
|
||||
*/
|
||||
filterMicroAppsEntriesMain: (state) => {
|
||||
return state.microAppsEntries.filter(item => item.location === 'main/menu')
|
||||
filterMicroAppsMenusMain: (state) => {
|
||||
return state.microAppsMenus.filter(item => item.location === 'main/menu')
|
||||
}
|
||||
}
|
||||
|
||||
11
resources/assets/js/store/mutations.js
vendored
11
resources/assets/js/store/mutations.js
vendored
@ -298,4 +298,15 @@ export default {
|
||||
'menu/operation': function(state, data) {
|
||||
state.menuOperation = data || {}
|
||||
},
|
||||
|
||||
// 微应用管理
|
||||
'microApps/menu': function(state, data) {
|
||||
state.microAppsMenus = data
|
||||
$A.IDBSave("microAppsMenus", state.microAppsMenus)
|
||||
},
|
||||
|
||||
'microApps/installed': function(state, data) {
|
||||
state.microAppsInstalled = data
|
||||
$A.IDBSave("microAppsInstalled", state.microAppsInstalled)
|
||||
},
|
||||
}
|
||||
|
||||
4
resources/assets/js/store/state.js
vendored
4
resources/assets/js/store/state.js
vendored
@ -261,7 +261,7 @@ export default {
|
||||
// 长按数据
|
||||
longpressData: {type: '', data: null, element: null},
|
||||
|
||||
// 微应用菜单入口
|
||||
// 微应用数据
|
||||
microAppsInstalled: [],
|
||||
microAppsEntries: [],
|
||||
microAppsMenus: [],
|
||||
};
|
||||
|
||||
8
resources/assets/sass/pages/page-manage.scss
vendored
8
resources/assets/sass/pages/page-manage.scss
vendored
@ -55,6 +55,14 @@
|
||||
font-size: 20px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.apply-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
background-position: center center;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.menu-title {
|
||||
flex: 1;
|
||||
white-space: nowrap;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user