| src/api/mes/qc/ai/index.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/components/ai-assistant.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/components/ai-suggest.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/defectrecord/components/inline-list.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/ipqc/modules/form.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/iqc/modules/form.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/oqc/modules/form.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| src/views/mes/qc/rqc/modules/form.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/api/mes/qc/ai/index.ts
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,23 @@ import { requestClient } from '#/api/request'; export namespace MesQcAiApi { export interface SuggestResultReqVO { qcId: number; qcType: number; } export interface SuggestResultRespVO { suggestedResult: number; suggestedResultName: string; reasoning: string; keyPoints: string[]; } } /** AI è¾ å©å¤å®æ£éªç»æ */ export function suggestQcResult(params: MesQcAiApi.SuggestResultReqVO) { return requestClient.post<MesQcAiApi.SuggestResultRespVO>( '/mes/qc/ai/suggest-result', params, ); } src/views/mes/qc/components/ai-assistant.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,88 @@ <script lang="ts" setup> import { ref } from 'vue'; import { useVbenModal } from '@vben/common-ui'; import { Empty, Input, Spin } from 'ant-design-vue'; import { searchKnowledgeSegment } from '#/api/ai/knowledge/segment'; defineOptions({ name: 'MesQcAiAssistant' }); const knowledgeId = 1; // è´¨æ£æ åç¥è¯åº IDï¼éæ ¹æ®å®é é ç½®ä¿®æ¹ const keyword = ref(''); const loading = ref(false); const segments = ref< Array<{ id: number; content: string; score: number; documentName: string }> >([]); async function handleSearch() { if (!keyword.value.trim()) return; loading.value = true; try { const data = await searchKnowledgeSegment({ knowledgeId, content: keyword.value, topK: 5, similarityThreshold: 0.5, }); segments.value = (data || []) as typeof segments.value; } finally { loading.value = false; } } function handleKeywordChange(e: Event) { keyword.value = (e.target as HTMLInputElement).value; } const [AssistantModal, modalApi] = useVbenModal({ footer: false, }); </script> <template> <a-button type="default" @click="modalApi.open()"> è´¨æ£å©æ </a-button> <AssistantModal title="è´¨æ£å©æ" class="w-1/3"> <div class="mb-4"> <a-textarea :value="keyword" placeholder="è¾å ¥é®é¢ï¼å¦ï¼å¤è§æ£éªæ 忝ä»ä¹ï¼" :rows="3" @change="handleKeywordChange" /> </div> <div class="mb-4 flex justify-end"> <a-button type="primary" :loading="loading" @click="handleSearch"> æç´¢ </a-button> </div> <Spin :spinning="loading" tip="æ£ç´¢ä¸..."> <template v-if="segments.length === 0 && !loading"> <Empty description="æªæ¾å°ç¸å ³æ åï¼è¯·å°è¯å ¶ä»å ³é®è¯" /> </template> <div v-else class="space-y-3"> <div v-for="segment in segments" :key="segment.id" class="rounded border border-gray-200 p-3" > <div class="mb-1 text-xs text-gray-500"> æ¥æºï¼{{ segment.documentName || 'æªç¥ææ¡£' }} </div> <div class="text-sm leading-relaxed"> {{ segment.content }} </div> <div class="mt-1 text-xs text-gray-400"> ç¸ä¼¼åº¦ {{ ((segment.score ?? 0) * 100).toFixed(0) }}% </div> </div> </div> </Spin> </AssistantModal> </template> src/views/mes/qc/components/ai-suggest.vue
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,90 @@ <script lang="ts" setup> import type { MesQcAiApi } from '#/api/mes/qc/ai'; import { ref } from 'vue'; import { useVbenModal } from '@vben/common-ui'; import { IconifyIcon } from '@vben/icons'; import { Alert, Button, message, Tag } from 'ant-design-vue'; import { suggestQcResult } from '#/api/mes/qc/ai'; interface Props { qcId: number; qcType: number; } defineOptions({ name: 'MesQcAiSuggest' }); const props = defineProps<Props>(); const loading = ref(false); const result = ref<MesQcAiApi.SuggestResultRespVO>(); const resultTagColor: Record<number, string> = { 1: 'green', 2: 'orange', 3: 'red', 4: 'red', }; async function handleSuggest() { loading.value = true; result.value = undefined; try { result.value = await suggestQcResult({ qcId: props.qcId, qcType: props.qcType, }); modalApi.open(); } catch { message.error('AI å¤å®ææ¶ä¸å¯ç¨ï¼è¯·äººå·¥å¤å®'); } finally { loading.value = false; } } const [ResultModal, modalApi] = useVbenModal({ footer: false, }); </script> <template> <Button type="default" :loading="loading" @click="handleSuggest"> <template #icon> <IconifyIcon icon="ant-design:robot-outlined" /> </template> AI è¾ å©å¤å® </Button> <ResultModal title="AI è¾ å©å¤å®ç»æ" class="w-1/2"> <template v-if="result"> <div class="mb-4 flex items-center gap-2"> <span class="text-base font-medium">建议å¤å®ï¼</span> <Tag :color="resultTagColor[result.suggestedResult]"> {{ result.suggestedResultName }} </Tag> </div> <div class="mb-4"> <div class="mb-2 text-base font-medium">æ¨ç便®ï¼</div> <div class="rounded bg-gray-50 p-3 text-sm leading-relaxed"> {{ result.reasoning }} </div> </div> <div v-if="result.keyPoints?.length"> <div class="mb-2 text-base font-medium">å ³æ³¨ç¹ï¼</div> <Alert v-for="(point, index) in result.keyPoints" :key="index" type="warning" show-icon class="mb-2" :message="point" /> </div> </template> </ResultModal> </template> src/views/mes/qc/defectrecord/components/inline-list.vue
@@ -131,7 +131,9 @@ return; } ctxData.value = modalApi.getData<CtxData>(); await gridApi.query(); setTimeout(() => { gridApi.query(); }, 50); }, }); </script> src/views/mes/qc/ipqc/modules/form.vue
@@ -15,6 +15,8 @@ import { $t } from '#/locales'; import { QcIndicatorResultList } from '../../indicatorresult/components'; import MesQcAiSuggest from '../../components/ai-suggest.vue'; import MesQcAiAssistant from '../../components/ai-assistant.vue'; import { useFormSchema } from '../data'; import LineList from './line-list.vue'; @@ -228,6 +230,12 @@ <Button v-if="canFinish" type="primary" @click="handleFinish"> 宿 </Button> <MesQcAiSuggest v-if="canFinish && formData?.id" :qc-id="formData.id" :qc-type="MesQcTypeEnum.IPQC" /> <MesQcAiAssistant /> </div> </template> </Modal> src/views/mes/qc/iqc/modules/form.vue
@@ -15,6 +15,8 @@ import { $t } from '#/locales'; import { QcIndicatorResultList } from '../../indicatorresult/components'; import MesQcAiSuggest from '../../components/ai-suggest.vue'; import MesQcAiAssistant from '../../components/ai-assistant.vue'; import { useFormSchema } from '../data'; import LineList from './line-list.vue'; @@ -229,6 +231,12 @@ <Button v-if="canFinish" type="primary" @click="handleFinish"> 宿 </Button> <MesQcAiSuggest v-if="canFinish && formData?.id" :qc-id="formData.id" :qc-type="MesQcTypeEnum.IQC" /> <MesQcAiAssistant /> </div> </template> </Modal> src/views/mes/qc/oqc/modules/form.vue
@@ -15,6 +15,8 @@ import { $t } from '#/locales'; import { QcIndicatorResultList } from '../../indicatorresult/components'; import MesQcAiSuggest from '../../components/ai-suggest.vue'; import MesQcAiAssistant from '../../components/ai-assistant.vue'; import { useFormSchema } from '../data'; import LineList from './line-list.vue'; @@ -232,6 +234,12 @@ <Button v-if="canFinish" type="primary" @click="handleFinish"> 宿 </Button> <MesQcAiSuggest v-if="canFinish && formData?.id" :qc-id="formData.id" :qc-type="MesQcTypeEnum.OQC" /> <MesQcAiAssistant /> </div> </template> </Modal> src/views/mes/qc/rqc/modules/form.vue
@@ -15,6 +15,8 @@ import { $t } from '#/locales'; import { QcIndicatorResultList } from '../../indicatorresult/components'; import MesQcAiSuggest from '../../components/ai-suggest.vue'; import MesQcAiAssistant from '../../components/ai-assistant.vue'; import { useFormSchema } from '../data'; import LineList from './line-list.vue'; @@ -228,6 +230,12 @@ <Button v-if="canFinish" type="primary" @click="handleFinish"> 宿 </Button> <MesQcAiSuggest v-if="canFinish && formData?.id" :qc-id="formData.id" :qc-type="MesQcTypeEnum.RQC" /> <MesQcAiAssistant /> </div> </template> </Modal>