feat: 更改配置

This commit is contained in:
zhanghao 2025-09-04 16:41:54 +08:00
parent bacb76d58e
commit 95c53fab93
8 changed files with 1232 additions and 524 deletions

View File

@ -1,17 +1,14 @@
# 页面标题 # 页面标题
VITE_APP_TITLE = 招商车研物联网平台 VITE_APP_TITLE = 招商车研物联网平台
# 开发环境配置 # 开发环境配置
VITE_APP_ENV = 'development' VITE_APP_ENV = 'development'
# 招商车研物联网平台/开发环境 # 招商车研物联网平台/开发环境
VITE_APP_BASE_API = '/dev-api' VITE_APP_BASE_API = '/dev-api'
VITE_API_URL = http://10.148.20.34:13080 VITE_API_URL = http://192.168.0.100:13080
VITE_WS_URL = ws://10.148.20.34:13080/ws VITE_WS_URL = ws://192.168.0.100:13080/ws
# VITE_API_URL = http://10.148.108.95:13080 //杨溪IP # VITE_API_URL = http://10.148.108.95:13080 //杨溪IP
# VITE_API_URL = http://10.148.108.58:13080 //赵培利IP # VITE_API_URL = http://10.148.108.58:13080 //赵培利IP
#node-red 服务地址
#VITE_NODE_RED_URL = 'http://10.148.20.34:13080'
VITE_NODE_RED_URL = 'http://10.148.108.59:1880'

44
src/api/vi/corpus.js Normal file
View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询语料库列表
export function listCorpus(query) {
return request({
url: '/vi/corpus/list',
method: 'get',
params: query
})
}
// 查询语料库详细
export function getCorpus(corpusId) {
return request({
url: '/vi/corpus/' + corpusId,
method: 'get'
})
}
// 新增语料库
export function addCorpus(data) {
return request({
url: '/vi/corpus',
method: 'post',
data: data
})
}
// 修改语料库
export function updateCorpus(data) {
return request({
url: '/vi/corpus',
method: 'put',
data: data
})
}
// 删除语料库
export function delCorpus(corpusId) {
return request({
url: '/vi/corpus/' + corpusId,
method: 'delete'
})
}

View File

@ -1,96 +1,96 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import Cookies from 'js-cookie' import Cookies from 'js-cookie'
import ElementPlus from 'element-plus' import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css' import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css' import 'element-plus/theme-chalk/dark/css-vars.css'
import locale from 'element-plus/es/locale/lang/zh-cn' import locale from 'element-plus/es/locale/lang/zh-cn'
import '@/assets/styles/index.scss' // global css import '@/assets/styles/index.scss' // global css
import App from './App' import App from './App'
import store from './store' import store from './store'
import router from './router' import router from './router'
import directive from './directive' // directive import directive from './directive' // directive
import WebSocketPlugin from './plugins/websocket'; import WebSocketPlugin from './plugins/websocket';
// 注册指令 // 注册指令
import plugins from './plugins' // plugins import plugins from './plugins' // plugins
import { download } from '@/utils/request' import { download } from '@/utils/request'
// svg图标 // svg图标
import 'virtual:svg-icons-register' import 'virtual:svg-icons-register'
import SvgIcon from '@/components/SvgIcon' import SvgIcon from '@/components/SvgIcon'
import elementIcons from '@/components/SvgIcon/svgicon' import elementIcons from '@/components/SvgIcon/svgicon'
import './permission' // permission control import './permission' // permission control
import { useDict } from '@/utils/dict' import { useDict } from '@/utils/dict'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi' import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'
// 分页组件 // 分页组件
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
// 自定义表格工具组件 // 自定义表格工具组件
import RightToolbar from '@/components/RightToolbar' import RightToolbar from '@/components/RightToolbar'
// 富文本组件 // 富文本组件
import Editor from "@/components/Editor" import Editor from "@/components/Editor"
// 文件上传组件 // 文件上传组件
import FileUpload from "@/components/FileUpload" import FileUpload from "@/components/FileUpload"
// 图片上传组件 // 图片上传组件
import ImageUpload from "@/components/ImageUpload" import ImageUpload from "@/components/ImageUpload"
// 图片预览组件 // 图片预览组件
import ImagePreview from "@/components/ImagePreview" import ImagePreview from "@/components/ImagePreview"
// 字典标签组件 // 字典标签组件
import DictTag from '@/components/DictTag' import DictTag from '@/components/DictTag'
// ace.config.js独立配置文件 // ace.config.js独立配置文件
import ace from 'ace-builds'; import ace from 'ace-builds';
import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url'; import modeJsonUrl from 'ace-builds/src-noconflict/mode-json?url';
ace.config.setModuleUrl('ace/mode/json', modeJsonUrl); // 动态绑定语法模块路径 ace.config.setModuleUrl('ace/mode/json', modeJsonUrl); // 动态绑定语法模块路径
const app = createApp(App) const app = createApp(App)
// 全局方法挂载 // 全局方法挂载
app.config.globalProperties.useDict = useDict app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime app.config.globalProperties.parseTime = parseTime
app.config.globalProperties.resetForm = resetForm app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.selectDictLabel = selectDictLabel app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels app.config.globalProperties.selectDictLabels = selectDictLabels
// 全局组件挂载 // 全局组件挂载
app.component('DictTag', DictTag) app.component('DictTag', DictTag)
app.component('Pagination', Pagination) app.component('Pagination', Pagination)
app.component('FileUpload', FileUpload) app.component('FileUpload', FileUpload)
app.component('ImageUpload', ImageUpload) app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview) app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar) app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor) app.component('Editor', Editor)
app.use(router) app.use(router)
app.use(store) app.use(store)
app.use(plugins) app.use(plugins)
app.use(elementIcons) app.use(elementIcons)
app.component('svg-icon', SvgIcon) app.component('svg-icon', SvgIcon)
directive(app) directive(app)
// 使用element-plus 并且设置全局的大小 // 使用element-plus 并且设置全局的大小
app.use(ElementPlus, { app.use(ElementPlus, {
locale: locale, locale: locale,
// 支持 large、default、small // 支持 large、default、small
size: Cookies.get('size') || 'default' size: Cookies.get('size') || 'default'
}) })
app.use(WebSocketPlugin, { app.use(WebSocketPlugin, {
// url: import.meta.env.VITE_WS_URL, // url: import.meta.env.VITE_WS_URL,
url: 'ws://10.148.108.95:13080/ws', url: 'ws://192.168.0.100:13080/ws',
// url: 'ws://10.148.209.5:13080/ws', // url: 'ws://10.148.209.5:13080/ws',
userId: 'your_user_id' userId: 'your_user_id'
}); });
app.mount('#app') app.mount('#app')

View File

@ -1,210 +1,221 @@
export const getInput = (nodeId, isStrict = true) => { export const getInput = (nodeId, isStrict = true) => {
const data = lf.getGraphData(); const data = lf.getGraphData();
let flag = false let flag = false
if (isStrict) { if (isStrict) {
data.edges.forEach(item => { data.edges.forEach(item => {
if (item.targetNodeId === nodeId) { if (item.targetNodeId === nodeId) {
flag = true flag = true
} }
}); });
} else { } else {
flag = true flag = true
} }
if (flag) { if (flag) {
const arr = [] const arr = []
data.nodes.forEach(item => { data.nodes.forEach(item => {
if (item.id === nodeId) { if (item.id === nodeId) {
return return
} }
if (item.properties.inputParams) { if (item.properties.inputParams) {
const obj = { const obj = {
value: item.id, value: item.id,
label: item.properties.name, label: item.properties.name,
children: [] children: []
} }
const optionData = transformTree(item.properties.inputParams, obj.children) const optionData = transformTree(item.properties.inputParams, obj.children)
obj.children.push(optionData) obj.children.push(optionData)
arr.push(obj) arr.push(obj)
} }
if (item.properties.nodeParams) { if (item.properties.nodeParams) {
const obj = { const obj = {
value: item.id, value: item.id,
label: item.properties.name, label: item.properties.name + '(输入)',
children: [] children: []
} }
const optionData = transformTree(item.properties.nodeParams, obj.children) const optionData = transformTree(item.properties.nodeParams, obj.children)
obj.children.push(optionData) obj.children.push(optionData)
arr.push(obj) arr.push(obj)
} }
})
return arr if (item.properties.outputParams) {
} const obj = {
return flag value: item.id,
} label: item.properties.name + '(输出)',
children: []
const transformTree = (arr, parent = []) => { }
arr.forEach(item => { const optionData = transformTree(item.properties.outputParams, obj.children)
const currentNode = { obj.children.push(optionData)
value: item.name, arr.push(obj)
label: item.name, }
children: [] })
}; return arr
parent.push(currentNode); }
return flag
if (item.children?.length > 0) { }
transformTree(item.children, currentNode.children);
} else { const transformTree = (arr, parent = []) => {
delete currentNode.children arr.forEach(item => {
} const currentNode = {
}); value: item.name,
return parent; label: item.name,
}; children: []
};
export const getStartNodeFormData = () => { parent.push(currentNode);
const flowData = lf.getGraphData();
const startNode = flowData.nodes.find(item => item.type === 'start') if (item.children?.length > 0) {
const data = addValueProperty(startNode.properties?.inputParams || []) transformTree(item.children, currentNode.children);
return data } else {
} delete currentNode.children
}
export const addValueProperty = (data) => { });
// 处理单个对象或对象数组 return parent;
const processItem = (item, index, path) => { };
// 根据类型设置默认值
item.value = ''; export const getStartNodeFormData = () => {
item.propPath = `${path}.${index}.` const flowData = lf.getGraphData();
if (item.type.includes('array') && !item.type.includes('object')) { const startNode = flowData.nodes.find(item => item.type === 'start')
const type = item.type.match(/<([^>]+)>/)[1] const data = addValueProperty(startNode.properties?.inputParams || [])
item.children = [{ name: 'Array Item', type, value: '', propPath: item.propPath + '.0'}] return data
} }
// 递归处理子项
if (item.children && item.children.length > 0) { export const addValueProperty = (data) => {
item.children = item.children.map((cItem, cIndex) => { // 处理单个对象或对象数组
return processItem(cItem, cIndex , item.propPath + 'children') const processItem = (item, index, path) => {
}); // 根据类型设置默认值
} item.value = '';
item.propPath = `${path}.${index}.`
return item; if (item.type.includes('array') && !item.type.includes('object')) {
}; const type = item.type.match(/<([^>]+)>/)[1]
item.children = [{ name: 'Array Item', type, value: '', propPath: item.propPath + '.0'}]
// 如果传入的是数组,处理每个元素;否则处理单个对象 }
return Array.isArray(data) ? data.map((item, index) => processItem(item, index, '')) : processItem(data, 0, '') // 递归处理子项
} if (item.children && item.children.length > 0) {
item.children = item.children.map((cItem, cIndex) => {
export const recursiveFilter = (data, id, type = ['loop', 'customGroup'], result = []) => { return processItem(cItem, cIndex , item.propPath + 'children')
data.forEach((item) => { });
if (type.includes(item.type) && item.children && item.children.includes(id)) { }
result.push(item)
recursiveFilter(data, item.id, result) return item;
} };
});
return result // 如果传入的是数组,处理每个元素;否则处理单个对象
} return Array.isArray(data) ? data.map((item, index) => processItem(item, index, '')) : processItem(data, 0, '')
}
export const formatTableData = (arr, data = {}) => {
arr.forEach(item => { export const recursiveFilter = (data, id, type = ['loop', 'customGroup'], result = []) => {
data[item.name] = item.value data.forEach((item) => {
if (item?.children && item.children.length > 0) { if (type.includes(item.type) && item.children && item.children.includes(id)) {
data[item.name] = {} result.push(item)
formatTableData(item.children, data[item.name]) recursiveFilter(data, item.id, result)
} }
}) });
return data return result
} }
export const addNewEdge = (nodeId) => { export const formatTableData = (arr, data = {}) => {
const { edges } = lf.getGraphData(); arr.forEach(item => {
const arr = JSON.parse(JSON.stringify(edges)) data[item.name] = item.value
arr.forEach(_edge => { if (item?.children && item.children.length > 0) {
const { sourceNodeId, targetNodeId, sourceAnchorId, targetAnchorId } = _edge data[item.name] = {}
if (sourceNodeId === nodeId || targetNodeId === nodeId) { formatTableData(item.children, data[item.name])
lf.deleteEdge(_edge.id); }
lf.addEdge({ })
type: "bezier", return data
sourceNodeId: sourceNodeId, }
targetNodeId: targetNodeId,
sourceAnchorId: sourceAnchorId, export const addNewEdge = (nodeId) => {
targetAnchorId: targetAnchorId const { edges } = lf.getGraphData();
}); const arr = JSON.parse(JSON.stringify(edges))
} arr.forEach(_edge => {
}) const { sourceNodeId, targetNodeId, sourceAnchorId, targetAnchorId } = _edge
} if (sourceNodeId === nodeId || targetNodeId === nodeId) {
lf.deleteEdge(_edge.id);
export const getInputNumber = (nodeId) => { lf.addEdge({
const data = lf.getGraphData(); type: "bezier",
let flag = false sourceNodeId: sourceNodeId,
data.edges.forEach(item => { targetNodeId: targetNodeId,
if (item.targetNodeId === nodeId) { sourceAnchorId: sourceAnchorId,
flag = true targetAnchorId: targetAnchorId
} });
}); }
if (flag) { })
const arr = [] }
data.nodes.forEach(item => {
if (item.properties.inputParams) { export const getInputNumber = (nodeId) => {
item.properties.inputParams.forEach(item => { const data = lf.getGraphData();
if (item.type === 'number') { let flag = false
arr.push(item) data.edges.forEach(item => {
} if (item.targetNodeId === nodeId) {
}) flag = true
} }
}) });
return arr if (flag) {
} const arr = []
return flag data.nodes.forEach(item => {
} if (item.properties.inputParams) {
item.properties.inputParams.forEach(item => {
export const removeSwitchEdge = (nodeId, sourceAnchorId) => { if (item.type === 'number') {
const { edges } = lf.getGraphData(); arr.push(item)
const edge = edges.find(item => { }
return item.sourceNodeId === nodeId && item.sourceAnchorId === sourceAnchorId })
}) }
})
if (edge) { return arr
lf.deleteEdge(edge.id); }
} return flag
} }
export const convertToTree = (data) => { export const removeSwitchEdge = (nodeId, sourceAnchorId) => {
// 创建 id 到节点的映射 const { edges } = lf.getGraphData();
const nodeMap = new Map(); const edge = edges.find(item => {
data.forEach(node => { return item.sourceNodeId === nodeId && item.sourceAnchorId === sourceAnchorId
nodeMap.set(node.id, { ...node, name: node.properties.name || '' }); // 浅拷贝节点 })
});
if (edge) {
// 标记非根节点(被其他节点引用的节点) lf.deleteEdge(edge.id);
const nonRootIds = new Set(); }
data.forEach(node => { }
if (node.children) {
node.children.forEach(childId => { export const convertToTree = (data) => {
nonRootIds.add(childId); // 创建 id 到节点的映射
}); const nodeMap = new Map();
} data.forEach(node => {
}); nodeMap.set(node.id, { ...node, name: node.properties.name || '' }); // 浅拷贝节点
});
// 构建树形结构
const result = []; // 标记非根节点(被其他节点引用的节点)
data.forEach(node => { const nonRootIds = new Set();
// 只处理根节点(未被引用的节点) data.forEach(node => {
if (!nonRootIds.has(node.id)) { if (node.children) {
const rootNode = nodeMap.get(node.id); node.children.forEach(childId => {
// 递归处理子节点 nonRootIds.add(childId);
const processNode = (currentNode) => { });
if (currentNode.children) { }
currentNode.children = currentNode.children.map(childId => { });
const childNode = nodeMap.get(childId);
processNode(childNode); // 递归处理子节点 // 构建树形结构
return childNode; const result = [];
}); data.forEach(node => {
} // 只处理根节点(未被引用的节点)
return currentNode; if (!nonRootIds.has(node.id)) {
}; const rootNode = nodeMap.get(node.id);
// 递归处理子节点
result.push(processNode(rootNode)); const processNode = (currentNode) => {
} if (currentNode.children) {
}); currentNode.children = currentNode.children.map(childId => {
const childNode = nodeMap.get(childId);
return result; processNode(childNode); // 递归处理子节点
return childNode;
});
}
return currentNode;
};
result.push(processNode(rootNode));
}
});
return result;
} }

View File

@ -1,201 +1,200 @@
<template> <template>
<div class="group__container" @mouseleave="setNodeProperties"> <div class="group__container" @mouseleave="setNodeProperties">
<NodeTitle :icon="loop" :nodeId="props.model.id" :nodeProperties="props.properties" :nodeName="props.properties?.name || '循环'" nodeDesc="循环执行一系列任务,直至输出所有结果" /> <NodeTitle :icon="loop" :nodeId="props.model.id" :nodeProperties="props.properties" :nodeName="props.properties?.name || '循环'" nodeDesc="循环执行一系列任务,直至输出所有结果" />
<div class="loop__container"> <div class="loop__container">
<div> <div>
<el-form :inline="true" :model="formData" :rules="rules" ref="dynamicForm" label-position="top" label-width="auto" :disabled="flowStore.disableForm"> <el-form :inline="true" :model="formData" :rules="rules" ref="dynamicForm" label-position="top" label-width="auto" :disabled="flowStore.disableForm">
<div v-for="(property, index) in formData.nodeParams" :key="index"> <div v-for="(property, index) in formData.nodeParams" :key="index">
<el-row> <el-row>
<el-form-item :label="index === 0 ? '参数名' : ''" :prop="`nodeParams.${index}.name`" :rules="[{ required: true, message: '请输入参数名', trigger: 'blur' }]"> <el-form-item :label="index === 0 ? '参数名' : ''" :prop="`nodeParams.${index}.name`" :rules="[{ required: true, message: '请输入参数名', trigger: 'blur' }]">
<el-input :disabled="index === 0" v-model="property.name" placeholder="请输入" clearable /> <el-input :disabled="index === 0" v-model="property.name" placeholder="请输入" clearable />
</el-form-item> </el-form-item>
<el-form-item :label="index === 0 ? '参数值' : ''" :prop="`nodeParams.${index}.type`" > <el-form-item :label="index === 0 ? '参数值' : ''" :prop="`nodeParams.${index}.type`" >
<el-select v-model="property.type" @change="handleTypeChange(index)"> <el-select v-model="property.type" @change="handleTypeChange(index)">
<el-option label="引用" value="quote" /> <el-option label="引用" value="quote" />
<el-option label="输入" value="input" /> <el-option label="输入" value="input" />
</el-select> </el-select>
<el-form-item v-if="property.type === 'input'" :rules="[{ required: true, message: '请输入参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.input`"> <el-form-item v-if="property.type === 'input'" :rules="[{ required: true, message: '请输入参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.input`">
<el-input-number v-model="property.input" :min="0" :controls="false" :step-strictly="true" placeholder="请输入" clearable /> <el-input-number v-model="property.input" :min="0" :controls="false" :step-strictly="true" placeholder="请输入" clearable />
</el-form-item> </el-form-item>
<el-form-item v-if="property.type === 'quote'" :rules="[{ required: true, message: '请选择参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.quote`"> <el-form-item v-if="property.type === 'quote'" :rules="[{ required: true, message: '请选择参数值', trigger: 'blur' }]" :prop="`nodeParams.${index}.quote`">
<el-cascader v-model="property.quote" :options="quoteOptions" placeholder="请选择" @visible-change="visibleChange"/> <el-cascader v-model="property.quote" :options="quoteOptions" placeholder="请选择" @visible-change="visibleChange"/>
</el-form-item> </el-form-item>
</el-form-item> </el-form-item>
</el-row> </el-row>
</div> </div>
</el-form> </el-form>
</div> </div>
</div> </div>
<div>循环体</div> <div>循环体</div>
<div class="child__container" @drop="handleDrop" @dragover="handleDragover"> <div class="child__container" @drop="handleDrop" @dragover="handleDragover">
<slot></slot> <slot></slot>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, onMounted } from 'vue' import { ref, onMounted } from 'vue'
import NodeTitle from '../../components/NodeTitle.vue' import NodeTitle from '../../components/NodeTitle.vue'
import loop from '../../icon/loop.svg' import loop from '../../icon/loop.svg'
import { useFlowStore } from '@/store/modules/flow' import { useFlowStore } from '@/store/modules/flow'
import { addNewEdge, getInputNumber } from '@/utils/flow' import { addNewEdge, getInput } from '@/utils/flow'
const props = defineProps({ const props = defineProps({
model: Object, model: Object,
graphModel: Object, graphModel: Object,
properties: Object, properties: Object,
nowTime: Number, nowTime: Number,
}); });
const flowStore = useFlowStore() const flowStore = useFlowStore()
const formData = reactive({ const formData = reactive({
nodeParams: [ nodeParams: [
{ name: "loopNum", type: "input", input: null, quote: "" } { name: "loopNum", type: "input", input: null, quote: "" }
] ]
}) })
const quoteOptions = ref([]) const quoteOptions = ref([])
const handleTypeChange = (index) => { const handleTypeChange = (index) => {
if (formData.nodeParams[index].type === 'input') { if (formData.nodeParams[index].type === 'input') {
formData.nodeParams[index].quote = "" formData.nodeParams[index].quote = ""
} else { } else {
formData.nodeParams[index].input = null formData.nodeParams[index].input = null
const option = getInputNumber(props.model.id) const option = getInput(props.model.id)
if (option) { if (option) {
quoteOptions.value = option quoteOptions.value = option
} }
} }
} }
const rules = reactive({}) const rules = reactive({})
const emits = defineEmits(['bindRef', 'addToGroup', 'contentChange']) const emits = defineEmits(['bindRef', 'addToGroup', 'contentChange'])
const handleDragover = (e) => { const handleDragover = (e) => {
e.preventDefault() e.preventDefault()
} }
const handleDrop = (e) => { const handleDrop = (e) => {
e.preventDefault() e.preventDefault()
e.stopPropagation(); e.stopPropagation();
// const type = e.dataTransfer.getData('nodeType'); let flowNode = e.dataTransfer.getData('flowNode');
let flowNode = e.dataTransfer.getData('flowNode'); flowNode = JSON.parse(flowNode)
flowNode = JSON.parse(flowNode) const point = lf.getPointByClient(e.clientX, e.clientY)
const point = lf.getPointByClient(e.clientX, e.clientY) const { type, ...other } = flowNode
const { type, ...other } = flowNode const node = lf.addNode({
const node = lf.addNode({ type,
type, x: point.canvasOverlayPosition.x,
x: point.canvasOverlayPosition.x, y: point.canvasOverlayPosition.y,
y: point.canvasOverlayPosition.y, properties: {
properties: { parentId: props.model.id,
parentId: props.model.id, ...other
...other }
} })
})
emits('addToGroup', node.id)
emits('addToGroup', node.id) setTimeout(() => {
setTimeout(() => { addNewEdge(props.model.id)
addNewEdge(props.model.id) }, 50)
}, 50) }
}
const dynamicForm = ref()
const dynamicForm = ref()
const setNodeProperties = async () => {
const setNodeProperties = async () => { try {
try { const valid = await dynamicForm.value.validate()
const valid = await dynamicForm.value.validate() if (valid) {
if (valid) { const data = toRaw(formData)
const data = toRaw(formData) setTimeout(() => {
setTimeout(() => { const properties = lf.getProperties(props.model.id)
const properties = lf.getProperties(props.model.id) window.lf.setProperties(props.model.id, {
window.lf.setProperties(props.model.id, { ...properties,
...properties, ...data
...data })
}) }, 50)
}, 50) }
} } catch (error) {
} catch (error) { dynamicForm.value.clearValidate()
dynamicForm.value.clearValidate() }
} }
}
const visibleChange = (value) => {
const visibleChange = (value) => { if (value) {
if (value) { const option = getInput(props.model.id)
const option = getInput(props.model.id) if (option) {
if (option) { quoteOptions.value = option
quoteOptions.value = option }
} }
} }
}
watch(
watch( () => props.properties,
() => props.properties, () => {
() => { if (props.properties.nodeParams && props.properties.nodeParams.length > 0) {
if (props.properties.nodeParams && props.properties.nodeParams.length > 0) { formData.nodeParams = props.properties.nodeParams
formData.nodeParams = props.properties.nodeParams const option = getInputNumber(props.model.id)
const option = getInputNumber(props.model.id) if (option) {
if (option) { quoteOptions.value = option
quoteOptions.value = option }
} }
} }, {
}, { immediate: true,
immediate: true, deep: true
deep: true }
} )
)
onMounted(() => {
onMounted(() => { emits('bindRef', dynamicForm.value)
emits('bindRef', dynamicForm.value) })
})
</script>
</script> <style lang="scss" scoped>
<style lang="scss" scoped> .group__container {
.group__container { width: 100%;
width: 100%; height: 100%;
height: 100%; background: #fff;
background: #fff; padding: 12px;
padding: 12px; cursor: default;
cursor: default; border-radius: 12px;
border-radius: 12px; border: 2px solid white;
border: 2px solid white; box-shadow: 0 5px 15px 0#00000008;
box-shadow: 0 5px 15px 0#00000008; display: flex;
display: flex; flex-direction: column;
flex-direction: column; position: relative;
position: relative;
.title {
.title { height: 40px;
height: 40px; }
}
:deep(.loop__container) {
:deep(.loop__container) { height: 80px;
height: 80px;
.el-input {
.el-input { width: 92px;
width: 92px; }
}
.el-input-number {
.el-input-number { width: 92px;
width: 92px; }
}
.el-select {
.el-select { width: 92px;
width: 92px; }
}
.el-cascader {
.el-cascader { width: 92px;
width: 92px; }
} }
}
.child__container {
.child__container { min-height: 80px;
min-height: 80px; flex: 1;
flex: 1; background-color: #f6f8fa;
background-color: #f6f8fa; border-radius: 8px;
border-radius: 8px; }
}
.el-row {
.el-row { align-items: end;
align-items: end; }
} }
}
</style> </style>

View File

@ -0,0 +1,322 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="语料名称" prop="corpusName">
<el-input
v-model="queryParams.corpusName"
placeholder="请输入语料名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="音色" prop="voiceType">
<el-select v-model="queryParams.voiceType" placeholder="请选择音色" clearable style="width: 200px">
<el-option
v-for="dict in vi_voice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="语种" prop="dialect">
<el-select v-model="queryParams.voiceType" placeholder="请选择语种" clearable style="width: 200px">
<el-option
v-for="dict in vi_dialect_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="预期结果" prop="expectedResult">
<el-input
v-model="queryParams.expectedResult"
placeholder="请输入预期结果"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['vi:corpus:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['vi:corpus:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['vi:corpus:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['vi:corpus:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="corpusList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="语料名称" align="center" prop="corpusName" />
<el-table-column label="语料类型" align="center" prop="type" />
<el-table-column label="语音文本" align="center" prop="textContent" />
<el-table-column label="语音文件路径" align="center" prop="audioPath" />
<el-table-column label="音色" align="center" prop="voiceType" />
<el-table-column label="语种" align="center" prop="dialect" />
<el-table-column label="预期结果" align="center" prop="expectedResult" />
<el-table-column label="顺序" align="center" prop="sortOrder" />
<el-table-column label="状态" align="center" prop="status" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['vi:corpus:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['vi:corpus:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改语料库对话框 -->
<el-dialog :title="title" v-model="open" width="580px" append-to-body>
<el-form ref="corpusRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="语料名称" prop="corpusName">
<el-input v-model="form.corpusName" placeholder="请输入语料名称" />
</el-form-item>
<el-form-item label="语音文本">
<el-input v-model="form.textContent" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="文件路径" prop="audioPath">
<el-input v-model="form.audioPath" type="textarea" placeholder="请输入内容" />
</el-form-item>
<el-form-item label="音色" prop="voiceType">
<el-select v-model="form.voiceType" placeholder="请选择音色" clearable style="width: 100%">
<el-option
v-for="dict in vi_voice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="语种" prop="dialect">
<el-select v-model="form.voiceType" placeholder="请选择语种" clearable style="width: 100%">
<el-option
v-for="dict in vi_dialect_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="预期结果" prop="expectedResult">
<el-input v-model="form.audioPath" type="textarea" placeholder="请输入预期结果" />
</el-form-item>
<el-form-item label="顺序" prop="sortOrder">
<el-input v-model="form.sortOrder" placeholder="请输入同一父语料下的顺序" />
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Corpus">
import { listCorpus, getCorpus, delCorpus, addCorpus, updateCorpus } from "@/api/vi/corpus"
const { proxy } = getCurrentInstance()
const { vi_voice_type, vi_dialect_type } = proxy.useDict("vi_voice_type", "vi_dialect_type")
const corpusList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
corpusName: null,
type: 'WAKE',
textContent: null,
audioPath: null,
voiceType: null,
dialect: null,
expectedResult: null,
sortOrder: null,
status: null,
},
rules: {
type: [
{ required: true, message: "语料类型不能为空", trigger: "change" }
],
textContent: [
{ required: true, message: "语音对应的文本不能为空", trigger: "blur" }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询语料库列表 */
function getList() {
loading.value = true
listCorpus(queryParams.value).then(response => {
corpusList.value = response.rows
total.value = response.total
loading.value = false
}).catch(err => {
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
corpusId: null,
corpusName: null,
type: null,
textContent: null,
audioPath: null,
voiceType: null,
dialect: null,
expectedResult: null,
sortOrder: null,
status: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null
}
proxy.resetForm("corpusRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.corpusId)
single.value = selection.length != 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加语料库"
}
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _corpusId = row.corpusId || ids.value
getCorpus(_corpusId).then(response => {
form.value = response.data
open.value = true
title.value = "修改语料库"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["corpusRef"].validate(valid => {
if (valid) {
if (form.value.corpusId != null) {
updateCorpus(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addCorpus(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _corpusIds = row.corpusId || ids.value
proxy.$modal.confirm('是否确认删除语料库编号为"' + _corpusIds + '"的数据项?').then(function() {
return delCorpus(_corpusIds)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('vi/corpus/export', {
...queryParams.value
}, `corpus_${new Date().getTime()}.xlsx`)
}
getList()
</script>

View File

@ -0,0 +1,335 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="语料名称" prop="corpusName">
<el-input
v-model="queryParams.corpusName"
placeholder="请输入语料名称"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item label="音色" prop="voiceType">
<el-select v-model="queryParams.voiceType" placeholder="请选择音色" clearable style="width: 200px">
<el-option
v-for="dict in vi_voice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="语种" prop="dialect">
<el-select v-model="queryParams.voiceType" placeholder="请选择语种" clearable style="width: 200px">
<el-option
v-for="dict in vi_dialect_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="预期结果" prop="expectedResult">
<el-input
v-model="queryParams.expectedResult"
placeholder="请输入预期结果"
clearable
@keyup.enter="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="Plus"
@click="handleAdd"
v-hasPermi="['vi:corpus:add']"
>新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="success"
plain
icon="Edit"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['vi:corpus:edit']"
>修改</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="Delete"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['vi:corpus:remove']"
>删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="Download"
@click="handleExport"
v-hasPermi="['vi:corpus:export']"
>导出</el-button>
</el-col>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="corpusList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="语料名称" align="center" prop="corpusName" />
<el-table-column label="语料类型" align="center" prop="type" />
<el-table-column label="语音文本" align="center" prop="textContent" />
<el-table-column label="语音文件路径" align="center" prop="audioPath" />
<el-table-column label="音色" align="center" prop="voiceType" />
<el-table-column label="语种" align="center" prop="dialect" />
<el-table-column label="预期结果" align="center" prop="expectedResult" />
<el-table-column label="顺序" align="center" prop="sortOrder" />
<el-table-column label="状态" align="center" prop="status" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['vi:corpus:edit']">修改</el-button>
<el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['vi:corpus:remove']">删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 添加或修改语料库对话框 -->
<el-dialog :title="title" v-model="open" width="640px" append-to-body>
<el-form ref="corpusRef" :model="form" :rules="rules" label-width="80px">
<el-form-item label="语料名称" prop="corpusName">
<el-input v-model="form.corpusName" placeholder="请输入语料名称" />
</el-form-item>
<el-form-item label="音色" prop="voiceType">
<el-select v-model="form.voiceType" placeholder="请选择音色" clearable style="width: 100%">
<el-option
v-for="dict in vi_voice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="语种" prop="dialect">
<el-select v-model="form.voiceType" placeholder="请选择语种" clearable style="width: 100%">
<el-option
v-for="dict in vi_dialect_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</el-form>
<el-table :data="tableData">
<el-table-column prop="num" label="序号">
<template #default="{ row }">
<el-inputNumber style="width: 100px;" v-model="row.num" />
</template>
</el-table-column>
<el-table-column prop="textContent" label="语料文本">
<template #default="{ row }">
<el-input v-model="row.textContent" />
</template>
</el-table-column>
<el-table-column prop="audioPath" label="音频文件">
<el-button>上传文件</el-button>
</el-table-column>
<el-table-column prop="expectedResult" label="预期结果">
<template #default="{ row }">
<el-input v-model="row.expectedResult" />
</template>
</el-table-column>
<el-table-column prop="action" label="操作">
</el-table-column>
</el-table>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script setup name="Corpus">
import { listCorpus, getCorpus, delCorpus, addCorpus, updateCorpus } from "@/api/vi/corpus"
const { proxy } = getCurrentInstance()
const { vi_voice_type, vi_dialect_type } = proxy.useDict("vi_voice_type", "vi_dialect_type")
const corpusList = ref([])
const open = ref(false)
const loading = ref(true)
const showSearch = ref(true)
const ids = ref([])
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const title = ref("")
const data = reactive({
form: {},
queryParams: {
pageNum: 1,
pageSize: 10,
corpusName: null,
type: null,
textContent: null,
audioPath: null,
voiceType: null,
dialect: null,
expectedResult: null,
sortOrder: null,
status: null,
},
rules: {
type: [
{ required: true, message: "语料类型不能为空", trigger: "change" }
],
textContent: [
{ required: true, message: "语音对应的文本不能为空", trigger: "blur" }
],
}
})
const { queryParams, form, rules } = toRefs(data)
/** 查询语料库列表 */
function getList() {
loading.value = true
listCorpus(queryParams.value).then(response => {
corpusList.value = response.rows
total.value = response.total
loading.value = false
}).catch(err => {
loading.value = false
})
}
//
function cancel() {
open.value = false
reset()
}
//
function reset() {
form.value = {
corpusId: null,
corpusName: null,
type: null,
textContent: null,
audioPath: null,
voiceType: null,
dialect: null,
expectedResult: null,
sortOrder: null,
status: null,
createBy: null,
createTime: null,
updateBy: null,
updateTime: null
}
proxy.resetForm("corpusRef")
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1
getList()
}
/** 重置按钮操作 */
function resetQuery() {
proxy.resetForm("queryRef")
handleQuery()
}
//
function handleSelectionChange(selection) {
ids.value = selection.map(item => item.corpusId)
single.value = selection.length != 1
multiple.value = !selection.length
}
/** 新增按钮操作 */
function handleAdd() {
reset()
open.value = true
title.value = "添加语料库"
}
const tableData = ref([{}])
/** 修改按钮操作 */
function handleUpdate(row) {
reset()
const _corpusId = row.corpusId || ids.value
getCorpus(_corpusId).then(response => {
form.value = response.data
open.value = true
title.value = "修改语料库"
})
}
/** 提交按钮 */
function submitForm() {
proxy.$refs["corpusRef"].validate(valid => {
if (valid) {
if (form.value.corpusId != null) {
updateCorpus(form.value).then(response => {
proxy.$modal.msgSuccess("修改成功")
open.value = false
getList()
})
} else {
addCorpus(form.value).then(response => {
proxy.$modal.msgSuccess("新增成功")
open.value = false
getList()
})
}
}
})
}
/** 删除按钮操作 */
function handleDelete(row) {
const _corpusIds = row.corpusId || ids.value
proxy.$modal.confirm('是否确认删除语料库编号为"' + _corpusIds + '"的数据项?').then(function() {
return delCorpus(_corpusIds)
}).then(() => {
getList()
proxy.$modal.msgSuccess("删除成功")
}).catch(() => {})
}
/** 导出按钮操作 */
function handleExport() {
proxy.download('vi/corpus/export', {
...queryParams.value
}, `corpus_${new Date().getTime()}.xlsx`)
}
getList()
</script>

View File

@ -32,11 +32,11 @@ export default defineConfig(({mode, command}) => {
proxy: { proxy: {
// https://cn.vitejs.dev/config/#server-proxy // https://cn.vitejs.dev/config/#server-proxy
'/dev-api': { '/dev-api': {
//杨 http://192.168.1.10:13080 //杨 http://192.168.0.10:13080
//赵 http://10.148.108.58:13080 //赵 http://10.148.108.58:13080
// dev http://10.148.20.34:13080 // dev http://10.148.20.34:13080
// target: command === 'build' ? VITE_API_URL : 'http://10.148.20.34:13080', // target: command === 'build' ? VITE_API_URL : 'http://10.148.20.34:13080',
target: command === 'build' ? VITE_API_URL : 'http://192.168.1.10:13080', target: command === 'build' ? VITE_API_URL : 'http://192.168.0.10:13080',
changeOrigin: true, changeOrigin: true,
rewrite: (p) => p.replace(/^\/dev-api/, '') rewrite: (p) => p.replace(/^\/dev-api/, '')
} }