| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549 |
- <?php
- namespace zin;
- $this->app->loadLang('ai');
- /* 当前类型的名称 */
- $typeLabel = '';
- if(isset($lang->ai->knowledgeLibs->knowledgeObjectTypes[$objectType]['label']))
- {
- $typeLabel = $lang->ai->knowledgeLibs->knowledgeObjectTypes[$objectType]['label'];
- }
- elseif(isset($lang->ai->knowledgeLibs->knowledgeObjectImportTypes[$objectType]['label']))
- {
- $typeLabel = $lang->ai->knowledgeLibs->knowledgeObjectImportTypes[$objectType]['label'];
- }
- jsVar('confirmDeleteFile', $lang->ai->knowledgeLibs->confirmDeleteFile);
- jsVar('confirmBatchDelete', sprintf($lang->ai->knowledgeLibs->confirmBatchDelete, $typeLabel));
- jsVar('noItemSelected', $lang->ai->knowledgeLibs->noItemSelected);
- jsVar('confirmPublish', $lang->ai->knowledgeLibs->confirmPublish);
- jsVar('confirmUnpublish', $lang->ai->knowledgeLibs->confirmUnpublish);
- jsVar('syncFailedText', $lang->ai->knowledgeLibs->syncFailed);
- jsVar('syncFailedHint', $lang->ai->knowledgeLibs->syncFailedHint);
- jsVar('knowledgeLibId', $knowledgeLib->id);
- jsVar('knowledgeItemId', $contentID);
- jsVar('knowledgeFrom', $from);
- jsVar('knowledgeLib', $knowledgeLib);
- /* 构建自定义添加菜单配置 */
- $buildCustomMenuConfig = function() use ($lang, $textFileItems)
- {
- $menuConfig = array();
- /* 自定义文本 */
- $textChildren = array();
- if(!empty($textFileItems['text']))
- {
- foreach($textFileItems['text'] as $item) $textChildren[] = array('id' => $item->id, 'text' => $item->title);
- }
- if(!empty($textChildren))
- {
- $menuConfig[] = array('text' => $lang->ai->knowledgeLibs->customText, 'icon' => 'file-text', 'type' => 'text', 'children' => $textChildren);
- }
- /* 本地文件 */
- $fileChildren = array();
- if(!empty($textFileItems['file']))
- {
- foreach($textFileItems['file'] as $item) $fileChildren[] = array('id' => $item->id, 'text' => $item->title);
- }
- if(!empty($fileChildren))
- {
- $menuConfig[] = array('text' => $lang->ai->knowledgeLibs->localFile, 'icon' => 'folder-o', 'type' => 'file', 'children' => $fileChildren);
- }
- return $menuConfig;
- };
- /* 构建禅道对象数据菜单配置 */
- $buildZentaoDataMenuConfig = function() use ($lang)
- {
- $menuConfig = array();
- /* 禅道对象 */
- foreach($lang->ai->knowledgeLibs->knowledgeObjectTypes as $itemType => $item)
- {
- $menuConfig[] = array('text' => $item['label'], 'icon' => $item['icon'], 'type' => $itemType, 'className' => 'kb-item-' . $itemType);
- }
- /* 资产库导入 */
- foreach($lang->ai->knowledgeLibs->knowledgeObjectImportTypes as $importItemType => $item)
- {
- $menuConfig[] = array('text' => $item['label'], 'icon' => $item['icon'], 'type' => $importItemType, 'className' => 'kb-item-' . $importItemType);
- }
- return $menuConfig;
- };
- /* 构建菜单项 */
- $buildMenuItems = function($config) use ($knowledgeLib, $type, $objectType, $contentID, $stats)
- {
- $items = array();
- foreach($config as $item)
- {
- $menuItem = array('id' => $item['type'], 'text' => $item['text'], 'icon' => $item['icon']);
- if(isset($item['children']))
- {
- $menuItem['className'] = 'kb-' . $item['type'];
- $menuItem['children'] = array();
- foreach($item['children'] as $child)
- {
- $isActive = ($type === $item['type'] && $contentID == $child['id']);
- $menuItem['children'][] = array(
- 'id' => $child['id'],
- 'text' => $child['text'],
- 'active' => $isActive,
- 'url' => inlink('knowledgelibview', "id={$knowledgeLib->id}&type={$item['type']}&contentID={$child['id']}")
- );
- }
- $items[] = $menuItem;
- }
- else
- {
- if(!in_array($item['type'], $stats->objectTypes)) continue;
- $isActive = ($objectType === $item['type']);
- $menuItem['className'] = 'kb-item-' . $item['type'];
- $menuItem['active'] = $isActive;
- $menuItem['url'] = inlink('knowledgelibview', "id={$knowledgeLib->id}&type=object_{$item['type']}");
- $items[] = $menuItem;
- }
- }
- return $items;
- };
- $selectedId = $type === 'object' ? $objectType : $contentID;
- $canAIChat = hasPriv('ai', 'aichatwithknowledgelib');
- $canSearch = hasPriv('ai', 'searchknowledgelib');
- $switchPublish = $knowledgeLib->published == '1' ? hasPriv('ai', 'unpublishknowledgelib') : hasPriv('ai', 'publishknowledgelib');
- $canCreateKnowledge = hasPriv('ai', 'createknowledge');
- $canDeleteKnowledge = hasPriv('ai', 'deleteknowledgeitem');
- $canEditKnowledge = hasPriv('ai', 'editknowledge');
- $showActions = $canAIChat || $canSearch || $switchPublish;
- $headerActions = array();
- if(!$isEmpty && $showActions)
- {
- $headerActions = array(
- $knowledgeLib->published == '1' && $canAIChat ? btn(
- set::icon('ai'),
- set::text($lang->ai->knowledgeLibs->aiChat),
- set::type('ghost'),
- set::size('small'),
- on::click()->call('openAIChatWithKnowledgeLib')
- ) : null,
- $canSearch ? btn(
- set::icon('search'),
- set::text($lang->ai->knowledgeLibs->searchTest),
- set::type('ghost'),
- set::size('small'),
- set::url(createLink('ai', 'searchknowledgelib', "knowledgeLibID={$knowledgeLib->id}&type=$type&contentID=$contentID"))
- ) : null,
- $switchPublish ? btn(
- set::icon($knowledgeLib->published == '1' ? 'cancel' : 'publish'),
- set::text($knowledgeLib->published == '1' ? $lang->ai->prompts->action->unpublish : $lang->ai->prompts->action->publish),
- set::type('ghost'),
- set::size('small'),
- on::click()->call($knowledgeLib->published == '1' ? 'unpublishKnowledgeLib' : 'publishKnowledgeLib')
- ) : null
- );
- }
- /* Permission Config. */
- $privs = array();
- $privs['taskBrowse'] = hasPriv('execution', 'task');
- $privs['productStory'] = hasPriv('product', 'browse');
- $privs['projectStory'] = hasPriv('projectstory', 'story');
- $privs['executionStory'] = hasPriv('execution', 'story');
- $privs['productplanView'] = hasPriv('productplan', 'view');
- $privs['requirementBrowse'] = hasPriv('product', 'requirement');
- $privs['epicBrowse'] = hasPriv('product', 'epic');
- $privs['productBug'] = hasPriv('bug', 'browse');
- $privs['releaseBrowse'] = hasPriv('release', 'browse');
- $privs['projectReleaseBrowse'] = hasPriv('projectRelease', 'browse');
- $privs['productplanBrowse'] = hasPriv('productplan', 'browse');
- $privs['feedbackBrowse'] = hasPriv('feedback', 'admin');
- $privs['ticketBrowse'] = hasPriv('ticket', 'browse');
- /* 构建创建菜单项 */
- $buildCreateItems = function($menuConfig) use ($knowledgeLib, $lang, $privs, $from, $config)
- {
- $createItems = array();
- foreach($lang->ai->knowledgeLibs->knowledgeTypes as $knowledgeType => $menuConfig)
- {
- $menuItem = array('icon' => $menuConfig['icon'], 'text' => $menuConfig['label'], 'className' => 'kb-item-' . $knowledgeType);
- if(!empty($menuConfig['action']))
- {
- $menuItem['data-toggle'] = 'modal';
- $menuItem['data-size'] = $menuConfig['action'] == 'adddoc' ? 'lg' : 'md';
- $menuItem['url'] = createLink('ai', $menuConfig['action'], "lib={$knowledgeLib->id}&from={$from}");
- }
- $createItems[] = $menuItem;
- }
- foreach($lang->ai->knowledgeLibs->knowledgeObjectTypes as $itemObjectType => $itemConfig)
- {
- $priv = isset($itemConfig['priv']) ? $itemConfig['priv'] : null;
- if($priv && isset($privs[$priv]) && !$privs[$priv]) continue;
- $menuItem = array('icon' => $itemConfig['icon'], 'text' => $itemConfig['label'], 'className' => 'kb-item-' . $itemObjectType);
- if(!empty($itemConfig['module']))
- {
- $menuItem['url'] = createLink($itemConfig['module'], $itemConfig['method'], $itemConfig['params']);
- $menuItem['data-toggle'] = 'modal';
- $menuItem['data-size'] = 'lg';
- }
- if(isset($lang->ai->knowledgeLibs->knowledgeObjectSubTypes[$itemObjectType]))
- {
- $subItems = array();
- foreach($lang->ai->knowledgeLibs->knowledgeObjectSubTypes[$itemObjectType] as $subType => $subLabel)
- {
- $priv = isset($subLabel['priv']) ? $subLabel['priv'] : null;
- if($priv && isset($privs[$priv]) && !$privs[$priv]) continue;
- if($subLabel['key'] == 'ER' && !$config->enableER) continue;
- if($subLabel['key'] == 'UR' && !$config->URAndSR) continue;
- $subItem = array('text' => is_array($subLabel) ? $subLabel['label'] : $subLabel);
- if(!empty($itemConfig['action']))
- {
- $subItem['innerClass'] = 'ajax-get';
- $subItem['url'] = createLink('ai', $itemConfig['action'], "lib={$knowledgeLib->id}&objectType={$itemObjectType}&subType={$subType}&from={$from}");
- }
- if(is_array($subLabel) && !empty($subLabel['module']))
- {
- $subItem['url'] = createLink($subLabel['module'], $subLabel['method'], $subLabel['params']);
- $subItem['data-toggle'] = 'modal';
- $subItem['data-size'] = 'lg';
- }
- $subItems[] = $subItem;
- }
- $menuItem['items'] = $subItems;
- }
- else if(!empty($itemConfig['action']))
- {
- $menuItem['data-toggle'] = 'modal';
- $menuItem['data-size'] = $itemConfig['action'] == 'adddoc' ? 'lg' : 'md';
- $menuItem['url'] = createLink('ai', $itemConfig['action'], "lib={$knowledgeLib->id}&from={$from}");
- }
- $createItems[] = $menuItem;
- }
- return $createItems;
- };
- /* 构建选择提示 */
- $buildVoidView = function($message)
- {
- return div(
- setClass('void-view'),
- $message
- );
- };
- /* 构建文本/文件视图 */
- $buildTextView = function($knowledge) use ($lang)
- {
- return div
- (
- setClass('section-content'),
- div
- (
- setClass('show-content'),
- zui::AIKnowledgeChunkList
- (
- set::id($knowledge->id),
- set::needSyncKnowledgeItemText($lang->ai->knowledgeLibs->needSyncKnowledgeItem),
- set::syncingKnowledgeItemText($lang->ai->knowledgeLibs->syncingKnowledgeItem),
- set::emptyKnowledgeDataText($lang->ai->knowledgeLibs->emptyKnowledgeData)
- )
- ),
- div
- (
- setClass('origin-content hidden'),
- setStyle(array('max-height' => 'calc(100vh - 280px)')),
- editor
- (
- set::maxHeight('calc(100vh - 280px)'),
- set::resizable(false),
- set::name('content'),
- set::markdown($knowledge->contentType == 'markdown'),
- set::uploadUrl('disabled'),
- html($knowledge->content)
- ),
- div
- (
- setClass('bg-canvas text-center mt-2 actions'),
- setData(array('knowledgeID' => $knowledge->id, 'knowledgeTitle' => $knowledge->title)),
- btn(
- set::type('primary'),
- set::text($lang->save),
- on::click()->call('saveTextKnowledge')
- )
- )
- )
- );
- };
- /* 构建对象视图 */
- $buildObjectView = function($objectType, $objectList, $objectCols) use ($lang, $knowledgeLib, $pager, $users)
- {
- $objectList = initTableData($objectList, $objectCols, null);
- $footToolbar = hasPriv('ai', 'deleteknowledgeitem') ? array(
- 'items' => array(
- array(
- 'text' => $lang->delete,
- 'data-on' => 'click',
- 'data-call' => "handleBatchDeleteBtnClick('.dtable')"
- )
- ),
- 'btnProps' => array('size' => 'sm', 'btnType' => 'secondary')
- ) : null;
- $dtablePager = $pager ? usePager(array(
- 'recPerPage' => $pager->recPerPage,
- 'recTotal' => $pager->recTotal,
- 'linkCreator' => createLink('ai', 'knowledgelibview', "id={$knowledgeLib->id}&type=object_{$objectType}&contentID=0&recTotal={recTotal}&recPerPage={recPerPage}&pageID={page}")
- )) : false;
- $dtableProps = [
- 'id' => 'knowledgeObjectList',
- 'cols' => $objectCols,
- 'data' => $objectList,
- 'userMap' => $users,
- 'footPager' => $dtablePager,
- 'footToolbar' => $footToolbar,
- 'emptyTip' => $lang->noData,
- 'checkable' => hasPriv('ai', 'deleteknowledgeitem'),
- 'extraHeight' => '+,#mainContent>.detail-header,.page-kbview>.main-content>.section-header,36',
- 'onRenderCell' => jsRaw('window.renderObjectTableCell')
- ];
- return dtable(set($dtableProps));
- };
- $customMenuConfig = $buildCustomMenuConfig();
- /* 构建主视图 */
- $buildMainView = function() use ($selectedId, $lang, $type, $objectType, $knowledgeData, $objectList, $objectCols, $knowledgeLib, $canEditKnowledge, $canDeleteKnowledge, $buildVoidView, $buildTextView, $buildObjectView, $buildZentaoDataMenuConfig, $customMenuConfig, $buildMenuItems)
- {
- $mainContent = null;
- $knowledge = $knowledgeData;
- $zentaoMenuConfig = $buildZentaoDataMenuConfig();
- $customMenuItems = $buildMenuItems($customMenuConfig);
- $zentaoMenuItems = $buildMenuItems($zentaoMenuConfig);
- if(empty($type) || empty($knowledge))
- {
- $mainContent = $buildVoidView($lang->ai->knowledgeLibs->selectContent);
- }
- else
- {
- switch($type) {
- case 'text':
- case 'file':
- $mainContent = $buildTextView($knowledge);
- break;
- case 'object':
- $mainContent = $buildObjectView($objectType, $objectList, $objectCols);
- break;
- default:
- $mainContent = $buildVoidView($lang->ai->knowledgeLibs->selectContent);
- }
- }
- return div(
- setClass('page-kbview'),
- sidebar(
- setClass('sidebar-left'),
- set::width(220),
- set::minWidth(220),
- panel(
- tabs(
- tabPane(
- set::key('custom'),
- set::title($lang->ai->knowledgeLibs->customAdd),
- set::active($type !== 'object'),
- treeEditor(
- set::id('knowledgeTree'),
- set::items($customMenuItems),
- set::selected($selectedId),
- set::defaultNestedShow(true),
- set::canSplit(false),
- set::collapsedIcon('folder text-warning'),
- set::expandedIcon('folder-open text-warning'),
- set::normalIcon(''),
- set::preserve(false)
- )
- ),
- tabPane(
- set::key('zentao'),
- set::title($lang->ai->knowledgeLibs->zentaoData),
- set::active($type === 'object'),
- treeEditor(
- set::id('knowledgeTree'),
- set::items($zentaoMenuItems),
- set::selected($selectedId),
- set::defaultNestedShow(true),
- set::canSplit(false),
- set::collapsedIcon('folder text-warning'),
- set::expandedIcon('folder-open text-warning'),
- set::normalIcon(''),
- set::preserve(false)
- )
- )
- )
- )
- ),
- div(
- setClass('main-content min-w-0'),
- $knowledge ? div(
- setClass('section-header'),
- h2(span(
- set::title($knowledge->title),
- $knowledge->title
- ), $type != 'object' ? input(
- set::type('text'),
- setClass('size-sm'),
- set::value($knowledge->title),
- set::maxlength(255),
- on::blur()->call('updateName')
- ) : null, $type != 'object' && $canEditKnowledge ? btn(
- setClass('edit-btn'),
- set::type('ghost'),
- set::icon('edit'),
- on::click()->call('toggleEditMode')
- ) : null),
- $type == 'object' ? div(
- setClass('actions'),
- $canEditKnowledge ? btn(
- setID('syncObjectListBtn'),
- set::type('ghost'),
- set::icon('refresh'),
- set::text($lang->ai->knowledgeLibs->updateListData),
- set::hint($lang->ai->knowledgeLibs->updateFromSourceData),
- on::click()->call('requestSyncObjectListToZAI', $knowledgeLib->id, $objectType, false, true)
- ): null
- ) : div(
- setClass('actions'),
- $canEditKnowledge && $type == 'text' ? div(
- setClass('show-source'),
- span($lang->ai->knowledgeLibs->viewSourceData),
- switcher(on::change()->call('toggleShowSource', jsRaw('event')))
- ) : null,
- $type == 'text' ? divider() : null,
- $canDeleteKnowledge ? btn(setClass('ajax-submit'), set::type('ghost'), set::icon('trash'), set::hint($lang->delete), set::url(createLink('ai', 'deleteknowledgeitem', "id=$selectedId&knowledgeLibID=$knowledgeLib->id")), setData('confirm', $lang->ai->knowledgeLibs->confirmDeleteFile)) : null
- )
- ) : null,
- $mainContent
- )
- );
- };
- $createMenuItems = $buildCreateItems($customMenuConfig);
- /* 构建空视图 */
- $buildEmptyView = function() use ($lang, $canCreateKnowledge, $createMenuItems)
- {
- $title = $lang->ai->knowledgeLibs->noPrivAddKnowledge;
- $actions = array();
- $menuItems = array();
- if($canCreateKnowledge)
- {
- $title = $lang->ai->knowledgeLibs->addKnowledgeTip;
- $menuItems = $createMenuItems;
- }
- foreach($menuItems as $menuItem)
- {
- if(isset($menuItem['items']) && !empty($menuItem['items']))
- {
- $actions[] = dropdown(
- btn(
- setClass($menuItem['className']),
- set::icon($menuItem['icon']),
- set::text($menuItem['text'])
- ),
- set::items($menuItem['items']),
- set::placement('bottom-center')
- );
- }
- else
- {
- $btnProps = array(setClass($menuItem['className']), set::icon($menuItem['icon']), set::text($menuItem['text']));
- if(!empty($menuItem['url']))
- {
- $btnProps[] = set('href', $menuItem['url']);
- $btnProps[] = setData(array('toggle' => $menuItem['data-toggle'], 'size' => $menuItem['data-size']));
- }
- $actions[] = btn(...$btnProps);
- }
- }
- return div
- (
- setClass('empty-view'),
- h2($title),
- div(setClass('add-actions'), $actions)
- );
- };
- detailHeader(
- to::prefix(
- backBtn(
- set::icon('back'),
- set::type('secondary'),
- set::url(inlink($from)),
- $lang->goback
- ),
- entityLabel(
- set(array(
- 'entityID' => $knowledgeLib->id,
- 'level' => 1,
- 'text' => $knowledgeLib->name,
- 'title' => $knowledgeLib->name
- ))
- )
- ),
- to::suffix(
- div(
- setClass('flex items-center gap-x-1'),
- $headerActions,
- $canCreateKnowledge ? dropdown(
- btn(set::icon('plus'), set::text($lang->ai->knowledgeLibs->addKnowledge), set::type('primary')),
- set::placement('bottom-end'),
- set::items($createMenuItems)
- ) : null
- )
- )
- );
- if($isEmpty)
- {
- $buildEmptyView();
- }
- else
- {
- $buildMainView();
- }
|