feat: template center
Some checks are pending
sync2gitee / repo-sync (push) Waiting to run
Typos Check / Spell Check with Typos (push) Waiting to run

This commit is contained in:
wangdan-fit2cloud 2025-12-25 15:55:37 +08:00
parent c362b4ed4e
commit 4cecf86543
15 changed files with 169 additions and 113 deletions

View File

@ -208,4 +208,25 @@ export default {
])
},
},
'app-template-center': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
},
[
h('path', {
d: 'M213.333333 128h469.333334v107.52a21.333333 21.333333 0 0 0 21.333333 21.333333H810.666667V896H213.333333V128z m515.626667-85.333333H170.666667a42.666667 42.666667 0 0 0-42.666667 42.666666v853.333334a42.666667 42.666667 0 0 0 42.666667 42.666666h682.666666a42.666667 42.666667 0 0 0 42.666667-42.666666V209.749333a42.666667 42.666667 0 0 0-12.501333-30.208l-124.330667-124.373333A42.666667 42.666667 0 0 0 729.002667 42.666667zM320 341.333333a21.333333 21.333333 0 0 0-21.333333 21.333334v42.666666a21.333333 21.333333 0 0 0 21.333333 21.333334h384a21.333333 21.333333 0 0 0 21.333333-21.333334v-42.666666a21.333333 21.333333 0 0 0-21.333333-21.333334h-384z m149.333333 192a21.333333 21.333333 0 0 1 21.333334-21.333333h213.333333a21.333333 21.333333 0 0 1 21.333333 21.333333v213.333334a21.333333 21.333333 0 0 1-21.333333 21.333333h-213.333333a21.333333 21.333333 0 0 1-21.333334-21.333333v-213.333334zM320 512a21.333333 21.333333 0 0 0-21.333333 21.333333v213.333334a21.333333 21.333333 0 0 0 21.333333 21.333333h42.666667a21.333333 21.333333 0 0 0 21.333333-21.333333v-213.333334a21.333333 21.333333 0 0 0-21.333333-21.333333h-42.666667z',
fill: 'currentColor',
}),
],
),
])
},
},
}

View File

@ -251,6 +251,48 @@ export const iconMap: any = {
])
},
},
'app-download': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 16 16',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
},
[
h('path', {
d: 'M14 12.3333V14C14 14.3681 13.7015 14.6666 13.3333 14.6666H2.66667C2.29848 14.6666 2 14.3681 2 14V12.3333C2 12.1492 2.14924 12 2.33333 12H3C3.18409 12 3.33333 12.1492 3.33333 12.3333V13.3333H12.6667V12.3333C12.6667 12.1492 12.8159 12 13 12H13.6667C13.8508 12 14 12.1492 14 12.3333ZM8.66667 9.3571L10.6736 7.35013C10.8038 7.21995 11.0149 7.21995 11.1451 7.35013L11.6165 7.82153C11.7466 7.9517 11.7466 8.16276 11.6165 8.29293L8.31663 11.5928C8.25154 11.6579 8.16623 11.6904 8.08092 11.6904C7.99562 11.6904 7.91031 11.6579 7.84522 11.5928L4.54539 8.29293C4.41521 8.16276 4.41521 7.9517 4.54539 7.82153L5.01679 7.35013C5.14697 7.21995 5.35802 7.21995 5.4882 7.35013L7.33334 9.19526V1.99996C7.33334 1.81586 7.48257 1.66663 7.66667 1.66663H8.33334C8.51743 1.66663 8.66667 1.81586 8.66667 1.99996V9.3571Z',
fill: 'currentColor',
}),
],
),
])
},
},
'app-upload': {
iconReader: () => {
return h('i', [
h(
'svg',
{
style: { height: '100%', width: '100%' },
viewBox: '0 0 1024 1024',
version: '1.1',
xmlns: 'http://www.w3.org/2000/svg',
},
[
h('path', {
d: 'M896 789.333333V896a42.666667 42.666667 0 0 1-42.666667 42.666667H170.666667a42.666667 42.666667 0 0 1-42.666667-42.666667v-106.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667a21.333333 21.333333 0 0 1 21.333333 21.333333V853.333333h597.333334v-64a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667a21.333333 21.333333 0 0 1 21.333333 21.333333z m-341.333333-512l128.426666 128.426667a21.333333 21.333333 0 0 0 30.208 0l30.165334-30.165333a21.333333 21.333333 0 0 0 0-30.165334l-211.2-211.2a21.248 21.248 0 0 0-30.165334 0l-211.2 211.2a21.333333 21.333333 0 0 0 0 30.165334l30.165334 30.165333a21.333333 21.333333 0 0 0 30.165333 0L469.333333 287.701333v460.501334a21.333333 21.333333 0 0 0 21.333334 21.333333h42.666666a21.333333 21.333333 0 0 0 21.333334-21.333333V277.333333z',
fill: 'currentColor',
}),
],
),
])
},
},
'app-404': {
iconReader: () => {
return h('i', [

View File

@ -141,4 +141,5 @@ export default {
prev: 'Previous',
next: 'Next',
},
use: 'Use',
}

View File

@ -25,6 +25,7 @@ export default {
debug: 'Run',
exit: 'Exit',
exitSave: 'Save & Exit',
templateCenter: 'Template Center',
},
tip: {
noData: 'No related results found',

View File

@ -141,4 +141,5 @@ export default {
prev: '上一步',
next: '下一步',
},
use: '使用',
}

View File

@ -24,6 +24,7 @@ export default {
copyParam: '复制参数',
exit: '直接退出',
exitSave: '保存并退出',
templateCenter: '模板中心',
},
tip: {
noData: '没有找到相关结果',

View File

@ -140,4 +140,5 @@ export default {
prev: '上一步',
next: '下一步',
},
use: '使用',
}

View File

@ -24,6 +24,7 @@ export default {
copyParam: '複製參數',
exit: '直接退出',
exitSave: '保存並退出',
templateCenter: '模板中心',
},
tip: {
noData: '沒有找到相關結果',

View File

@ -524,9 +524,7 @@
@click.stop="downloadDocument(row)"
v-if="permissionPrecise.doc_download(id)"
>
<el-icon class="color-secondary">
<Download />
</el-icon>
<AppIcon iconName="app-download" class="color-secondary" />
{{ $t('views.document.setting.download') }}
</el-dropdown-item>
<el-upload
@ -539,9 +537,7 @@
:on-change="(file: any, fileList: any) => replaceDocument(file, row)"
>
<el-dropdown-item>
<el-icon class="color-secondary">
<Upload />
</el-icon>
<AppIcon iconName="app-upload" class="color-secondary" />
{{ $t('views.document.setting.replace') }}
</el-dropdown-item>
</el-upload>

View File

@ -31,7 +31,8 @@
v-if="permissionPrecise.create()"
@click="openTemplateStoreDialog()"
>
{{ $t('模版中心') }}
<AppIcon iconName="app-template-center" class="mr-4" />
{{ $t('workflow.setting.templateCenter') }}
</el-button>
<el-button @click="showPopover = !showPopover">
<AppIcon iconName="app-add-outlined" class="mr-4" />
@ -169,7 +170,12 @@
v-click-outside="clickoutsideHistory"
@refreshVersion="refreshVersion"
/>
<TemplateStoreDialog ref="templateStoreDialogRef" :api-type="apiType" source="work_flow" @refresh="getDetail"/>
<TemplateStoreDialog
ref="templateStoreDialogRef"
:api-type="apiType"
source="work_flow"
@refresh="getDetail"
/>
</div>
</template>
<script setup lang="ts">
@ -183,7 +189,6 @@ import PublishHistory from '@/views/knowledge-workflow/component/PublishHistory.
import { isAppIcon, resetUrl } from '@/utils/common'
import { MsgSuccess, MsgError, MsgConfirm } from '@/utils/message'
import { datetimeFormat } from '@/utils/time'
import { mapToUrlParams } from '@/utils/application'
import useStore from '@/stores'
import { KnowledgeWorkFlowInstance } from '@/workflow/common/validate'
import { hasPermission } from '@/utils/permission'
@ -195,7 +200,7 @@ import permissionMap from '@/permission'
import { WorkflowMode } from '@/enums/application'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import { knowledgeBaseNode } from '@/workflow/common/data'
import TemplateStoreDialog from "@/views/knowledge/template-store/TemplateStoreDialog.vue";
import TemplateStoreDialog from '@/views/knowledge/template-store/TemplateStoreDialog.vue'
provide('getResourceDetail', () => detail)
provide('workflowMode', WorkflowMode.Knowledge)
provide('loopWorkflowMode', WorkflowMode.KnowledgeLoop)
@ -664,7 +669,6 @@ function openTemplateStoreDialog() {
templateStoreDialogRef.value?.open(folderId)
}
/**
* 定时保存
*/

View File

@ -40,7 +40,8 @@
v-if="!isShared && permissionPrecise.create()"
@click="openTemplateStoreDialog()"
>
{{ $t('模版中心') }}
<AppIcon iconName="app-template-center" class="mr-4" />
{{ $t('workflow.setting.templateCenter') }}
</el-button>
<el-dropdown trigger="click" v-if="!isShared && permissionPrecise.create()">
<el-button type="primary" class="ml-8">
@ -337,7 +338,7 @@ import { i18n_name } from '@/utils/common'
import { SourceTypeEnum } from '@/enums/common'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api'
import permissionMap from '@/permission'
import TemplateStoreDialog from "@/views/knowledge/template-store/TemplateStoreDialog.vue";
import TemplateStoreDialog from '@/views/knowledge/template-store/TemplateStoreDialog.vue'
const router = useRouter()
const route = useRoute()
const { folder, user, knowledge } = useStore()

View File

@ -7,41 +7,34 @@
<Back />
</el-icon>
</el-button>
<h4>详情</h4>
<h4>{{ $t('common.detail') }}</h4>
</div>
</template>
<div>
<div class="card-header">
<div class="flex-between">
<div class="border-b">
<div class="flex-between mb-24">
<div class="title flex align-center">
<el-avatar
v-if="isAppIcon(toolDetail?.icon)"
shape="square"
:size="64"
style="background: none"
class="mr-8"
>
<img :src="toolDetail?.icon" alt="" />
<el-avatar shape="square" :size="64" style="background: none">
<img src="@/assets/knowledge/icon_basic_template.svg" alt="" />
</el-avatar>
<el-avatar
v-else-if="toolDetail?.name"
:name="toolDetail?.name"
pinyinColor
shape="square"
:size="64"
class="mr-8"
/>
<div class="ml-16">
<h3 class="mb-8">{{ toolDetail.name }}</h3>
<el-text type="info" v-if="toolDetail?.desc">
{{ toolDetail.desc }}
</el-text>
<span
class="color-secondary flex align-center mt-8"
v-if="toolDetail?.downloads != undefined"
>
<AppIcon iconName="app-download" class="mr-4" />
<span> {{ numberFormat(toolDetail.downloads || 0) }} </span>
</span>
</div>
</div>
<div @click.stop>
<el-button type="primary" @click="addInternalTool(toolDetail)">
{{ $t('common.add') }}
{{ $t('common.use') }}
</el-button>
</div>
</div>

View File

@ -1,53 +1,38 @@
<template>
<CardBox :title="props.tool.name" :description="props.tool.desc" class="cursor tool-card">
<template #icon>
<el-avatar
v-if="isAppIcon(props.tool?.icon)"
shape="square"
:size="32"
style="background: none"
>
<img :src="resetUrl(props.tool?.icon)" alt=""/>
<el-avatar shape="square" :size="32" style="background: none">
<img src="@/assets/knowledge/icon_basic_template.svg" alt="" />
</el-avatar>
<el-avatar
v-else-if="props.tool?.name"
:name="props.tool?.name"
pinyinColor
shape="square"
:size="32"
/>
</template>
<template #title>
<div class="flex align-center">
<span :title="props.tool?.name" class="ellipsis"> {{ props.tool?.name }}</span>
<el-tag v-if="props.tool?.version" class="ml-4" type="info" effect="plain">
{{ props.tool?.version }}
</el-tag>
</div>
<span :title="props.tool?.name" class="ellipsis"> {{ props.tool?.name }}</span>
</template>
<template #tag>
<!-- <template #tag>
<el-tag type="info" v-if="props.tool?.label === 'knowledge_template'" class="info-tag">
{{ $t('知识库') }}
</el-tag>
<el-tag type="info" class="info-tag" v-else>
{{ $t('views.tool.title') }}
</el-tag>
</template>
<template #subTitle>
</template> -->
<!-- <template #subTitle>
<el-text class="color-secondary lighter" size="small">
{{ getSubTitle(props.tool) }}
</el-text>
</template>
</template> -->
<template #footer>
<span class="card-footer-left color-secondary" v-if="props.tool?.downloads != undefined">
{{ `${$t('views.document.upload.download')}: ${numberFormat(props.tool.downloads || 0)} ` }}
<span class="card-footer-left color-secondary flex align-center" v-if="props.tool?.downloads != undefined">
<AppIcon iconName="app-download" class="mr-4" />
<span> {{ numberFormat(props.tool.downloads || 0) }} </span>
</span>
<div class="card-footer-operation mb-8" @click.stop>
<el-button @click="emit('handleDetail')">
{{ $t('common.detail') }}
</el-button>
<el-button type="primary" :loading="props.addLoading" @click="emit('handleAdd')">
{{ $t('common.add') }}
{{ $t('common.use') }}
</el-button>
</div>
</template>

View File

@ -1,7 +1,7 @@
<template>
<el-dialog
v-model="dialogVisible"
width="1200"
width="1000"
append-to-body
class="tool-store-dialog"
align-center
@ -11,7 +11,7 @@
<template #header="{ titleId }">
<div class="dialog-header flex-between mb-8">
<h4 :id="titleId" class="medium w-240 mr-8">
{{ $t('模版中心') }}
{{ $t('workflow.setting.templateCenter') }}
</h4>
<div class="flex align-center" style="margin-right: 28px">
@ -23,12 +23,12 @@
clearable
@change="getList"
/>
<el-divider direction="vertical"/>
<el-divider direction="vertical" />
</div>
</div>
</template>
<LayoutContainer v-loading="loading" :minLeftWidth="204">
<!-- <LayoutContainer v-loading="loading" :minLeftWidth="204">
<template #left>
<el-anchor
direction="vertical"
@ -44,54 +44,54 @@
:title="category.title"
/>
</el-anchor>
</template>
</template> -->
<el-scrollbar class="layout-bg" wrap-class="p-16-24 category-scrollbar">
<template v-if="filterList === null">
<div v-for="category in categories" :key="category.id">
<h4
<el-scrollbar class="layout-bg" wrap-class="p-16-24 category-scrollbar">
<template v-if="filterList === null">
<div v-for="category in categories" :key="category.id">
<!-- <h4
class="title-decoration-1 mb-16 mt-8 color-text-primary"
:id="`category-${category.id}`"
>
{{ category.title }}
</h4>
<el-row :gutter="16">
<el-col v-for="tool in category.tools" :key="tool.id" :span="8" class="mb-16">
<TemplateCard
:tool="tool"
:addLoading="addLoading"
:get-sub-title="getSubTitle"
@handleAdd="handleOpenAdd(tool)"
@handleDetail="handleDetail(tool)"
>
</TemplateCard>
</el-col>
</el-row>
</div>
</template>
<div v-else>
<h4 class="color-text-primary medium mb-16">
<span class="color-primary">{{ searchValue }}</span>
{{ t('views.tool.toolStore.searchResult', {count: filterList.length}) }}
</h4>
<el-row :gutter="16" v-if="filterList.length">
<el-col v-for="tool in filterList" :key="tool.id" :span="12" class="mb-16">
</h4> -->
<el-row :gutter="16">
<el-col v-for="tool in category.tools" :key="tool.id" :span="8" class="mb-16">
<TemplateCard
:tool="tool"
:addLoading="addLoading"
:get-sub-title="getSubTitle"
@handleAdd="handleOpenAdd(tool)"
@handleDetail="handleDetail(tool)"
/>
>
</TemplateCard>
</el-col>
</el-row>
<el-empty v-else :description="$t('common.noData')"/>
</div>
</el-scrollbar>
</LayoutContainer>
</template>
<div v-else>
<!-- <h4 class="color-text-primary medium mb-16">
<span class="color-primary">{{ searchValue }}</span>
{{ t('views.tool.toolStore.searchResult', { count: filterList.length }) }}
</h4> -->
<el-row :gutter="16" v-if="filterList.length">
<el-col v-for="tool in filterList" :key="tool.id" :span="12" class="mb-16">
<TemplateCard
:tool="tool"
:addLoading="addLoading"
:get-sub-title="getSubTitle"
@handleAdd="handleOpenAdd(tool)"
@handleDetail="handleDetail(tool)"
/>
</el-col>
</el-row>
<el-empty v-else :description="$t('common.noData')" />
</div>
</el-scrollbar>
<!-- </LayoutContainer> -->
</el-dialog>
<InternalDescDrawer ref="internalDescDrawerRef" @addTool="handleOpenAdd"/>
<CreateWorkflowKnowledgeDialog ref="CreateKnowledgeDialogRef"/>
<InternalDescDrawer ref="internalDescDrawerRef" @addTool="handleOpenAdd" />
<CreateWorkflowKnowledgeDialog ref="CreateKnowledgeDialogRef" />
</template>
<script setup lang="ts">
@ -99,18 +99,17 @@ import { ref } from 'vue'
import ToolStoreApi from '@/api/tool/store'
import { t } from '@/locales'
import TemplateCard from './TemplateCard.vue'
import { MsgSuccess } from '@/utils/message'
import { MsgSuccess, MsgConfirm } from '@/utils/message'
import InternalDescDrawer from './InternalDescDrawer.vue'
import { loadSharedApi } from '@/utils/dynamics-api/shared-api.ts'
import useStore from '@/stores'
import CreateWorkflowKnowledgeDialog
from "@/views/knowledge/create-component/CreateWorkflowKnowledgeDialog.vue";
import { useRoute } from "vue-router";
import CreateWorkflowKnowledgeDialog from '@/views/knowledge/create-component/CreateWorkflowKnowledgeDialog.vue'
import { useRoute } from 'vue-router'
const {user} = useStore()
const { user } = useStore()
const route = useRoute()
const {
params: {id},
params: { id },
/*
folderId 可以区分 resource-management shared还是 workspace
*/
@ -163,7 +162,7 @@ async function getList() {
if (existing) {
existing.tools = [...existing.tools, ...category.tools]
} else {
acc.push({...category})
acc.push({ ...category })
}
return acc
}, [] as ToolCategory[])
@ -171,10 +170,9 @@ async function getList() {
categories.value = merged.filter((item: any) => item.tools.length > 0)
}
async function getStoreToolList() {
try {
const res = await ToolStoreApi.getStoreKBList({name: searchValue.value}, loading)
const res = await ToolStoreApi.getStoreKBList({ name: searchValue.value }, loading)
const tags = res.data.additionalProperties.tags
const storeTools = res.data.apps
let categories = []
@ -213,9 +211,20 @@ const CreateKnowledgeDialogRef = ref()
function handleOpenAdd(data?: any, isEdit?: boolean) {
if (props.source === 'work_flow') {
handleStoreAdd(data)
MsgConfirm(
t('common.tip'),
`${t('views.application.tip.confirmUse')} ${data.name} ${t('views.application.tip.overwrite')}?`,
{
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
},
)
.then(() => {
handleStoreAdd(data)
})
.catch(() => {})
} else {
CreateKnowledgeDialogRef.value.open({id: folderId.value}, data)
CreateKnowledgeDialogRef.value.open({ id: folderId.value }, data)
}
}
@ -223,8 +232,8 @@ const addLoading = ref(false)
function handleStoreAdd(tool: any) {
try {
loadSharedApi({type: 'knowledge', systemType: props.apiType})
.putKnowledgeWorkflow(id, {work_flow_template: tool})
loadSharedApi({ type: 'knowledge', systemType: props.apiType })
.putKnowledgeWorkflow(id, { work_flow_template: tool })
.then(() => {
emit('refresh')
MsgSuccess(t('common.addSuccess'))
@ -235,8 +244,7 @@ function handleStoreAdd(tool: any) {
}
}
defineExpose({open})
defineExpose({ open })
</script>
<style lang="scss">
.tool-store-dialog {

View File

@ -7,7 +7,7 @@
<Back />
</el-icon>
</el-button>
<h4>详情</h4>
<h4>{{ $t('common.detail') }}</h4>
</div>
</template>