Files
ebiz-ai-knowledge-manage/src/views/knowledge/detail/components/split/AddRule.vue
陈昱达 013bdb74b7 refactor(dialog): 优化对话框组件的配置和交互
- 修改了多个组件的关闭对话框逻辑,设置 wrapperClosable 为 false
- 更新了多个组件的确认对话框逻辑,使用 $messageBox 替代 $confirm
- 调整了部分对话框的样式和布局
2025-05-08 14:36:34 +08:00

467 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div>
<!-- 添加预处理结果预览对话框 -->
<el-drawer
:title="
currentId
? (isPreview ? '预览' : '编辑') + '知识拆分规则'
: '新增知识拆分规则'
"
:visible.sync="dialogVisible"
size="30%"
:wrapperClosable="false"
:before-close="handleClose"
>
<div class="content">
<el-form
ref="ruleForm"
:model="form"
:rules="rules"
label-position="top"
>
<div class="section-title">基本信息</div>
<el-row
v-if="isPreview"
:gutter="20"
style="display: flex; align-items: end;"
>
<el-col
:span="isPreview ? 24 : 14"
:class="isPreview ? 'full-width-item' : ''"
>
<el-form-item
label="规则名称"
prop="ruleName"
style="width: 100%;"
>
<el-input
size="medium"
:disabled="isPreview"
v-model="form.ruleName"
placeholder="请输入规则名称"
style="width: 100%"
/>
</el-form-item>
</el-col>
</el-row>
<el-row v-else :gutter="20" style="display: flex; align-items: end;">
<el-col span="24" :class="isPreview ? 'full-width-item' : ''">
<el-form-item label="规则名称" prop="ruleName">
<el-input
style="width: 100%"
:disabled="isPreview"
size="medium"
v-model="form.ruleName"
placeholder="请输入规则名称"
/>
</el-form-item>
</el-col>
<el-col v-if="!isPreview" :span="14" style="padding-bottom: 24px;">
<el-select
v-model="searchValue"
@change="queryExistingRules"
filterable
clearable
size="medium"
placeholder="查询并导入现有规则"
>
<el-option
v-for="item in ruleList"
:key="item.id"
:label="item.ruleName"
:value="item.id"
/>
</el-select>
</el-col>
</el-row>
<el-form-item label="备注" prop="description" class="full-width-item">
<el-input
:disabled="isPreview"
v-model="form.description"
size="medium"
placeholder="请输入规则备注"
type="textarea"
/>
</el-form-item>
<div
class="form-section"
v-for="(rule, index) in form.ruleList"
:key="index"
>
<div class="section-title">
拆分规则 {{ index + 1 }}
<div>
<el-button
v-if="!isPreview && form.ruleList.length > 1"
type="text"
class="delete-btn"
@click="removeRule(index)"
>
<i class="el-icon-delete"></i> 删除
</el-button>
<el-button
v-if="!isPreview"
type="text"
class="copy-btn"
@click="copyRule(index)"
>
<i class="el-icon-copy-document"></i> 复制
</el-button>
</div>
</div>
<el-form-item
label="样式"
:prop="'ruleList.' + index + '.titleLevel'"
class="full-width-item"
>
<el-select
:disabled="isPreview"
v-model="rule.titleLevel"
placeholder="请选择标题级别"
size="medium"
>
<el-option
v-for="item in options"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label="规则"
:prop="'ruleList.' + index + '.ruleRegex'"
class="full-width-item"
>
<el-input
:disabled="isPreview"
type="textarea"
size="medium"
v-model="rule.ruleRegex"
placeholder="请输入规则表达式"
></el-input>
</el-form-item>
<el-form-item
label="备注"
:prop="'ruleList.' + index + '.description'"
class="full-width-item"
>
<el-input
:disabled="isPreview"
type="textarea"
size="medium"
v-model="rule.description"
placeholder="请输入规则备注"
></el-input>
</el-form-item>
</div>
<div class="add-rule-btn">
<el-button
v-if="!isPreview"
type="primary"
size="medium"
@click="addSplitRule"
>
<i class="el-icon-plus"></i>
新增拆分规则
</el-button>
</div>
</el-form>
</div>
<div class="drawer-footer" v-if="!isPreview">
<el-button size="medium" @click="handleClose"> </el-button>
<el-button type="primary" size="medium" @click="handleSubmit"
> </el-button
>
</div>
</el-drawer>
</div>
</template>
<script>
import {
addRuleSplit,
getRuleDetail,
getRulesList,
updateRuleSplit
} from '@/api/generatedApi'
export default {
name: 'AddRule',
data() {
return {
isPreview: false,
dialogVisible: false,
currentId: null, // 当前编辑的规则ID
form: {
ruleName: '',
ruleType: 1,
ruleList: [
{
titleLevel: '',
ruleRegex: '',
description: ''
}
]
},
ruleList: [],
searchValue: '',
options: [
{
value: 1,
label: '一级标题'
},
{
value: 2,
label: '二级标题'
},
{
value: 3,
label: '三级标题'
},
{
value: 4,
label: '四级标题'
},
{
value: 5,
label: '五级标题'
},
{
value: 6,
label: '六级标题'
}
],
rules: {
ruleName: [
{ required: true, message: '请输入规则名称', trigger: 'blur' },
{ max: 50, message: '长度不能超过50个字符', trigger: 'blur' },
{
pattern: /^(?!_)[a-zA-Z0-9\u4e00-\u9fa5_]+$/,
message: '支持中文、英文、数字、下划线(_),不能以下划线为开头',
trigger: 'blur'
}
],
'ruleList.0.titleLevel': [
{ required: true, message: '请选择标题级别' }
],
'ruleList.0.ruleRegex': [
{ required: true, message: '请输入关键词', trigger: 'blur' }
]
}
}
},
methods: {
init(id, options = { preview: false }) {
this.isPreview = options.preview
this.dialogVisible = true
this.getRuleList()
this.currentId = id
// 如果有id则获取详情
if (id) {
this.getDetail(id)
} else {
// 重置表单
this.$nextTick(() => {
this.$refs.ruleForm && this.$refs.ruleForm.resetFields()
this.form = {
ruleName: '',
ruleType: 1,
ruleList: [
{
titleLevel: '',
ruleRegex: '',
description: ''
}
]
}
})
}
},
async getRuleList() {
let res = await getRulesList({ ruleType: 1 })
console.log(res)
this.ruleList = res.content.content
},
// 获取详情
getDetail(id) {
getRuleDetail(id).then(res => {
this.form = res.content.content
// !this.currentId即新增
if (!this.currentId) {
this.form.ruleList.forEach(item => {
Object.keys(item).forEach(key => {
if (
key !== 'titleLevel' &&
key !== 'ruleRegex' &&
key !== 'description'
) {
delete item[key]
}
})
})
}
// 为每个规则项添加验证规则
this.form.ruleList.forEach((_, index) => {
this.addValidationRules(index)
})
})
},
queryExistingRules(val) {
console.log(val)
if (val) {
this.getDetail(val)
}
},
// 动态添加验证规则
addValidationRules(index) {
const rules = this.rules
rules[`ruleList.${index}.titleLevel`] = [
{ required: true, message: '请选择样式', trigger: 'change' }
]
rules[`ruleList.${index}.ruleRegex`] = [
{ required: true, message: '请输入关键词', trigger: 'blur' }
]
this.rules = { ...rules }
},
// 复制
copyRule(index) {
const currentRule = this.form.ruleList[index]
this.form.ruleList.push({
...currentRule
})
this.addValidationRules(this.form.ruleList.length - 1)
},
// 新增
addSplitRule() {
this.form.ruleList.push({
ruleName: '',
titleLevel: '',
ruleRegex: '',
description: ''
})
this.addValidationRules(this.form.ruleList.length - 1)
},
removeRule(index) {
this.form.ruleList.splice(index, 1)
// 重新生成所有验证规则
const newRules = {
ruleName: this.rules.ruleName
}
// 为剩余的每条规则重新生成验证规则
this.form.ruleList.forEach((_, newIndex) => {
newRules[`ruleList.${newIndex}.titleLevel`] = [
{ required: true, message: '请选择样式', trigger: 'change' }
]
newRules[`ruleList.${newIndex}.ruleRegex`] = [
{ required: true, message: '请输入关键词', trigger: 'blur' }
]
})
this.rules = newRules
},
handleSubmit() {
this.$refs.ruleForm.validate(valid => {
if (valid) {
// 表单验证通过根据是否有id调用新增还是编辑接口
const api = this.currentId ? updateRuleSplit : addRuleSplit
const params = {
...this.form,
id: this.currentId // 编辑时带上id
}
api(params)
.then(() => {
this.$message.success(this.currentId ? '修改成功' : '新增成功')
this.dialogVisible = false
this.$emit('getDataList')
})
.catch(err => {
this.$message.error(
(this.currentId ? '修改' : '新增') + '失败:' + err.message
)
})
} else {
this.$message.error('请填写完整所有必填项')
return false
}
})
},
handleClose() {
this.searchValue = ''
this.$refs.ruleForm.resetFields()
this.dialogVisible = false
}
}
}
</script>
<style scoped lang="scss">
.section-title {
font-size: 15px;
font-weight: 600;
color: #303133;
display: flex;
justify-content: space-between;
align-items: center;
.delete-btn {
color: #f78989;
}
.copy-btn {
color: #70b936;
font-size: 14px;
}
}
.content {
font-family: PingFangSC, PingFang SC;
overflow: hidden;
.form-section {
border-radius: 4px;
.section-title {
margin-top: 20px;
font-size: 15px;
font-weight: 600;
color: #303133;
display: flex;
justify-content: space-between;
align-items: center;
.delete-btn {
color: #f78989;
}
.copy-btn {
color: #70b936;
font-size: 14px;
}
}
}
.add-rule-btn {
text-align: center;
margin-bottom: 60px;
}
.full-width-item {
width: 100%;
margin-bottom: 10px;
}
}
.drawer-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: 20px;
background: #fff;
border-top: 1px solid #e4e7ed;
text-align: right;
}
</style>