提交代码
This commit is contained in:
parent
959ed2c2c9
commit
049a415936
|
|
@ -49,6 +49,7 @@
|
|||
"js-beautify": "1.13.0",
|
||||
"js-cookie": "3.0.1",
|
||||
"jsencrypt": "3.0.0-rc.1",
|
||||
"label-studio": "^1.0.1",
|
||||
"nprogress": "0.2.0",
|
||||
"quill": "1.3.7",
|
||||
"screenfull": "5.0.2",
|
||||
|
|
|
|||
|
|
@ -41,12 +41,19 @@ export function getAnnotationDetails(data) {
|
|||
})
|
||||
}
|
||||
|
||||
export function listSelection(data) {
|
||||
export function getMyNoAnnotatedTask(data) {
|
||||
return request({
|
||||
url: '/ai/annotationTask/list/listSelection',
|
||||
url: '/ai/annotationTask/getMyNoAnnotatedTask',
|
||||
method: 'get',
|
||||
params: data
|
||||
})
|
||||
}
|
||||
|
||||
export function getMyAnnotationFiles(annotationStatus,taskId) {
|
||||
return request({
|
||||
url: '/ai/annotationTask/getMyAnnotationFiles/'+annotationStatus+'/'+taskId,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@
|
|||
<!-- 新建数据集弹窗 -->
|
||||
<add-task-dialog :open="addOpen" :get-list="getList" @dialog-cancel="handleCancel"></add-task-dialog>
|
||||
|
||||
<release-version-dialog :dataset-id="datasetId" :open="releaseOpen" :task-id="taskId" @dialog-cancel="handleCancel"></release-version-dialog>
|
||||
<release-version-dialog :get-list="getList" :dataset-id="datasetId" :open="releaseOpen" :task-id="taskId" :last-version-name="lastVersionName" @dialog-cancel="handleCancel"></release-version-dialog>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -137,6 +137,7 @@ export default {
|
|||
{label:'正在审核',value:'3'},
|
||||
{label:'已审核',value:'4'},
|
||||
],
|
||||
lastVersionName:'',
|
||||
taskId:0,
|
||||
datasetId: 0,
|
||||
// 遮罩层
|
||||
|
|
@ -204,9 +205,11 @@ export default {
|
|||
this.addOpen = true;
|
||||
},
|
||||
handleRelease(row){
|
||||
this.releaseOpen = true;
|
||||
this.datasetId = row.datasetId;
|
||||
this.taskId = row.taskId;
|
||||
this.lastVersionName = row.lastVersionName || '';
|
||||
console.log(this.lastVersionName);
|
||||
this.releaseOpen = true;
|
||||
},
|
||||
handleDimension(row){
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
<template>
|
||||
<div>
|
||||
<div ref="labelStudio" id="label-studio-container"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import LabelStudio from 'label-studio';
|
||||
import 'label-studio/build/static/css/main.css';
|
||||
|
||||
export default {
|
||||
name: 'CustomLabelStudio',
|
||||
props: {
|
||||
task: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
labelStudio: null,
|
||||
customButtons: [
|
||||
{
|
||||
id: "custom-button",
|
||||
name: "自定义按钮",
|
||||
icon: "🔍",
|
||||
action: () => {
|
||||
console.log("自定义按钮被点击了!");
|
||||
}
|
||||
}
|
||||
],
|
||||
chineseLocalization: {
|
||||
"DONE": "完成",
|
||||
"SKIP": "跳过",
|
||||
"SUBMIT": "提交",
|
||||
"ANNOTATION": "标注",
|
||||
"ANNOTATIONS": "标注",
|
||||
"LABEL": "标签",
|
||||
"LABELS": "标签",
|
||||
"RELATIONS": "关系",
|
||||
"REGIONS": "区域",
|
||||
"RESULTS": "结果",
|
||||
},
|
||||
labelConfig: `
|
||||
<View>
|
||||
<Image name="image" value="$image"/>
|
||||
<RectangleLabels name="label" toName="image">
|
||||
<Label value="人" background="#ff0000"/>
|
||||
<Label value="车" background="#00ff00"/>
|
||||
</RectangleLabels>
|
||||
</View>
|
||||
`,
|
||||
previousAnnotations: [] // 用于保存上次的标注框数据
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initLabelStudio();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.labelStudio) {
|
||||
this.labelStudio.destroy();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initLabelStudio() {
|
||||
this.labelStudio = new LabelStudio('label-studio-container', {
|
||||
config: this.labelConfig,
|
||||
interfaces: [
|
||||
"panel",
|
||||
"update",
|
||||
"controls",
|
||||
],
|
||||
user: {
|
||||
pk: 1,
|
||||
firstName: "James",
|
||||
lastName: "Dean"
|
||||
},
|
||||
task: JSON.parse(this.task),
|
||||
locale: 'zh_CN',
|
||||
messages: this.chineseLocalization,
|
||||
onLabelStudioLoad: (LS) => {
|
||||
console.log("Label Studio 已加载", LS);
|
||||
var c = LS.annotationStore.addAnnotation({
|
||||
userGenerate: true
|
||||
});
|
||||
LS.annotationStore.selectAnnotation(c.id);
|
||||
// 注册事件监听
|
||||
LS.annotationStore.events.on('addAnnotation', this.handleAddAnnotation);
|
||||
LS.annotationStore.events.on('updateAnnotation', this.handleUpdateAnnotation);
|
||||
|
||||
// 启动定期检查标注框数据
|
||||
this.startAnnotationCheck(LS);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 处理新增标注框
|
||||
handleAddAnnotation(annotation) {
|
||||
console.log("新增标注框:", annotation);
|
||||
},
|
||||
|
||||
// 处理更新标注框
|
||||
handleUpdateAnnotation(annotation) {
|
||||
console.log("更新标注框:", annotation);
|
||||
},
|
||||
|
||||
// 启动定期检查标注框数据
|
||||
startAnnotationCheck(LS) {
|
||||
this.checkAnnotationsInterval = setInterval(() => {
|
||||
this.checkAnnotations(LS);
|
||||
}, 1000); // 每秒检查一次
|
||||
},
|
||||
|
||||
// 停止定期检查
|
||||
stopAnnotationCheck() {
|
||||
if (this.checkAnnotationsInterval) {
|
||||
clearInterval(this.checkAnnotationsInterval);
|
||||
}
|
||||
},
|
||||
|
||||
// 检查标注框数据
|
||||
checkAnnotations(LS) {
|
||||
const currentAnnotations = LS.annotationStore.data; // 获取当前的标注数据
|
||||
|
||||
// 如果标注数据发生了变化
|
||||
if (this.hasAnnotationsChanged(currentAnnotations)) {
|
||||
console.log('标注数据发生变化:', currentAnnotations);
|
||||
this.previousAnnotations = currentAnnotations; // 更新保存的标注数据
|
||||
}
|
||||
},
|
||||
|
||||
// 比较标注数据是否发生变化
|
||||
hasAnnotationsChanged(currentAnnotations) {
|
||||
// 直接比较标注数量变化
|
||||
if (currentAnnotations.length !== this.previousAnnotations.length) {
|
||||
return true; // 数量不一样说明发生了变化
|
||||
}
|
||||
|
||||
// 比较每个标注框的 ID 和几何信息(减少深度比较)
|
||||
for (let i = 0; i < currentAnnotations.length; i++) {
|
||||
const current = currentAnnotations[i];
|
||||
const previous = this.previousAnnotations[i];
|
||||
|
||||
if (current.id !== previous.id) {
|
||||
return true; // 标注 ID 不同说明发生了变化
|
||||
}
|
||||
|
||||
// 如果标注框的几何信息有变化,返回 true
|
||||
if (JSON.stringify(current.geometry) !== JSON.stringify(previous.geometry)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.label-studio-container {
|
||||
height: 600px;
|
||||
width: 100%;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -8,7 +8,8 @@
|
|||
<el-button v-for="(icon, index) in leftIcons"
|
||||
:key="index"
|
||||
:icon="icon"
|
||||
circle>
|
||||
circle
|
||||
>
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- 右侧选择框和设置按钮 -->
|
||||
|
|
@ -18,12 +19,14 @@
|
|||
placeholder="请选择标注任务"
|
||||
clearable
|
||||
class="select-task"
|
||||
@change="selectTask"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in dict.type.ai_annotate_type"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
v-for="dict in taskList"
|
||||
:key="dict.taskId"
|
||||
:label="dict.taskName"
|
||||
:value="dict.taskId"
|
||||
|
||||
/>
|
||||
</el-select>
|
||||
<span class="settings-icon">
|
||||
|
|
@ -40,41 +43,91 @@
|
|||
<div>
|
||||
<el-button
|
||||
type="primary"
|
||||
:class="{'is-selected': annotationType===0}"
|
||||
plain
|
||||
size="mini"
|
||||
>全部</el-button>
|
||||
@click="toggleSelected(0)"
|
||||
>全部
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:class="{'is-selected': annotationType===1}"
|
||||
plain
|
||||
size="mini"
|
||||
>已标注</el-button>
|
||||
@click="toggleSelected(1)"
|
||||
>已标注
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:class="{'is-selected': annotationType===2}"
|
||||
plain
|
||||
size="mini"
|
||||
>未标注</el-button>
|
||||
@click="toggleSelected(2)"
|
||||
>未标注
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
:class="{'is-selected': annotationType===3}"
|
||||
plain
|
||||
size="mini"
|
||||
>审核驳回</el-button>
|
||||
@click="toggleSelected(3)"
|
||||
>审核驳回
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-content-left-bottom">
|
||||
<div>
|
||||
<ul>
|
||||
<li v-for="i in count" class="list-item">
|
||||
<el-checkbox v-model="checked"> 文件名称{{ i }}</el-checkbox>
|
||||
<li v-for="item in images" class="list-item">
|
||||
<div @click="setItem(item)">
|
||||
<input type="checkbox" :checked="false" disabled>
|
||||
<span style="font-size: 14px;margin-left: 5px">{{ item.fileName }}</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-content-center">
|
||||
<div></div>
|
||||
<div>
|
||||
<custom-label-studio :task="JSON.stringify(task)"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-content-right">
|
||||
<div></div>
|
||||
<div class="bottom-content-right-center">
|
||||
<div class="bottom-content-right-top">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-content-right-middle">
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="bottom-content-right-bottom">
|
||||
<div>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
size="mini"
|
||||
>上一张
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
size="mini"
|
||||
>下一张
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
size="mini"
|
||||
>保存
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -82,10 +135,21 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import customLabelStudio from './customLabelStudio.vue'
|
||||
import { getMyNoAnnotatedTask,getMyAnnotationFiles } from '../../../../api/dataCenter/annotationTask'
|
||||
|
||||
export default {
|
||||
dicts: ['ai_annotate_type'],
|
||||
components: { customLabelStudio },
|
||||
data() {
|
||||
return {
|
||||
taskList:[],
|
||||
task: {
|
||||
id: 1,
|
||||
data: {
|
||||
image: 'http://192.168.0.14:9090/bonus/1/测试/xigu_wangwang_3787075_37.jpg'
|
||||
}
|
||||
},
|
||||
taskId: undefined, // 当前选中的任务 ID
|
||||
leftIcons: [
|
||||
'el-icon-circle-plus-outline',
|
||||
|
|
@ -93,21 +157,66 @@ export default {
|
|||
'el-icon-search',
|
||||
'el-icon-search',
|
||||
'el-icon-search',
|
||||
'el-icon-search',
|
||||
'el-icon-search'
|
||||
], // 顶部左侧按钮的图标
|
||||
count: 600
|
||||
};
|
||||
count: 600,
|
||||
annotationType: 0,
|
||||
images: []
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
load () {
|
||||
this.count += 2
|
||||
created() {
|
||||
this.listSelection()
|
||||
},
|
||||
methods: {
|
||||
listSelection() {
|
||||
getMyNoAnnotatedTask({}).then(res => {
|
||||
this.taskList = res.data;
|
||||
})
|
||||
},
|
||||
selectTask(id){
|
||||
this.images = [];
|
||||
this.annotationType = 0;
|
||||
this.taskId = id;
|
||||
getMyAnnotationFiles(this.annotationType,id).then(response => {
|
||||
this.images =response.data;
|
||||
})
|
||||
},
|
||||
load() {
|
||||
},
|
||||
toggleSelected(type) {
|
||||
this.images = [];
|
||||
if (this.annotationType !== type) {
|
||||
this.annotationType = type
|
||||
}
|
||||
if (!this.taskId){
|
||||
return
|
||||
}
|
||||
getMyAnnotationFiles(this.annotationType,this.taskId).then(response => {
|
||||
this.images =response.data;
|
||||
})
|
||||
},
|
||||
setItem(item) {
|
||||
console.log(item)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
/* 默认按钮样式 */
|
||||
.el-button {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 选中时的样式 */
|
||||
.el-button.is-selected {
|
||||
background-color: #007bff !important; /* 设置选中背景色 */
|
||||
border-color: #007bff !important; /* 设置选中边框色 */
|
||||
color: white !important; /* 设置字体颜色 */
|
||||
}
|
||||
|
||||
.div-main {
|
||||
width: 100%;
|
||||
height: calc(100vh - 84px);
|
||||
|
|
@ -157,7 +266,9 @@ export default {
|
|||
.bottom-part {
|
||||
width: 100%;
|
||||
height: calc(100% - 60px);
|
||||
padding: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
|
||||
.bottom-content {
|
||||
display: flex;
|
||||
|
|
@ -177,26 +288,29 @@ export default {
|
|||
width: 20%;
|
||||
|
||||
.bottom-content-left-bottom,
|
||||
.bottom-content-left-top{
|
||||
.bottom-content-left-top {
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
}
|
||||
.bottom-content-left-top{
|
||||
|
||||
.bottom-content-left-top {
|
||||
height: 50px;
|
||||
div{
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dfe4ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-content-left-bottom{
|
||||
.bottom-content-left-bottom {
|
||||
height: calc(100% - 50px);
|
||||
div{
|
||||
|
||||
> div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
|
|
@ -204,7 +318,8 @@ export default {
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
ul{
|
||||
|
||||
ul {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
|
@ -212,18 +327,54 @@ export default {
|
|||
list-style: none; /* 移除默认的点样式 */
|
||||
li {
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
padding: 1px;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
div {
|
||||
height: 40px;
|
||||
padding-left: 2px;
|
||||
display: flex;
|
||||
cursor: pointer; /* 手势效果 */
|
||||
align-items: center;
|
||||
background-color: #f5f7fa;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
appearance: none; /* 隐藏默认复选框样式 */
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
border: 1px solid #4d4e51;
|
||||
border-radius: 4px; /* 圆角方框 */
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked::after {
|
||||
content: '✔'; /* 显示勾符号 */
|
||||
color: white;
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
input[type="checkbox"]:checked {
|
||||
background-color: rgb(64, 158, 255); /* 改变选中颜色 */
|
||||
border-color: rgb(64, 158, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 针对自定义滚动条样式 */
|
||||
ul::-webkit-scrollbar {
|
||||
cursor: default; /* 对滚动条自定义光标 */
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
ul::-webkit-scrollbar-thumb {
|
||||
background-color: #888;
|
||||
cursor: pointer; /* 手势效果 */
|
||||
}
|
||||
|
||||
ul::-webkit-scrollbar-thumb:hover {
|
||||
background-color: #555;
|
||||
}
|
||||
|
|
@ -234,7 +385,8 @@ export default {
|
|||
.bottom-content-center {
|
||||
width: 60%;
|
||||
padding: 5px;
|
||||
div{
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
|
|
@ -245,15 +397,57 @@ export default {
|
|||
.bottom-content-right {
|
||||
width: 20%;
|
||||
padding: 5px;
|
||||
div{
|
||||
|
||||
.bottom-content-right-center {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dfe4ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow:auto;
|
||||
flex-direction: column;
|
||||
|
||||
.bottom-content-right-top {
|
||||
width: 100%;
|
||||
height: calc(50% - 25px);
|
||||
padding: 5px;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dfe4ed;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-content-right-middle {
|
||||
width: 100%;
|
||||
height: calc(50% - 25px);
|
||||
padding: 5px;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dfe4ed;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-content-right-bottom {
|
||||
width: 100%;
|
||||
height: 50px;
|
||||
padding: 5px;
|
||||
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #f5f7fa;
|
||||
border: 1px solid #dfe4ed;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ import {listDataSetLabels } from "@/api/dataCenter/labels";
|
|||
import Treeselect from "@riophae/vue-treeselect";
|
||||
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
|
||||
import { datasetList } from '@/api/dataCenter/dataSet'
|
||||
import { parseTime } from '../../../../utils/bonus'
|
||||
export default {
|
||||
dicts: ['ai_annotate_type'],
|
||||
components: { selectPersonnelDialog, Treeselect},
|
||||
|
|
@ -226,8 +227,11 @@ export default {
|
|||
}
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.startTime = parseTime(this.form.data[0])
|
||||
this.form.endTime = parseTime(this.form.data[1])
|
||||
this.form.isStartTeam = this.form.startTeam?'1':'0';
|
||||
this.form.labels = this.form.label.join(",")
|
||||
console.log(this.form)
|
||||
if (this.form.isStartTeam) {
|
||||
let annotators = [];
|
||||
let reviewers = [];
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
<template>
|
||||
<div>
|
||||
<el-dialog title="发布版本" :visible.sync="isOpen" width="500px" append-to-body @close="cancel" :close-on-click-modal="false">
|
||||
<el-form ref="form" label-position="top" :model="form" :rules="rules" >
|
||||
<el-dialog title="发布版本" :visible.sync="isOpen" width="500px" append-to-body @close="cancel"
|
||||
:close-on-click-modal="false"
|
||||
>
|
||||
<el-form ref="form" label-position="top" :model="form" :rules="rules">
|
||||
<el-form-item label="版本名称" prop="versionName">
|
||||
<el-input v-model="form.versionName" maxlength="20" placeholder="请输入版本名称" />
|
||||
<el-input v-model="form.versionName" maxlength="20" placeholder="请输入版本名称"/>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="versionDesc">
|
||||
<el-input
|
||||
|
|
@ -35,66 +37,106 @@ export default {
|
|||
open: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
required: true
|
||||
},
|
||||
getList: {
|
||||
type: Function,
|
||||
required: true,
|
||||
},
|
||||
datasetId:{
|
||||
datasetId: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
taskId:{
|
||||
taskId: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
lastVersionName: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isOpen: {
|
||||
get() {
|
||||
return this.open;
|
||||
return this.open
|
||||
},
|
||||
set(value) {
|
||||
this.$emit('update:open', value);
|
||||
},
|
||||
this.$emit('update:open', value)
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {}, // 初始化为空
|
||||
rules:{
|
||||
versionName:[
|
||||
form: {
|
||||
versionName: this.lastVersionName || '' // 初始化为传入的 lastVersionName
|
||||
}, // 初始化为空
|
||||
rules: {
|
||||
versionName: [
|
||||
{ required: true, message: '版本名称不能为空', trigger: 'blur' },
|
||||
{ pattern: /^V\d{1,3}(\.\d{1,3}){2}$/, message: '版本名称式不正确,应为 vX.Y.Z 格式', trigger: 'blur' }
|
||||
]
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isOpen(newVal){
|
||||
if (newVal){
|
||||
if (this.isValidVersion(this.lastVersionName)) {
|
||||
this.form.versionName = this.incrementMajorVersion(this.lastVersionName);
|
||||
} else {
|
||||
this.form.versionName = 'V1.0.0'; // 如果格式不正确,则清空
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
// 判断版本号格式是否正确
|
||||
isValidVersion(version) {
|
||||
return /^V\d{1,3}(\.\d{1,3}){2}$/.test(version);
|
||||
},
|
||||
|
||||
// 增加大版本号
|
||||
incrementMajorVersion(version) {
|
||||
const match = version.match(/^V(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/);
|
||||
if (match) {
|
||||
let major = parseInt(match[1], 10);
|
||||
// 增加主版本号
|
||||
major += 1;
|
||||
return `V${major}.0.0`; // 返回新的版本号,次版本和修订号重置为 0
|
||||
}
|
||||
return version; // 如果格式不符合,则返回原始版本号
|
||||
},
|
||||
// 数据提交
|
||||
submitForm() {
|
||||
this.$refs["form"].validate(valid => {
|
||||
this.$refs['form'].validate(valid => {
|
||||
if (valid) {
|
||||
this.form.datasetId = this.datasetId;
|
||||
this.form.taskId = this.taskId;
|
||||
this.form.datasetId = this.datasetId
|
||||
this.form.taskId = this.taskId
|
||||
add(this.form).then(response => {
|
||||
this.$modal.msgSuccess("发布成功");
|
||||
this.cancel();
|
||||
this.$modal.msgSuccess('发布成功')
|
||||
this.cancel()
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
// 取消按钮
|
||||
cancel() {
|
||||
this.isOpen = false;
|
||||
this.reset();
|
||||
this.$emit('dialog-cancel'); // 通知父组件
|
||||
this.isOpen = false
|
||||
this.reset()
|
||||
this.$emit('dialog-cancel') // 通知父组件
|
||||
this.getList();
|
||||
},
|
||||
// 表单重置
|
||||
reset() {
|
||||
this.form = {}; // 清空表单
|
||||
this.$refs.form.resetFields(); // 调用 Element UI 的重置方法
|
||||
},
|
||||
},
|
||||
};
|
||||
this.form = {versionName:''} // 清空表单
|
||||
this.$refs.form.resetFields() // 调用 Element UI 的重置方法
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
|
|
|||
Loading…
Reference in New Issue