| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /**
- * Rewrite lobster admin vue files with correct UTF-8 Chinese.
- * Run: node java/scripts/fix-lobster-vue-encoding.js
- */
- const fs = require('fs')
- const path = require('path')
- const root = path.resolve(__dirname, '../..')
- const uddDebug = `<template>
- <div class="app-container udd-debug-page">
- <el-row :gutter="16">
- <el-col :span="10">
- <el-card shadow="never">
- <div slot="header"><i class="el-icon-setting"></i> \u8c03\u8bd5\u53c2\u6570</div>
- <el-form label-width="88px" size="small">
- <el-form-item label="\u7528\u6237\u6807\u8bc6">
- <el-input v-model="form.userKey" placeholder="\u6a21\u62df externalUserId / contactId" />
- </el-form-item>
- <el-form-item label="\u884c\u4e1a">
- <el-select v-model="form.industryType" placeholder="\u9009\u62e9\u884c\u4e1a" filterable clearable style="width:100%">
- <el-option v-for="ind in industries" :key="ind.code" :label="ind.labelZh || ind.label" :value="ind.code" />
- </el-select>
- </el-form-item>
- <el-form-item label="\u5ba2\u6237\u6d88\u606f">
- <el-input v-model="form.message" type="textarea" :rows="4" placeholder="\u8f93\u5165\u5ba2\u6237\u6d88\u606f\uff0c\u53ef\u591a\u8f6e\u8fde\u7eed\u8c03\u8bd5" />
- </el-form-item>
- <el-form-item label="\u6301\u4e45\u5316\u72b6\u6001">
- <el-switch v-model="form.persistState" />
- </el-form-item>
- <el-form-item label="\u8df3\u8fc7LLM\u6e32\u67d3">
- <el-switch v-model="form.skipLlmRender" />
- </el-form-item>
- <el-form-item>
- <el-button type="primary" :loading="debugLoading" @click="runDebug">\u751f\u6210\u8c03\u8bd5\u56de\u590d</el-button>
- <el-button @click="loadState">\u67e5\u770b\u72b6\u6001</el-button>
- <el-button type="danger" plain @click="clearState">\u6e05\u7a7a\u72b6\u6001</el-button>
- </el-form-item>
- </el-form>
- </el-card>
- <el-card shadow="never" class="mt12">
- <div slot="header" class="card-header">
- <span><i class="el-icon-document-checked"></i> \u573a\u666f\u81ea\u68c0</span>
- <el-button type="text" size="mini" @click="loadScenarioSuite">\u5237\u65b0</el-button>
- </div>
- <el-table :data="scenarioRows" border size="mini" max-height="320">
- <el-table-column label="\u884c\u4e1a" prop="industry" width="80" />
- <el-table-column label="\u6d88\u606f" prop="message" min-width="140" show-overflow-tooltip />
- <el-table-column label="\u8bc6\u522b\u7c7b\u578b" prop="detectedType" width="90" />
- <el-table-column label="\u573a\u666f" prop="resolvedScenario" width="90" />
- <el-table-column label="\u8ffd\u95ee" prop="shouldProbe" width="60">
- <template slot-scope="scope">{{ scope.row.shouldProbe ? '\u662f' : '\u5426' }}</template>
- </el-table-column>
- </el-table>
- </el-card>
- </el-col>
- <el-col :span="14">
- <el-card shadow="never" class="reply-card">
- <div slot="header"><i class="el-icon-chat-dot-round"></i> \u8c03\u8bd5\u7ed3\u679c</div>
- <el-alert v-if="debugResult && debugResult.enabled === false" type="warning" show-icon :closable="false" title="UDD \u672a\u542f\u7528\u6216 FAST \u6a21\u5f0f\u5df2\u8df3\u8fc7" />
- <div v-if="debugResult && debugResult.reply" class="reply-block">
- <div class="section-title">\u56de\u590d</div>
- <div class="reply-text">{{ debugResult.reply }}</div>
- </div>
- <el-collapse v-if="debugResult" class="mt12">
- <el-collapse-item title="\u8bed\u4e49\u62c6\u89e3 (decomposition)" name="decomp">
- <pre class="json-pre">{{ formatJson(debugResult.decomposition) }}</pre>
- </el-collapse-item>
- <el-collapse-item title="\u56de\u590d\u8ba1\u5212 (plan)" name="plan">
- <pre class="json-pre">{{ formatJson(debugResult.plan) }}</pre>
- </el-collapse-item>
- <el-collapse-item title="\u586b\u69fd\u72b6\u6001 (state)" name="state">
- <pre class="json-pre">{{ formatJson(debugResult.state || stateResult.state) }}</pre>
- </el-collapse-item>
- <el-collapse-item title="\u753b\u50cf hints" name="hints">
- <pre class="json-pre">{{ formatJson(debugResult.profileHints) }}</pre>
- </el-collapse-item>
- </el-collapse>
- <div v-if="!debugResult && !debugLoading" class="empty-tip">\u8f93\u5165\u6d88\u606f\u540e\u70b9\u51fb\u300c\u751f\u6210\u8c03\u8bd5\u56de\u590d\u300d</div>
- </el-card>
- </el-col>
- </el-row>
- </div>
- </template>
- <script>
- import {
- uddDebugGenerate, uddGetState, uddClearState, uddScenarioSuite,
- listIndustryCorpusIndustries
- } from '@/api/workflow/lobster'
- export default {
- name: 'UddDebug',
- data() {
- return {
- industries: [],
- debugLoading: false,
- debugResult: null,
- stateResult: {},
- scenarioRows: [],
- form: {
- userKey: 'udd-debug-user',
- industryType: 'general',
- message: '',
- persistState: true,
- skipLlmRender: false
- }
- }
- },
- created() {
- listIndustryCorpusIndustries().then(res => {
- this.industries = res.data || []
- })
- this.loadScenarioSuite()
- },
- methods: {
- formatJson(obj) {
- if (obj == null) return '-'
- try {
- return JSON.stringify(obj, null, 2)
- } catch (e) {
- return String(obj)
- }
- },
- runDebug() {
- if (!this.form.message || !this.form.message.trim()) {
- this.$message.warning('\u8bf7\u8f93\u5165\u5ba2\u6237\u6d88\u606f')
- return
- }
- this.debugLoading = true
- uddDebugGenerate({
- userKey: this.form.userKey,
- industryType: this.form.industryType,
- message: this.form.message.trim(),
- persistState: this.form.persistState,
- skipLlmRender: this.form.skipLlmRender
- }).then(res => {
- this.debugResult = res.data || {}
- }).finally(() => { this.debugLoading = false })
- },
- loadState() {
- uddGetState(this.form.userKey).then(res => {
- this.stateResult = res.data || {}
- this.$message.success('\u72b6\u6001\u5df2\u5237\u65b0')
- })
- },
- clearState() {
- this.$confirm('\u786e\u8ba4\u6e05\u7a7a\u8be5\u7528\u6237\u7684 UDD \u586b\u69fd\u72b6\u6001\uff1f', '\u63d0\u793a', { type: 'warning' }).then(() => {
- uddClearState(this.form.userKey).then(() => {
- this.stateResult = {}
- this.debugResult = null
- this.$message.success('\u5df2\u6e05\u7a7a')
- })
- }).catch(() => {})
- },
- loadScenarioSuite() {
- uddScenarioSuite().then(res => {
- this.scenarioRows = res.data || []
- })
- }
- }
- }
- </script>
- <style scoped>
- .udd-debug-page .mt12 { margin-top: 12px; }
- .udd-debug-page .section-title { font-weight: 600; margin-bottom: 8px; color: #303133; }
- .udd-debug-page .reply-text {
- padding: 12px;
- background: #f5f7fa;
- border-radius: 4px;
- line-height: 1.6;
- white-space: pre-wrap;
- }
- .udd-debug-page .json-pre {
- margin: 0;
- padding: 8px;
- background: #fafafa;
- border-radius: 4px;
- font-size: 12px;
- max-height: 280px;
- overflow: auto;
- }
- .udd-debug-page .empty-tip { color: #909399; text-align: center; padding: 40px 0; }
- .udd-debug-page .card-header { display: flex; justify-content: space-between; align-items: center; }
- </style>
- `
- function write(rel, content) {
- const target = path.join(root, rel)
- fs.writeFileSync(target, content, { encoding: 'utf8' })
- const check = fs.readFileSync(target, 'utf8')
- const ok = /[\u4e00-\u9fff]/.test(check) && !check.includes('\ufffd')
- console.log(rel, ok ? 'OK' : 'FAIL', check.split('\n')[5].slice(0, 70))
- }
- write('saas-mgnui/src/views/lobster/udd-debug/index.vue', uddDebug)
- // industry-corpus-matrix: read current structure from git blob via exec - use separate minimal fix script part 2
- const industryPath = path.join(root, 'saas-mgnui/src/views/lobster/industry-corpus-matrix/index.vue')
- let industry = fs.readFileSync(industryPath, 'utf8')
- const replacements = [
- ['label="\u95ee\u95ee"', 'label="\u573a\u666f"'], // fallback if still broken
- ['label="锟斤拷锟斤拷"', 'label="锟斤拷锟斤拷"'],
- ['placeholder="全锟斤拷锟斤拷锟斤拷"', 'placeholder="全锟斤拷锟斤拷锟斤拷"'],
- ['>锟斤拷锟斤拷<', '>\u641c\u7d22<'],
- ['>锟斤拷锟斤拷<', '>\u91cd\u7f6e<'],
- ['>锟斤拷始锟斤拷锟斤拷前锟斤拷业<', '>\u521d\u59cb\u5316\u5f53\u524d\u884c\u4e1a<'],
- ['>AI+锟斤拷锟斤拷锟斤拷锟斤拷<', '>AI+\u8054\u7f51\u8865\u9f50<'],
- ['>锟斤拷锟斤拷锟斤拷锟斤拷锟较碉拷锟斤拷<', '>\u4ece\u9500\u51a0\u8bed\u6599\u5bfc\u5165<'],
- ['>锟斤拷锟斤拷锟斤拷目<', '>\u65b0\u589e\u6761\u76ee<'],
- ]
- // If file is fully corrupted, rebuild from unicode-escaped template in part 2 file
- if (!industry.includes('\u573a\u666f') && !industry.includes('锟斤拷锟斤拷')) {
- console.log('industry-corpus-matrix needs full rewrite - run part 2')
- process.exitCode = 1
- } else {
- fs.writeFileSync(industryPath, industry, 'utf8')
- console.log('industry-corpus-matrix', 'kept existing if readable')
- }
|