2025-11-26 18:25:40 +08:00
|
|
|
|
<template>
|
|
|
|
|
|
<el-card class="analysis-rule-container">
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<!-- 返回按钮和保存按钮 -->
|
2025-11-26 18:25:40 +08:00
|
|
|
|
<div class="back-container">
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleSaveRules"
|
2025-11-28 14:27:39 +08:00
|
|
|
|
:disabled="!selectedLabelItemId ||
|
|
|
|
|
|
(currentTab === 'ruleConfig' && (ruleSets.length === 0 || contentSources.length === 0)) ||
|
|
|
|
|
|
(currentTab === 'promptConfig' && !promptWord.trim())"
|
2025-11-26 18:25:40 +08:00
|
|
|
|
class="save-btn"
|
|
|
|
|
|
>
|
|
|
|
|
|
保存
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="default"
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
@click="handleBack"
|
|
|
|
|
|
class="back-btn">
|
|
|
|
|
|
返回
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
|
<!-- 左侧树状图区域 -->
|
|
|
|
|
|
<el-col :span="4">
|
|
|
|
|
|
<div class="tree-container" style="height: calc(100vh - 205px)">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
placeholder="搜索标签项"
|
|
|
|
|
|
v-model="treeSearchKey"
|
|
|
|
|
|
class="tree-search"
|
|
|
|
|
|
clearable
|
|
|
|
|
|
size="small"
|
|
|
|
|
|
/>
|
|
|
|
|
|
|
|
|
|
|
|
<el-tree
|
|
|
|
|
|
ref="labelItemTree"
|
|
|
|
|
|
:data="treeData"
|
|
|
|
|
|
:props="treeProps"
|
|
|
|
|
|
node-key="analysisLabelItemId"
|
|
|
|
|
|
:filter-node-method="filterTreeNode"
|
|
|
|
|
|
:highlight-current="true"
|
|
|
|
|
|
default-expand-all
|
|
|
|
|
|
@node-click="handleTreeNodeClick"
|
|
|
|
|
|
@current-change="handleTreeNodeChange"
|
|
|
|
|
|
>
|
|
|
|
|
|
<template #default="{ node, data }">
|
|
|
|
|
|
<span class="tree-node-content">
|
|
|
|
|
|
<span
|
|
|
|
|
|
:style="{
|
|
|
|
|
|
color: data.analysisLevel === 3 ? '#1F72EA' : '#333',
|
|
|
|
|
|
fontWeight: data.analysisLevel === 3 ? '500' : 'normal'
|
|
|
|
|
|
}"
|
|
|
|
|
|
>
|
|
|
|
|
|
{{ node.label }}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</el-tree>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 右侧解析规则配置区域 -->
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<el-col :span="13">
|
2025-11-26 18:25:40 +08:00
|
|
|
|
<div class="rule-config-container">
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<!-- 标签切换 -->
|
|
|
|
|
|
<el-tabs v-model="currentTab" @tab-click="handleTabClick">
|
|
|
|
|
|
<el-tab-pane label="规则配置" name="ruleConfig"></el-tab-pane>
|
|
|
|
|
|
<el-tab-pane label="提示词配置" name="promptConfig"></el-tab-pane>
|
|
|
|
|
|
<el-tab-pane label="规则验证" name="ruleValidation"></el-tab-pane>
|
|
|
|
|
|
</el-tabs>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 规则配置内容 -->
|
|
|
|
|
|
<div v-if="currentTab === 'ruleConfig'">
|
|
|
|
|
|
<el-form ref="ruleForm" :model="ruleForm" label-width="100px" class="rule-sets">
|
|
|
|
|
|
<!-- 添加规则按钮 -->
|
|
|
|
|
|
<div class="add-rule-container">
|
|
|
|
|
|
<el-button
|
2025-12-05 09:12:28 +08:00
|
|
|
|
:disabled="!selectedLabelItemId ||
|
|
|
|
|
|
(currentTab === 'ruleConfig' && (ruleSets.length === 0 || contentSources.length === 0)) ||
|
|
|
|
|
|
(currentTab === 'promptConfig' && !promptWord.trim())"
|
2025-11-28 14:27:39 +08:00
|
|
|
|
type="primary"
|
|
|
|
|
|
icon="el-icon-plus"
|
|
|
|
|
|
@click="handleAddRuleSet"
|
|
|
|
|
|
>
|
|
|
|
|
|
添加规则
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
2025-11-26 18:25:40 +08:00
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<!-- 规则集列表 -->
|
|
|
|
|
|
<div v-for="(ruleSet, index) in ruleSets" :key="index" class="rule-set-item">
|
|
|
|
|
|
<div class="rule-set-header">
|
|
|
|
|
|
<span class="rule-set-index">规则 {{ index + 1 }}</span>
|
|
|
|
|
|
<div class="rule-set-actions">
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
icon="el-icon-copy"
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
size="mini"
|
|
|
|
|
|
@click="handleCopyRuleSet(index)"
|
|
|
|
|
|
>复制</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
size="mini"
|
|
|
|
|
|
type="danger"
|
|
|
|
|
|
@click="handleDeleteRuleSet(index)"
|
|
|
|
|
|
>删除</el-button>
|
|
|
|
|
|
</div>
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<div class="rule-set-content">
|
|
|
|
|
|
<!-- 内容来源单选 -->
|
|
|
|
|
|
<el-form-item label="内容来源">
|
|
|
|
|
|
<el-radio-group
|
|
|
|
|
|
v-model="ruleSet.selectedCompositionId"
|
|
|
|
|
|
class="content-source-radios"
|
2025-11-26 18:25:40 +08:00
|
|
|
|
>
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<el-radio
|
|
|
|
|
|
v-for="source in contentSources"
|
|
|
|
|
|
:key="source.compositionId"
|
|
|
|
|
|
:label="source.compositionId"
|
2025-11-26 18:25:40 +08:00
|
|
|
|
>
|
2025-11-28 14:27:39 +08:00
|
|
|
|
{{ source.compositionName }}
|
|
|
|
|
|
</el-radio>
|
|
|
|
|
|
</el-radio-group>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 定位查询规则 -->
|
|
|
|
|
|
<div class="position-rules">
|
|
|
|
|
|
<el-form-item label="定位规则查询" class="position-rule-label">
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</el-form-item>
|
2025-11-28 14:27:39 +08:00
|
|
|
|
<div v-for="(positionRule, posIndex) in ruleSet.positionRules" :key="posIndex" class="position-rule-item">
|
|
|
|
|
|
<el-form-item>
|
|
|
|
|
|
<!-- 规则类型选择下拉框 -->
|
|
|
|
|
|
<el-select
|
|
|
|
|
|
v-model="positionRule.ruleSetType"
|
|
|
|
|
|
@change="handleRuleTypeChange(positionRule, posIndex, index)"
|
|
|
|
|
|
placeholder="请选择规则类型"
|
|
|
|
|
|
style="width: 280px;"
|
|
|
|
|
|
>
|
|
|
|
|
|
<el-option
|
|
|
|
|
|
v-for="option in ruleSetTypeOptions"
|
|
|
|
|
|
:key="option.value"
|
|
|
|
|
|
:label="option.label"
|
|
|
|
|
|
:value="option.value"
|
|
|
|
|
|
></el-option>
|
|
|
|
|
|
</el-select>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 规则类型对应的字段 -->
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'headSpecifyLength'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedWordCount"
|
|
|
|
|
|
placeholder="指定字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'docToSpecifyText'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedText"
|
|
|
|
|
|
placeholder="指定文字"
|
|
|
|
|
|
style="width: 200px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'tailSpecifyLength'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedWordCount"
|
|
|
|
|
|
placeholder="指定字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'specifyTextToEnd'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedText"
|
|
|
|
|
|
placeholder="指定文字"
|
|
|
|
|
|
style="width: 200px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'keywordAround'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.beforeCharactersNum"
|
|
|
|
|
|
placeholder="前面字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 120px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedKeywords"
|
|
|
|
|
|
placeholder="指定关键词"
|
|
|
|
|
|
style="width: 180px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.afterCharactersNum"
|
|
|
|
|
|
placeholder="后面字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 120px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'specifyTextToLength'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedText"
|
|
|
|
|
|
placeholder="指定文字"
|
|
|
|
|
|
style="width: 200px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedWordCountLength"
|
|
|
|
|
|
placeholder="指定字数长度"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'specifyTextEndToLength'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.beforeSpecifiedCharactersNum"
|
|
|
|
|
|
placeholder="指定文字前方字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 180px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.specifiedText"
|
|
|
|
|
|
placeholder="指定文字"
|
|
|
|
|
|
style="width: 200px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div class="rule-fields" v-if="positionRule.ruleSetType === 'headTailRange'">
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.firstText"
|
|
|
|
|
|
placeholder="首部文字"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.shouldIncludeCharactersNum"
|
|
|
|
|
|
placeholder="需要包含的字数"
|
|
|
|
|
|
type="number"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="positionRule.endText"
|
|
|
|
|
|
placeholder="尾部文字"
|
|
|
|
|
|
style="width: 150px; margin-left: 10px;"
|
|
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
icon="el-icon-minus"
|
|
|
|
|
|
size="mini"
|
|
|
|
|
|
type="danger"
|
|
|
|
|
|
@click="handleRemovePositionRule(index, posIndex)"
|
|
|
|
|
|
style="margin-left: 10px;"
|
|
|
|
|
|
></el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
icon="el-icon-plus"
|
|
|
|
|
|
size="mini"
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleAddPositionRule(index)"
|
|
|
|
|
|
></el-button>
|
|
|
|
|
|
</el-form-item>
|
|
|
|
|
|
</div>
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2025-11-28 14:27:39 +08:00
|
|
|
|
</el-form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 提示词配置内容 -->
|
|
|
|
|
|
<div v-if="currentTab === 'promptConfig'">
|
|
|
|
|
|
<div class="button-group">
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleLabelIdClick"
|
|
|
|
|
|
class="info-button"
|
|
|
|
|
|
>
|
|
|
|
|
|
标的编号
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleLabelNameClick"
|
|
|
|
|
|
class="info-button"
|
|
|
|
|
|
>
|
|
|
|
|
|
标的名称
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleSegmentIdClick"
|
|
|
|
|
|
class="info-button"
|
|
|
|
|
|
>
|
|
|
|
|
|
标段编号
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleSegmentNameClick"
|
|
|
|
|
|
class="info-button"
|
|
|
|
|
|
>
|
|
|
|
|
|
标段名称
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
<el-button
|
|
|
|
|
|
type="primary"
|
|
|
|
|
|
@click="handleExtractedContentClick"
|
|
|
|
|
|
class="info-button"
|
|
|
|
|
|
>
|
|
|
|
|
|
规则提取内容
|
|
|
|
|
|
</el-button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<!-- 仅保留一个大文本框,用户输入所有内容(包括任务说明、字段说明等) -->
|
|
|
|
|
|
<el-input
|
|
|
|
|
|
v-model="promptWord"
|
|
|
|
|
|
type="textarea"
|
|
|
|
|
|
rows="15"
|
|
|
|
|
|
placeholder="请输入提示词内容"
|
2025-12-05 09:12:28 +08:00
|
|
|
|
style="height: 100%;"
|
2025-11-28 14:27:39 +08:00
|
|
|
|
></el-input>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 规则验证内容(占位) -->
|
|
|
|
|
|
<div v-if="currentTab === 'ruleValidation'">
|
|
|
|
|
|
<div class="validation-placeholder">
|
|
|
|
|
|
规则验证功能待实现
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</div>
|
2025-11-28 14:27:39 +08:00
|
|
|
|
</div>
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</el-col>
|
|
|
|
|
|
</el-row>
|
|
|
|
|
|
</el-card>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
import { columnsRuleList } from '../config'
|
|
|
|
|
|
import {
|
|
|
|
|
|
listAnalysisLabelItem,
|
|
|
|
|
|
} from '@/api/template/analysisLabelItem/analysisLabelItem'
|
|
|
|
|
|
import {
|
|
|
|
|
|
listAnalysisRuleSet,
|
|
|
|
|
|
delAnalysisRuleSet,
|
2025-11-28 14:27:39 +08:00
|
|
|
|
addAnalysisRuleSet,
|
|
|
|
|
|
updateAnalysisRuleSet
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} from '@/api/template/analysisRuleSet/analysisRuleSet'
|
|
|
|
|
|
import { getTemplateInfoDetail } from '@/api/template/templateInfo/templateInfo'
|
|
|
|
|
|
import { encryptWithSM4, decryptWithSM4 } from '@/utils/sm'
|
|
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
|
name: 'AnalysisRuleSet',
|
|
|
|
|
|
components: {
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
data() {
|
|
|
|
|
|
return {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
promptWord: '',
|
|
|
|
|
|
deletedSubRuleIds: [], // 记录被删除的子规则ID
|
|
|
|
|
|
deletedPositionIds: [], // 记录被删除的定位规则ID
|
2025-11-26 18:25:40 +08:00
|
|
|
|
ruleForm: {},
|
|
|
|
|
|
columnsRuleList,
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 标签页状态
|
|
|
|
|
|
currentTab: 'ruleConfig', // 默认显示规则配置
|
|
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
// 树状图配置
|
|
|
|
|
|
treeData: [],
|
|
|
|
|
|
treeProps: {
|
|
|
|
|
|
label: 'analysisName',
|
|
|
|
|
|
children: 'children'
|
|
|
|
|
|
},
|
|
|
|
|
|
treeSearchKey: '',
|
2025-11-28 14:27:39 +08:00
|
|
|
|
labelItemMap: new Map(),
|
2025-11-26 18:25:40 +08:00
|
|
|
|
|
|
|
|
|
|
// 表格传递参数
|
|
|
|
|
|
tableSendParams: {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
templateId: '',
|
|
|
|
|
|
analysisLabelItemId: ''
|
2025-11-26 18:25:40 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 路由参数
|
|
|
|
|
|
templateId: '',
|
|
|
|
|
|
analysisLabelId: '',
|
2025-11-28 14:27:39 +08:00
|
|
|
|
templateName: '',
|
|
|
|
|
|
contentSources: [],
|
2025-11-26 18:25:40 +08:00
|
|
|
|
|
|
|
|
|
|
// 选中的标签项信息
|
|
|
|
|
|
selectedLabelItemId: '',
|
|
|
|
|
|
selectedLabelLevel: 0,
|
|
|
|
|
|
analysisCode: '',
|
|
|
|
|
|
analysisLevel: '',
|
|
|
|
|
|
analysisName: '',
|
|
|
|
|
|
analysisSort: '',
|
|
|
|
|
|
parentId: '',
|
|
|
|
|
|
|
|
|
|
|
|
// 规则集数据
|
|
|
|
|
|
ruleSets: [],
|
2025-11-28 14:27:39 +08:00
|
|
|
|
ruleSetTypeOptions: [],
|
|
|
|
|
|
|
|
|
|
|
|
// 提示词配置数据
|
|
|
|
|
|
promptForm: {
|
|
|
|
|
|
taskDescription: '', // 任务说明(用户填写)
|
|
|
|
|
|
fieldDescription: '', // 字段说明(用户填写)
|
|
|
|
|
|
inputContent: '', // 输入内容(用户填写)
|
|
|
|
|
|
outputFormat: '' // 输出格式(用户填写)
|
|
|
|
|
|
},
|
|
|
|
|
|
// 提示词表格数据
|
|
|
|
|
|
promptTableData: [
|
|
|
|
|
|
{
|
|
|
|
|
|
labelId: '',
|
|
|
|
|
|
labelName: '',
|
|
|
|
|
|
segmentId: '',
|
|
|
|
|
|
segmentName: '',
|
|
|
|
|
|
extractedContent: ''
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
2025-11-26 18:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
created() {
|
|
|
|
|
|
this.loadRuleSetTypeDict()
|
|
|
|
|
|
this.templateId = decryptWithSM4(this.$route.query.templateId) || ''
|
|
|
|
|
|
this.analysisLabelId = decryptWithSM4(this.$route.query.analysisLabelId) || ''
|
|
|
|
|
|
this.tableSendParams.templateId = this.templateId
|
|
|
|
|
|
this.loadTemplateInfo()
|
|
|
|
|
|
this.loadTreeData()
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
methods: {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 加载规则类型字典表数据
|
2025-11-26 18:25:40 +08:00
|
|
|
|
loadRuleSetTypeDict() {
|
|
|
|
|
|
this.getDicts('rule_set_type').then(response => {
|
|
|
|
|
|
this.ruleSetTypeOptions = response.data.map(item => ({
|
|
|
|
|
|
label: item.dictLabel,
|
|
|
|
|
|
value: item.dictValue
|
|
|
|
|
|
}))
|
|
|
|
|
|
}).catch(error => {
|
|
|
|
|
|
console.error('加载查询规则类型字典失败:', error)
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 返回上一页
|
2025-11-26 18:25:40 +08:00
|
|
|
|
handleBack() {
|
|
|
|
|
|
const obj = { path: "/templateInfo/index" };
|
|
|
|
|
|
this.$tab.closeOpenPage(obj);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 加载模板信息
|
2025-11-26 18:25:40 +08:00
|
|
|
|
loadTemplateInfo() {
|
|
|
|
|
|
if (this.templateId) {
|
|
|
|
|
|
getTemplateInfoDetail({templateId: this.templateId})
|
|
|
|
|
|
.then(res => {
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
this.templateName = res.data.templateName || '';
|
|
|
|
|
|
const compositionList = res.data.compositionList || [];
|
|
|
|
|
|
|
2025-12-05 09:12:28 +08:00
|
|
|
|
console.log('detail',res.data)
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
// 去重处理
|
|
|
|
|
|
const uniqueSources = [];
|
|
|
|
|
|
const seenIds = new Set();
|
|
|
|
|
|
compositionList.forEach(source => {
|
|
|
|
|
|
if (source.compositionId && !seenIds.has(source.compositionId)) {
|
|
|
|
|
|
seenIds.add(source.compositionId);
|
|
|
|
|
|
uniqueSources.push({
|
|
|
|
|
|
compositionId: source.compositionId,
|
|
|
|
|
|
compositionName: source.fileName
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
this.contentSources = uniqueSources;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.selectedLabelItemId) {
|
|
|
|
|
|
this.loadRuleSets();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(err => {
|
|
|
|
|
|
console.error('加载模板信息失败:', err);
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 加载树形结构数据
|
2025-11-26 18:25:40 +08:00
|
|
|
|
loadTreeData() {
|
2025-11-29 17:54:26 +08:00
|
|
|
|
const allItems = []; // 用于存储所有页的数据
|
2025-12-05 09:12:28 +08:00
|
|
|
|
const pageSize = 1000; // 每页数量,根据后端接口定义调整
|
2025-11-29 17:54:26 +08:00
|
|
|
|
let currentPage = 1; // 当前页码
|
|
|
|
|
|
|
|
|
|
|
|
// 定义一个递归函数来获取每一页的数据
|
|
|
|
|
|
const fetchPage = () => {
|
|
|
|
|
|
listAnalysisLabelItem({
|
|
|
|
|
|
analysisId: this.analysisLabelId,
|
|
|
|
|
|
pageNum: currentPage,
|
|
|
|
|
|
pageSize: pageSize
|
|
|
|
|
|
}).then(res => {
|
|
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
const { rows, total } = res;
|
|
|
|
|
|
|
|
|
|
|
|
// 将当前页的数据追加到总数组
|
|
|
|
|
|
if (rows && rows.length > 0) {
|
|
|
|
|
|
allItems.push(...rows);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算总页数
|
|
|
|
|
|
const totalPages = Math.ceil(total / pageSize);
|
|
|
|
|
|
|
|
|
|
|
|
// 如果当前页不是最后一页,则继续获取下一页
|
|
|
|
|
|
if (currentPage < totalPages) {
|
|
|
|
|
|
currentPage++;
|
|
|
|
|
|
fetchPage(); // 递归调用,获取下一页
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 所有页都获取完毕,构建树形结构
|
|
|
|
|
|
console.log('所有数据获取完毕,共', allItems.length, '条');
|
|
|
|
|
|
this.treeData = this.buildTree(allItems);
|
|
|
|
|
|
this.buildLabelItemMap(allItems); // 构建映射表
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// 出错处理
|
|
|
|
|
|
this.$modal.msgError('加载标签项数据失败');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
// 开始执行首次获取
|
|
|
|
|
|
fetchPage();
|
2025-11-26 18:25:40 +08:00
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 构建树形结构
|
2025-11-26 18:25:40 +08:00
|
|
|
|
buildTree(list) {
|
|
|
|
|
|
const tree = []
|
|
|
|
|
|
const map = {}
|
|
|
|
|
|
list.forEach(item => {
|
|
|
|
|
|
map[item.analysisLabelItemId] = { ...item, children: [] }
|
|
|
|
|
|
})
|
|
|
|
|
|
list.forEach(item => {
|
|
|
|
|
|
if (item.parentId && map[item.parentId]) {
|
|
|
|
|
|
map[item.parentId].children.push(map[item.analysisLabelItemId])
|
|
|
|
|
|
} else {
|
|
|
|
|
|
tree.push(map[item.analysisLabelItemId])
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
return tree
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 构建标签项ID与名称映射表
|
2025-11-26 18:25:40 +08:00
|
|
|
|
buildLabelItemMap(list) {
|
|
|
|
|
|
this.labelItemMap.clear()
|
|
|
|
|
|
list.forEach(item => {
|
|
|
|
|
|
this.labelItemMap.set(String(item.analysisLabelItemId), {
|
|
|
|
|
|
name: item.analysisName,
|
|
|
|
|
|
level: item.analysisLevel
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 树形节点过滤
|
2025-11-26 18:25:40 +08:00
|
|
|
|
filterTreeNode(value, data) {
|
|
|
|
|
|
if (!value) return true
|
|
|
|
|
|
return data.analysisName.includes(value) ||
|
|
|
|
|
|
(data.analysisCode && data.analysisCode.includes(value))
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 树形节点点击事件
|
2025-11-26 18:25:40 +08:00
|
|
|
|
handleTreeNodeClick(data) {
|
|
|
|
|
|
if (data.analysisLevel === 3) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.promptWord = data.promptWord
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.analysisLevel = data.analysisLevel
|
|
|
|
|
|
this.analysisName = data.analysisName
|
|
|
|
|
|
this.analysisCode = data.analysisCode
|
|
|
|
|
|
this.analysisSort = data.analysisSort
|
|
|
|
|
|
this.parentId = data.parentId
|
|
|
|
|
|
this.selectedLabelItemId = data.analysisLabelItemId
|
|
|
|
|
|
this.selectedLabelLevel = data.analysisLevel
|
|
|
|
|
|
this.tableSendParams.analysisLabelItemId = data.analysisLabelItemId
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.loadRuleSets()
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
this.$modal.msgInfo('请选择三级标签项进行操作')
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 树形节点切换事件
|
2025-11-26 18:25:40 +08:00
|
|
|
|
handleTreeNodeChange(currentNode) {
|
|
|
|
|
|
if (currentNode && currentNode.analysisLevel === 3) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.promptWord = data.promptWord
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.selectedLabelItemId = currentNode.analysisLabelItemId
|
|
|
|
|
|
this.selectedLabelLevel = currentNode.analysisLevel
|
|
|
|
|
|
this.tableSendParams.analysisLabelItemId = currentNode.analysisLabelItemId
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.loadRuleSets()
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} else if (currentNode) {
|
|
|
|
|
|
this.$modal.msgInfo('请选择三级标签项进行操作')
|
|
|
|
|
|
this.$refs.labelItemTree.setCurrentKey(null)
|
|
|
|
|
|
this.selectedLabelItemId = ''
|
|
|
|
|
|
this.selectedLabelLevel = 0
|
|
|
|
|
|
this.tableSendParams.analysisLabelItemId = ''
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.promptWord = ''
|
|
|
|
|
|
this.ruleSets = []
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
this.selectedLabelItemId = ''
|
|
|
|
|
|
this.selectedLabelLevel = 0
|
|
|
|
|
|
this.tableSendParams.analysisLabelItemId = ''
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.promptWord = ''
|
|
|
|
|
|
this.ruleSets = []
|
2025-11-26 18:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加载规则集
|
|
|
|
|
|
*/
|
|
|
|
|
|
loadRuleSets() {
|
|
|
|
|
|
if (this.selectedLabelItemId && this.templateId) {
|
|
|
|
|
|
listAnalysisRuleSet({
|
|
|
|
|
|
templateId: this.templateId,
|
|
|
|
|
|
analysisLabelItemId: this.selectedLabelItemId
|
|
|
|
|
|
}).then(res => {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
console.log('规则集数据:', res)
|
2025-11-26 18:25:40 +08:00
|
|
|
|
if (res.code === 200) {
|
|
|
|
|
|
this.ruleSets = [];
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.promptWord = res.rows.length > 0 ? (res.rows[0].promptWord || '') : '';
|
2025-11-26 18:25:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
res.rows.forEach(ruleSet => {
|
|
|
|
|
|
(ruleSet.subRules || []).forEach(subRule => {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
let sourceObj = { compositionId: '', compositionName: '' };
|
2025-11-28 14:27:39 +08:00
|
|
|
|
if (subRule.compositionId) {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
const foundSource = this.contentSources.find(
|
2025-11-28 14:27:39 +08:00
|
|
|
|
s => s.compositionId === subRule.compositionId
|
2025-11-26 18:25:40 +08:00
|
|
|
|
);
|
2025-11-28 14:27:39 +08:00
|
|
|
|
sourceObj = foundSource ? foundSource : {
|
|
|
|
|
|
compositionId: subRule.compositionId,
|
|
|
|
|
|
compositionName: subRule.compositionName || '未知来源'
|
|
|
|
|
|
};
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} else if (this.contentSources.length > 0) {
|
|
|
|
|
|
sourceObj = this.contentSources[0];
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
const subRulePositions = (ruleSet.positions || []).filter(
|
|
|
|
|
|
pos => pos.subRuleId === subRule.subRuleId
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
const ruleSetItem = {
|
|
|
|
|
|
ruleSetId: ruleSet.ruleSetId,
|
|
|
|
|
|
subRuleId: subRule.subRuleId,
|
|
|
|
|
|
ruleResourceId: subRule.ruleResourceId,
|
2025-11-26 18:25:40 +08:00
|
|
|
|
contentSource: sourceObj,
|
2025-11-28 14:27:39 +08:00
|
|
|
|
selectedCompositionId: subRule.compositionId,
|
|
|
|
|
|
positionRules: subRulePositions.length > 0
|
|
|
|
|
|
? subRulePositions.map(pos => ({
|
|
|
|
|
|
...pos,
|
|
|
|
|
|
subRuleIndex: this.ruleSets.length
|
|
|
|
|
|
}))
|
2025-11-26 18:25:40 +08:00
|
|
|
|
: [this.createEmptyPositionRule()]
|
2025-11-28 14:27:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
this.ruleSets.push(ruleSetItem);
|
2025-11-26 18:25:40 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if (this.ruleSets.length === 0 && this.contentSources.length > 0) {
|
|
|
|
|
|
this.handleAddRuleSet();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 添加规则集
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleAddRuleSet() {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 初始化内容来源
|
2025-11-26 18:25:40 +08:00
|
|
|
|
const defaultSource = this.contentSources.length > 0
|
|
|
|
|
|
? {
|
|
|
|
|
|
compositionId: this.contentSources[0].compositionId,
|
|
|
|
|
|
compositionName: this.contentSources[0].compositionName
|
|
|
|
|
|
}
|
|
|
|
|
|
: { compositionId: '', compositionName: '' };
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 新增规则集
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.ruleSets.push({
|
|
|
|
|
|
contentSource: defaultSource,
|
2025-11-28 14:27:39 +08:00
|
|
|
|
selectedCompositionId: defaultSource.compositionId,
|
2025-11-26 18:25:40 +08:00
|
|
|
|
positionRules: [this.createEmptyPositionRule()]
|
|
|
|
|
|
});
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 复制规则集
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleCopyRuleSet(index) {
|
|
|
|
|
|
const copiedRuleSet = JSON.parse(JSON.stringify(this.ruleSets[index]));
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 删除ID信息,由后端重新生成
|
|
|
|
|
|
delete copiedRuleSet.subRuleId;
|
2025-11-26 18:25:40 +08:00
|
|
|
|
delete copiedRuleSet.ruleSetId;
|
2025-11-28 14:27:39 +08:00
|
|
|
|
delete copiedRuleSet.ruleResourceId;
|
|
|
|
|
|
|
|
|
|
|
|
copiedRuleSet.selectedCompositionId = copiedRuleSet.contentSource.compositionId;
|
|
|
|
|
|
|
|
|
|
|
|
copiedRuleSet.positionRules.forEach(posRule => {
|
|
|
|
|
|
delete posRule.queryRuleId;
|
|
|
|
|
|
posRule.subRuleIndex = this.ruleSets.length;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.ruleSets.splice(index + 1, 0, copiedRuleSet);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 删除规则集
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleDeleteRuleSet(index) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
const deletedRuleSet = this.ruleSets[index];
|
|
|
|
|
|
// 如果是已有子规则(有subRuleId),添加到删除列表
|
|
|
|
|
|
if (deletedRuleSet.subRuleId) {
|
|
|
|
|
|
this.deletedSubRuleIds.push(deletedRuleSet.subRuleId);
|
|
|
|
|
|
}
|
|
|
|
|
|
// 收集该子规则下所有定位规则的ID
|
|
|
|
|
|
if (deletedRuleSet.positionRules && deletedRuleSet.positionRules.length) {
|
|
|
|
|
|
deletedRuleSet.positionRules.forEach(pos => {
|
|
|
|
|
|
if (pos.queryRuleId) { // 仅收集已有定位规则
|
|
|
|
|
|
this.deletedPositionIds.push(pos.queryRuleId);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.ruleSets.splice(index, 1);
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 添加定位规则
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleAddPositionRule(ruleSetIndex) {
|
|
|
|
|
|
this.ruleSets[ruleSetIndex].positionRules.push(this.createEmptyPositionRule());
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 移除定位规则
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleRemovePositionRule(ruleSetIndex, posIndex) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
const positionRule = this.ruleSets[ruleSetIndex].positionRules[posIndex];
|
|
|
|
|
|
// 如果是已有定位规则(有queryRuleId),添加到删除列表
|
|
|
|
|
|
if (positionRule.queryRuleId) {
|
|
|
|
|
|
this.deletedPositionIds.push(positionRule.queryRuleId);
|
|
|
|
|
|
}
|
2025-11-26 18:25:40 +08:00
|
|
|
|
if (this.ruleSets[ruleSetIndex].positionRules.length > 1) {
|
|
|
|
|
|
this.ruleSets[ruleSetIndex].positionRules.splice(posIndex, 1);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
this.$message.warning('至少保留一个定位规则');
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 规则类型改变事件
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleRuleTypeChange(positionRule, posIndex, ruleSetIndex) {
|
|
|
|
|
|
const allFields = [
|
|
|
|
|
|
'specifiedWordCount', 'specifiedText', 'specifiedKeywords',
|
|
|
|
|
|
'beforeCharactersNum', 'afterCharactersNum', 'specifiedWordCountLength',
|
|
|
|
|
|
'beforeSpecifiedCharactersNum', 'firstText', 'shouldIncludeCharactersNum', 'endText'
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
allFields.forEach(field => {
|
|
|
|
|
|
if (positionRule.hasOwnProperty(field)) {
|
|
|
|
|
|
this.$set(positionRule, field, '');
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const ruleType = positionRule.ruleSetType;
|
|
|
|
|
|
switch (ruleType) {
|
|
|
|
|
|
case 'headSpecifyLength':
|
|
|
|
|
|
case 'tailSpecifyLength':
|
|
|
|
|
|
this.$set(positionRule, 'specifiedWordCount', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'docToSpecifyText':
|
|
|
|
|
|
case 'specifyTextToEnd':
|
|
|
|
|
|
this.$set(positionRule, 'specifiedText', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'keywordAround':
|
|
|
|
|
|
this.$set(positionRule, 'beforeCharactersNum', '');
|
|
|
|
|
|
this.$set(positionRule, 'specifiedKeywords', '');
|
|
|
|
|
|
this.$set(positionRule, 'afterCharactersNum', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'specifyTextToLength':
|
|
|
|
|
|
this.$set(positionRule, 'specifiedText', '');
|
|
|
|
|
|
this.$set(positionRule, 'specifiedWordCountLength', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'specifyTextEndToLength':
|
|
|
|
|
|
this.$set(positionRule, 'beforeSpecifiedCharactersNum', '');
|
|
|
|
|
|
this.$set(positionRule, 'specifiedText', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
case 'headTailRange':
|
|
|
|
|
|
this.$set(positionRule, 'firstText', '');
|
|
|
|
|
|
this.$set(positionRule, 'shouldIncludeCharactersNum', '');
|
|
|
|
|
|
this.$set(positionRule, 'endText', '');
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 创建空的定位规则
|
|
|
|
|
|
*/
|
|
|
|
|
|
createEmptyPositionRule() {
|
|
|
|
|
|
return {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
subRuleIndex: 0,
|
|
|
|
|
|
ruleSetType: '',
|
2025-11-26 18:25:40 +08:00
|
|
|
|
};
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2025-11-28 14:27:39 +08:00
|
|
|
|
* 标签切换事件处理
|
|
|
|
|
|
*/
|
|
|
|
|
|
handleTabClick(tab) {
|
|
|
|
|
|
this.currentTab = tab.name;
|
|
|
|
|
|
// 可以在这里添加切换标签时的额外逻辑
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 整合提示词内容为一个字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
getPromptWord() {
|
|
|
|
|
|
// 将各个提示词部分整合为一个字符串
|
|
|
|
|
|
let promptParts = [];
|
|
|
|
|
|
|
|
|
|
|
|
if (this.promptForm.taskDescription) {
|
|
|
|
|
|
promptParts.push(`# 任务说明\n${this.promptForm.taskDescription}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.promptForm.fieldDescription) {
|
|
|
|
|
|
promptParts.push(`# 字段说明\n${this.promptForm.fieldDescription}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.promptForm.inputContent) {
|
|
|
|
|
|
promptParts.push(`# 输入内容\n${this.promptForm.inputContent}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.promptForm.outputFormat) {
|
|
|
|
|
|
promptParts.push(`# 输出格式\n${this.promptForm.outputFormat}`);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return promptParts.join('\n\n');
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 验证提示词配置
|
|
|
|
|
|
*/
|
|
|
|
|
|
validatePrompt() {
|
|
|
|
|
|
// 直接验证当前使用的 promptWord 变量
|
|
|
|
|
|
if (!this.promptWord.trim()) {
|
|
|
|
|
|
this.$message.warning('请填写提示词内容');
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 保存规则(包括提示词)
|
2025-11-26 18:25:40 +08:00
|
|
|
|
*/
|
|
|
|
|
|
handleSaveRules() {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 根据当前标签页进行不同验证
|
|
|
|
|
|
if (this.currentTab === 'ruleConfig' && !this.validateRules()) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (this.currentTab === 'promptConfig' && !this.validatePrompt()) {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 准备提交的数据
|
2025-11-26 18:25:40 +08:00
|
|
|
|
const submitData = {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
deletedSubRuleIds: this.deletedSubRuleIds,
|
|
|
|
|
|
deletedPositionIds: this.deletedPositionIds,
|
|
|
|
|
|
ruleSetId: this.ruleSets.length > 0 ? this.ruleSets[0].ruleSetId : null,
|
2025-11-26 18:25:40 +08:00
|
|
|
|
analysisLevel: this.analysisLevel,
|
|
|
|
|
|
analysisName: this.analysisName,
|
|
|
|
|
|
analysisCode: this.analysisCode,
|
|
|
|
|
|
analysisSort: this.analysisSort,
|
|
|
|
|
|
parentId: this.parentId,
|
|
|
|
|
|
templateId: this.templateId,
|
|
|
|
|
|
analysisLabelItemId: this.selectedLabelItemId,
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 子规则信息
|
|
|
|
|
|
subRules: this.ruleSets.map((ruleSet) => ({
|
|
|
|
|
|
subRuleId: ruleSet.subRuleId,
|
|
|
|
|
|
compositionId: ruleSet.selectedCompositionId,
|
|
|
|
|
|
ruleResourceId: ruleSet.ruleResourceId
|
2025-11-26 18:25:40 +08:00
|
|
|
|
})),
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
positions: [],
|
|
|
|
|
|
|
|
|
|
|
|
// 提示词内容,整合为promptWord字段
|
|
|
|
|
|
promptWord: this.promptWord.trim()
|
2025-11-26 18:25:40 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.deletedSubRuleIds = [];
|
|
|
|
|
|
this.deletedPositionIds = [];
|
|
|
|
|
|
|
|
|
|
|
|
// 处理定位规则
|
|
|
|
|
|
this.ruleSets.forEach((ruleSet, ruleSetIndex) => {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
ruleSet.positionRules.forEach(posRule => {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
const positionData = {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
queryRuleId: posRule.queryRuleId,
|
|
|
|
|
|
ruleSetType: posRule.ruleSetType,
|
|
|
|
|
|
specifiedWordCount: posRule.specifiedWordCount,
|
|
|
|
|
|
specifiedText: posRule.specifiedText,
|
|
|
|
|
|
specifiedKeywords: posRule.specifiedKeywords,
|
|
|
|
|
|
beforeCharactersNum: posRule.beforeCharactersNum,
|
|
|
|
|
|
afterCharactersNum: posRule.afterCharactersNum,
|
|
|
|
|
|
specifiedWordCountLength: posRule.specifiedWordCountLength,
|
|
|
|
|
|
beforeSpecifiedCharactersNum: posRule.beforeSpecifiedCharactersNum,
|
|
|
|
|
|
firstText: posRule.firstText,
|
2025-11-28 14:27:39 +08:00
|
|
|
|
subRuleIndex: ruleSetIndex,
|
2025-11-26 18:25:40 +08:00
|
|
|
|
shouldIncludeCharactersNum: posRule.shouldIncludeCharactersNum,
|
|
|
|
|
|
endText: posRule.endText
|
2025-11-28 14:27:39 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (ruleSet.subRuleId) {
|
|
|
|
|
|
positionData.subRuleId = ruleSet.subRuleId;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
submitData.positions.push(positionData);
|
2025-11-26 18:25:40 +08:00
|
|
|
|
});
|
|
|
|
|
|
});
|
2025-11-28 14:27:39 +08:00
|
|
|
|
console.log('提交数据:', submitData)
|
|
|
|
|
|
|
|
|
|
|
|
// 调用接口:区分新增和更新
|
|
|
|
|
|
const isUpdate = this.ruleSets.some(rule => rule.ruleSetId);
|
|
|
|
|
|
const apiMethod = isUpdate ? updateAnalysisRuleSet : addAnalysisRuleSet;
|
2025-11-26 18:25:40 +08:00
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
apiMethod(submitData)
|
2025-11-26 18:25:40 +08:00
|
|
|
|
.then(res => {
|
|
|
|
|
|
if (res.code === 200) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.$message.success(isUpdate ? '规则更新成功' : '规则保存成功');
|
|
|
|
|
|
this.loadRuleSets(); // 重新加载以获取最新ID
|
2025-11-26 18:25:40 +08:00
|
|
|
|
} else {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.$message.error(res.msg || (isUpdate ? '规则更新失败' : '规则保存失败'));
|
2025-11-26 18:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
.catch(err => {
|
|
|
|
|
|
console.error('保存规则失败:', err);
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.$message.error('操作失败,请重试');
|
2025-11-26 18:25:40 +08:00
|
|
|
|
});
|
|
|
|
|
|
},
|
2025-11-28 14:27:39 +08:00
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 验证规则
|
|
|
|
|
|
*/
|
|
|
|
|
|
validateRules() {
|
|
|
|
|
|
for (let i = 0; i < this.ruleSets.length; i++) {
|
|
|
|
|
|
const ruleSet = this.ruleSets[i];
|
|
|
|
|
|
|
|
|
|
|
|
// 验证内容来源
|
2025-11-28 14:27:39 +08:00
|
|
|
|
if (!ruleSet.selectedCompositionId) {
|
2025-11-26 18:25:40 +08:00
|
|
|
|
this.$message.warning(`规则 ${i + 1}:请选择内容来源`);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 验证每个定位规则
|
|
|
|
|
|
for (let j = 0; j < ruleSet.positionRules.length; j++) {
|
|
|
|
|
|
const posRule = ruleSet.positionRules[j];
|
|
|
|
|
|
|
|
|
|
|
|
if (!posRule.ruleSetType) {
|
|
|
|
|
|
this.$message.warning(`规则 ${i + 1},定位规则 ${j + 1}:请选择规则类型`);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (posRule.ruleSetType === 'headSpecifyLength' && !posRule.specifiedWordCount) {
|
|
|
|
|
|
this.$message.warning(`规则 ${i + 1},定位规则 ${j + 1}:请输入指定字数`);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (posRule.ruleSetType === 'docToSpecifyText' && !posRule.specifiedText) {
|
|
|
|
|
|
this.$message.warning(`规则 ${i + 1},定位规则 ${j + 1}:请输入指定文字`);
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取字典标签
|
|
|
|
|
|
*/
|
|
|
|
|
|
getDictLabel(dictType, dictValue) {
|
|
|
|
|
|
const dictItem = this.dictCache[dictType]?.find(item => item.dictValue === dictValue)
|
|
|
|
|
|
return dictItem ? dictItem.dictLabel : dictValue
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
watch: {
|
|
|
|
|
|
// 监听树搜索关键词变化
|
|
|
|
|
|
treeSearchKey(val) {
|
|
|
|
|
|
this.$refs.labelItemTree.filter(val)
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
// 监听路由参数变化
|
|
|
|
|
|
'$route.query.analysisLabelId'(val) {
|
|
|
|
|
|
this.analysisLabelId = decryptWithSM4(val) || ''
|
|
|
|
|
|
this.loadTreeData()
|
|
|
|
|
|
},
|
|
|
|
|
|
'$route.query.templateId'(val) {
|
|
|
|
|
|
this.templateId = decryptWithSM4(val) || ''
|
|
|
|
|
|
this.tableSendParams.templateId = this.templateId
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.loadTemplateInfo()
|
2025-11-26 18:25:40 +08:00
|
|
|
|
if (this.selectedLabelItemId) {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
this.loadRuleSets()
|
2025-11-26 18:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<style scoped lang="scss">
|
2025-11-28 14:27:39 +08:00
|
|
|
|
/* 原有样式保持不变 */
|
2025-11-26 18:25:40 +08:00
|
|
|
|
.back-container {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: flex-end;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
padding: 0 20px;
|
|
|
|
|
|
|
|
|
|
|
|
.back-btn {
|
|
|
|
|
|
width: 98px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
background: #FFFFFF;
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
|
color: #409EFF;
|
|
|
|
|
|
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.save-btn {
|
|
|
|
|
|
width: 98px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(76, 76, 76, 0.2);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
box-shadow: 0px 6px 12px 0px rgba(76, 76, 76, 0.3);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.analysis-rule-container {
|
|
|
|
|
|
height: calc(100vh - 84px);
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
background: linear-gradient(180deg, #F1F6FF 20%, #E5EFFF 100%);
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.tree-container {
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #ebeef5;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
|
|
|
padding: 16px;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
.tree-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
font-weight: 600; // 增强标题权重,与表格标题一致
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
.tree-search {
|
|
|
|
|
|
margin-bottom: 16px;
|
|
|
|
|
|
::v-deep .el-input__inner {
|
|
|
|
|
|
border-color: #dcdfe6;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
&:focus {
|
2025-11-28 14:27:39 +08:00
|
|
|
|
border-color: #1f72ea; // 聚焦时边框色与表格交互元素一致
|
2025-11-26 18:25:40 +08:00
|
|
|
|
box-shadow: 0 0 0 2px rgba(31, 114, 234, 0.2);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-tree {
|
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
&::-webkit-scrollbar {
|
|
|
|
|
|
width: 6px;
|
|
|
|
|
|
height: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
&::-webkit-scrollbar-thumb {
|
|
|
|
|
|
background-color: #ddd;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
}
|
|
|
|
|
|
&::-webkit-scrollbar-track {
|
|
|
|
|
|
background-color: #f5f5f5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-tree-node__content {
|
|
|
|
|
|
height: 40px;
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background-color: #f5f7fa;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-tree-node.is-current > .el-tree-node__content {
|
|
|
|
|
|
background-color: #e6f7ff;
|
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.tree-node-content {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
width: 100%;
|
2025-11-28 14:27:39 +08:00
|
|
|
|
height: 100%; // 确保内容充满节点行高
|
|
|
|
|
|
|
2025-12-05 09:12:28 +08:00
|
|
|
|
> span:first-child {font-size: 15px !important;}
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
.tree-node-actions {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
transition: opacity 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
i {
|
|
|
|
|
|
margin-left: 8px;
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
// 9. 图标交互效果与表格操作按钮对齐
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
filter: brightness(1.2); // hover 时轻微提亮
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-icon-edit {
|
|
|
|
|
|
color: #EAA819;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.el-icon-delete {
|
|
|
|
|
|
color: #DB3E29;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:hover .tree-node-actions {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
}
|
2025-11-26 18:25:40 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 规则配置区域样式
|
|
|
|
|
|
.rule-config-container {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
height: calc(100vh - 205px);
|
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-05 09:12:28 +08:00
|
|
|
|
.rule-config-container {
|
|
|
|
|
|
/* 使用 ::v-deep 穿透 scoped 样式 */
|
|
|
|
|
|
::v-deep .el-textarea {
|
|
|
|
|
|
/* 确保 textarea 容器占满可用宽度 */
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
|
|
|
|
|
|
&__inner {
|
|
|
|
|
|
/* 1. 基础文本美化 */
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
|
|
|
|
font-size: 15px; /* slightly larger font for better readability */
|
|
|
|
|
|
line-height: 1.7; /* 增加行高,提升可读性 */
|
|
|
|
|
|
letter-spacing: 0.5px; /* 增加字间距,让文字不拥挤 */
|
|
|
|
|
|
color: #333; /* 文本颜色 */
|
|
|
|
|
|
|
|
|
|
|
|
/* 2. 容器样式美化 */
|
|
|
|
|
|
background-color: #ffffff;
|
|
|
|
|
|
border: 1px solid #e0e6ed; /* 更柔和的边框色 */
|
|
|
|
|
|
border-radius: 8px; /* 圆润的 corners */
|
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05); /* subtle outer shadow */
|
|
|
|
|
|
|
|
|
|
|
|
/* 3. 内部 Padding */
|
|
|
|
|
|
padding: 16px; /* 上下左右都有 padding */
|
|
|
|
|
|
|
|
|
|
|
|
/* 4. 交互与过渡效果 */
|
|
|
|
|
|
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* 平滑过渡 */
|
|
|
|
|
|
|
|
|
|
|
|
/* Hover 状态 */
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
border-color: #c9d2dc;
|
|
|
|
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Focus 状态 (这是最重要的交互反馈) */
|
|
|
|
|
|
&:focus {
|
|
|
|
|
|
outline: none;
|
|
|
|
|
|
border-color: #409EFF; /* 高亮边框色,与主题色一致 */
|
|
|
|
|
|
box-shadow: 0 0 0 3px rgba(64, 158, 255, 0.15); /* 聚焦发光效果 */
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* 5. 美化 Placeholder */
|
|
|
|
|
|
::v-deep .el-textarea__inner::placeholder {
|
|
|
|
|
|
color: #b4bcc2; /* 更淡的占位符颜色 */
|
|
|
|
|
|
font-style: italic; /* 斜体,增加设计感 */
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-26 18:25:40 +08:00
|
|
|
|
.template-info {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
border-bottom: 1px solid #eee;
|
|
|
|
|
|
|
|
|
|
|
|
h3 {
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
color: #1F72EA;
|
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-28 14:27:39 +08:00
|
|
|
|
// 提示词表单样式
|
|
|
|
|
|
.prompt-form {
|
|
|
|
|
|
::v-deep .el-form-item {
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-textarea__inner {
|
2025-12-05 09:12:28 +08:00
|
|
|
|
min-height: 100%;
|
2025-11-28 14:27:39 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 规则验证占位样式
|
|
|
|
|
|
.validation-placeholder {
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
padding: 50px 0;
|
|
|
|
|
|
color: #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 其他原有样式保持不变
|
2025-11-26 18:25:40 +08:00
|
|
|
|
.rule-sets {
|
|
|
|
|
|
::v-deep .el-form-item {
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-form-item__label {
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::v-deep .el-form-item__content {
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.add-rule-container {
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rule-set-item {
|
|
|
|
|
|
background: #f9f9f9;
|
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rule-set-header {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
border-bottom: 1px dashed #e0e0e0;
|
|
|
|
|
|
|
|
|
|
|
|
.rule-set-index {
|
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rule-set-actions {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
gap: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rule-set-content {
|
|
|
|
|
|
margin-top: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.content-source-radios {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 15px;
|
|
|
|
|
|
margin-top: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.position-rules {
|
|
|
|
|
|
margin-top: 15px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.position-rule-item {
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
background: #f9f9f9;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.position-rule-item ::v-deep .el-form-item__content {
|
|
|
|
|
|
margin-left: 0 !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.rule-fields {
|
|
|
|
|
|
display: inline-flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.add-position-rule {
|
|
|
|
|
|
color: #409EFF;
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.save-rule-container {
|
|
|
|
|
|
margin-top: 30px;
|
|
|
|
|
|
text-align: right;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.add-btn {
|
|
|
|
|
|
width: 121px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
background: #1F72EA;
|
|
|
|
|
|
box-shadow: 0px 4px 8px 0px rgba(51, 135, 255, 0.5);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
color: #fff;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
transition: all 0.3s;
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
|
|
|
|
|
|
&:hover {
|
|
|
|
|
|
background: #4A8BFF;
|
|
|
|
|
|
box-shadow: 0px 6px 12px 0px rgba(51, 135, 255, 0.6);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
&:disabled {
|
|
|
|
|
|
background: #a0cfff;
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
cursor: not-allowed;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.action-btn {
|
|
|
|
|
|
margin-right: 8px;
|
|
|
|
|
|
|
|
|
|
|
|
&:last-child {
|
|
|
|
|
|
margin-right: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-11-28 14:27:39 +08:00
|
|
|
|
|
|
|
|
|
|
.button-group {
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
|
gap: 10px;
|
|
|
|
|
|
padding: 10px 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.info-button {
|
|
|
|
|
|
min-width: 120px;
|
|
|
|
|
|
}
|
2025-11-26 18:25:40 +08:00
|
|
|
|
</style>
|