refactor: update case API to use camelCase for parameters and add import/export functionality for case templates
This commit is contained in:
@@ -33,10 +33,14 @@ export function deleteModule(data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getCaseList(projectId, params) {
|
export function getCaseList(projectId, params) {
|
||||||
|
const query = Object.assign({}, params || {})
|
||||||
|
if (projectId !== undefined && projectId !== null && projectId !== '') {
|
||||||
|
query.projectId = projectId
|
||||||
|
}
|
||||||
return request({
|
return request({
|
||||||
url: '/case/list',
|
url: '/case/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: Object.assign({ project_id: projectId }, params || {})
|
params: query
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,8 +49,8 @@ export function getCaseDetail(projectId, caseId) {
|
|||||||
url: '/case/detail',
|
url: '/case/detail',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
params: {
|
params: {
|
||||||
project_id: projectId,
|
projectId,
|
||||||
id: caseId
|
caseId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -55,7 +59,7 @@ export function createCase(projectId, data) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/case/create',
|
url: '/case/create',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: Object.assign({ project_id: projectId }, data)
|
data: Object.assign({ projectId }, data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,7 +67,7 @@ export function updateCase(projectId, caseId, data) {
|
|||||||
return request({
|
return request({
|
||||||
url: '/case/update',
|
url: '/case/update',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: Object.assign({ project_id: projectId, id: caseId }, data)
|
data: Object.assign({ projectId, caseId }, data)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,8 +76,8 @@ export function deleteCase(projectId, caseId) {
|
|||||||
url: '/case/delete',
|
url: '/case/delete',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: {
|
data: {
|
||||||
project_id: projectId,
|
projectId,
|
||||||
id: caseId
|
caseId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,44 @@
|
|||||||
<div class="page-wrap">
|
<div class="page-wrap">
|
||||||
<page-section :title="form.id ? '编辑用例' : '新建用例'">
|
<page-section :title="form.id ? '编辑用例' : '新建用例'">
|
||||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px" size="small">
|
<el-form ref="form" :model="form" :rules="rules" label-width="120px" size="small">
|
||||||
<el-form-item label="项目ID">
|
<el-form-item label="产品" prop="productId">
|
||||||
<el-input v-model="projectId" style="width: 200px;"></el-input>
|
<el-select
|
||||||
|
v-model="form.productId"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择产品"
|
||||||
|
style="width: 360px;"
|
||||||
|
@change="handleProductChange"
|
||||||
|
@focus="loadProductOptions">
|
||||||
|
<el-option v-for="item in productOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="项目" prop="projectId">
|
||||||
|
<el-select
|
||||||
|
v-model="form.projectId"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择项目"
|
||||||
|
style="width: 360px;"
|
||||||
|
:disabled="!form.productId"
|
||||||
|
@change="handleProjectChange">
|
||||||
|
<el-option v-for="item in projectOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="模块" prop="moduleId">
|
||||||
|
<el-select
|
||||||
|
v-model="form.moduleId"
|
||||||
|
filterable
|
||||||
|
clearable
|
||||||
|
placeholder="请选择模块"
|
||||||
|
style="width: 360px;"
|
||||||
|
:disabled="!form.projectId"
|
||||||
|
@focus="loadModuleOptions">
|
||||||
|
<el-option v-for="item in moduleOptions" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="用例编号">
|
||||||
|
<el-input v-model="form.caseKey" placeholder="不填则由后端自动生成"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="标题" prop="title">
|
<el-form-item label="标题" prop="title">
|
||||||
<el-input v-model="form.title"></el-input>
|
<el-input v-model="form.title"></el-input>
|
||||||
@@ -23,19 +59,32 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="类型">
|
<el-form-item label="类型">
|
||||||
<el-select v-model="form.case_type">
|
<el-select v-model="form.caseType">
|
||||||
<el-option label="功能" :value="1"></el-option>
|
<el-option label="功能" :value="1"></el-option>
|
||||||
<el-option label="性能" :value="2"></el-option>
|
<el-option label="性能" :value="2"></el-option>
|
||||||
<el-option label="安全" :value="3"></el-option>
|
<el-option label="安全" :value="3"></el-option>
|
||||||
<el-option label="接口" :value="4"></el-option>
|
<el-option label="接口" :value="4"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="状态">
|
||||||
|
<el-select v-model="form.status">
|
||||||
|
<el-option label="正常" :value="1"></el-option>
|
||||||
|
<el-option label="已废弃" :value="2"></el-option>
|
||||||
|
<el-option label="评审中" :value="3"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否自动化">
|
||||||
|
<el-select v-model="form.isAuto">
|
||||||
|
<el-option label="未实现" :value="0"></el-option>
|
||||||
|
<el-option label="已实现" :value="1"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="标签">
|
<el-form-item label="标签">
|
||||||
<el-input v-model="tagsText" placeholder="多个标签用逗号分隔"></el-input>
|
<el-input v-model="tagsText" placeholder="多个标签用逗号分隔"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" :loading="saving" @click="submitForm">保存</el-button>
|
<el-button type="primary" :loading="saving" @click="submitForm">保存</el-button>
|
||||||
<el-button @click="$router.push('/test-platform/cases')">返回</el-button>
|
<el-button @click="backList">返回</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</page-section>
|
</page-section>
|
||||||
@@ -44,7 +93,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import PageSection from '@/components/TestPlatform/common/PageSection'
|
import PageSection from '@/components/TestPlatform/common/PageSection'
|
||||||
import { createCase, getCaseDetail, updateCase } from '@/api/caseApi'
|
import { createCase, getCaseDetail, getModuleTree, updateCase } from '@/api/caseApi'
|
||||||
|
import { getProductList } from '@/api/productApi'
|
||||||
|
import { getProjectDetail, getProjectList } from '@/api/projectApi'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CaseEditor',
|
name: 'CaseEditor',
|
||||||
@@ -52,59 +103,175 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
saving: false,
|
saving: false,
|
||||||
projectId: this.$route.query.projectId || 1,
|
productOptions: [],
|
||||||
|
projectOptions: [],
|
||||||
|
moduleOptions: [],
|
||||||
form: {
|
form: {
|
||||||
|
productId: this.$route.query.productId ? Number(this.$route.query.productId) : '',
|
||||||
|
projectId: this.$route.query.projectId ? Number(this.$route.query.projectId) : '',
|
||||||
id: '',
|
id: '',
|
||||||
|
moduleId: '',
|
||||||
|
caseKey: '',
|
||||||
title: '',
|
title: '',
|
||||||
preconditions: '',
|
preconditions: '',
|
||||||
steps: [],
|
steps: [],
|
||||||
priority: 2,
|
priority: 2,
|
||||||
case_type: 1,
|
caseType: 1,
|
||||||
tags: []
|
tags: [],
|
||||||
|
status: 1,
|
||||||
|
isAuto: 0
|
||||||
},
|
},
|
||||||
stepsText: '[]',
|
stepsText: '[]',
|
||||||
tagsText: '',
|
tagsText: '',
|
||||||
rules: {
|
rules: {
|
||||||
|
productId: [{ required: true, message: '请选择产品', trigger: 'change' }],
|
||||||
|
projectId: [{ required: true, message: '请选择项目', trigger: 'change' }],
|
||||||
|
moduleId: [{ required: true, message: '请选择模块', trigger: 'change' }],
|
||||||
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
|
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
|
||||||
steps: [{ required: true, message: '请输入步骤', trigger: 'change' }]
|
steps: [{ required: true, message: '请输入步骤', trigger: 'change' }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
loadProductOptions() {
|
||||||
|
if (this.productOptions && this.productOptions.length > 0) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
return getProductList({ pageNo: 1, pageSize: 1000, status: 1 }).then(res => {
|
||||||
|
const data = res && res.data ? res.data : res || {}
|
||||||
|
this.productOptions = data.items || data.list || data.data || []
|
||||||
|
}).catch(() => {
|
||||||
|
this.productOptions = []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadProjectOptions() {
|
||||||
|
if (!this.form.productId) {
|
||||||
|
this.projectOptions = []
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
return getProjectList({ pageNo: 1, pageSize: 1000, status: 1, productId: this.form.productId }).then(res => {
|
||||||
|
const data = res && res.data ? res.data : res || {}
|
||||||
|
this.projectOptions = data.items || data.list || data.data || []
|
||||||
|
}).catch(() => {
|
||||||
|
this.projectOptions = []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
loadModuleOptions() {
|
||||||
|
if (!this.form.projectId) {
|
||||||
|
this.moduleOptions = []
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
return getModuleTree({ projectId: this.form.projectId }).then(res => {
|
||||||
|
const data = (res && res.data) || res || {}
|
||||||
|
const list = data.list || data.items || []
|
||||||
|
this.moduleOptions = Array.isArray(list) ? list : []
|
||||||
|
}).catch(() => {
|
||||||
|
this.moduleOptions = []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleProductChange() {
|
||||||
|
this.form.projectId = ''
|
||||||
|
this.form.moduleId = ''
|
||||||
|
this.projectOptions = []
|
||||||
|
this.moduleOptions = []
|
||||||
|
this.loadProjectOptions()
|
||||||
|
},
|
||||||
|
handleProjectChange() {
|
||||||
|
this.form.moduleId = ''
|
||||||
|
this.moduleOptions = []
|
||||||
|
this.loadModuleOptions()
|
||||||
|
},
|
||||||
fetchDetail() {
|
fetchDetail() {
|
||||||
const caseId = this.$route.query.caseId
|
const caseId = this.$route.query.caseId
|
||||||
if (!caseId) {
|
if (!caseId) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
getCaseDetail(this.projectId, caseId).then(res => {
|
getCaseDetail(this.form.projectId, caseId).then(res => {
|
||||||
const data = (res && res.data) || res || {}
|
const data = (res && res.data) || res || {}
|
||||||
this.form = Object.assign({}, this.form, data)
|
this.form = Object.assign({}, this.form, {
|
||||||
this.stepsText = JSON.stringify(data.steps || [], null, 2)
|
id: data.id || caseId,
|
||||||
this.tagsText = (data.tags || []).join(',')
|
moduleId: data.moduleId || data.module_id || '',
|
||||||
|
caseKey: data.caseKey || data.case_key || '',
|
||||||
|
title: data.title || '',
|
||||||
|
preconditions: data.preconditions || '',
|
||||||
|
steps: data.steps || [],
|
||||||
|
priority: data.priority !== undefined ? data.priority : 2,
|
||||||
|
caseType: data.caseType || data.case_type || 1,
|
||||||
|
tags: data.tags || [],
|
||||||
|
status: data.status || 1,
|
||||||
|
isAuto: data.isAuto !== undefined ? data.isAuto : (data.is_auto !== undefined ? data.is_auto : 0)
|
||||||
|
})
|
||||||
|
this.stepsText = JSON.stringify(this.form.steps || [], null, 2)
|
||||||
|
this.tagsText = Array.isArray(this.form.tags) ? this.form.tags.join(',') : (this.form.tags || '')
|
||||||
|
if (this.form.projectId) {
|
||||||
|
this.loadModuleOptions()
|
||||||
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
submitForm() {
|
submitForm() {
|
||||||
|
let steps = []
|
||||||
try {
|
try {
|
||||||
this.form.steps = JSON.parse(this.stepsText || '[]')
|
steps = JSON.parse(this.stepsText || '[]')
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.$message({ type: 'error', message: '步骤 JSON 格式错误' })
|
this.$message({ type: 'error', message: '步骤 JSON 格式错误' })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.form.tags = this.tagsText ? this.tagsText.split(',').map(item => item.trim()).filter(Boolean) : []
|
const tags = this.tagsText ? this.tagsText.split(',').map(item => item.trim()).filter(Boolean) : []
|
||||||
|
const payload = this.cleanParams({
|
||||||
|
projectId: this.form.projectId,
|
||||||
|
moduleId: this.form.moduleId,
|
||||||
|
caseKey: this.form.caseKey,
|
||||||
|
title: this.form.title,
|
||||||
|
preconditions: this.form.preconditions,
|
||||||
|
steps,
|
||||||
|
priority: this.form.priority,
|
||||||
|
caseType: this.form.caseType,
|
||||||
|
tags,
|
||||||
|
status: this.form.status,
|
||||||
|
isAuto: this.form.isAuto
|
||||||
|
})
|
||||||
this.saving = true
|
this.saving = true
|
||||||
const request = this.form.id || this.$route.query.caseId
|
const caseId = this.form.id || this.$route.query.caseId
|
||||||
? updateCase(this.projectId, this.form.id || this.$route.query.caseId, this.form)
|
const request = caseId ? updateCase(this.form.projectId, caseId, payload) : createCase(this.form.projectId, payload)
|
||||||
: createCase(this.projectId, this.form)
|
|
||||||
request.then(() => {
|
request.then(() => {
|
||||||
this.$message({ type: 'success', message: '保存成功' })
|
this.$message({ type: 'success', message: '保存成功' })
|
||||||
this.$router.push({ path: '/test-platform/cases', query: { projectId: this.projectId } })
|
this.backList()
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.saving = false
|
this.saving = false
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
cleanParams(params) {
|
||||||
|
return Object.keys(params).reduce((result, key) => {
|
||||||
|
if (params[key] !== '' && params[key] !== undefined && params[key] !== null) {
|
||||||
|
result[key] = params[key]
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}, {})
|
||||||
|
},
|
||||||
|
backList() {
|
||||||
|
this.$router.push({ path: '/test-platform/case', query: { productId: this.form.productId || undefined, projectId: this.form.projectId || undefined } })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
this.loadProductOptions().then(() => {
|
||||||
|
if (this.form.projectId && !this.form.productId) {
|
||||||
|
return getProjectDetail(this.form.projectId).then(res => {
|
||||||
|
const data = res && res.data ? res.data : res || {}
|
||||||
|
const pid = data.productId || data.product_id || ''
|
||||||
|
if (pid) {
|
||||||
|
this.form.productId = pid
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
}).then(() => {
|
||||||
|
return this.loadProjectOptions()
|
||||||
|
}).then(() => {
|
||||||
|
if (this.form.projectId) {
|
||||||
|
return this.loadModuleOptions()
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
this.fetchDetail()
|
this.fetchDetail()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -26,17 +26,30 @@ service.interceptors.request.use(
|
|||||||
// 响应拦截 401 token过期处理
|
// 响应拦截 401 token过期处理
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
response => {
|
response => {
|
||||||
if(response.data.code===500){
|
const data = response && response.data ? response.data : {}
|
||||||
Message.error("服务异常")
|
// 兼容后端返回结构:{ success, code, message, data }
|
||||||
}else if(response.data.code===451){
|
if (data && data.code === 500) {
|
||||||
router.push({name:'login'})
|
Message.error('服务异常')
|
||||||
}
|
} else if (data && data.code === 451) {
|
||||||
else {
|
router.push({ name: 'login' })
|
||||||
|
} else if (data && data.success === false) {
|
||||||
|
Message.error(data.message || '请求失败')
|
||||||
|
} else {
|
||||||
return response.data
|
return response.data
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error => {
|
error => {
|
||||||
// 错误提醒
|
// 非 2xx 时会进入这里(如 40009/40012),后端通常会带 JSON body
|
||||||
|
const data = error && error.response && error.response.data ? error.response.data : null
|
||||||
|
if (data && typeof data === 'object') {
|
||||||
|
if (data.success === false) {
|
||||||
|
Message.error(data.message || '请求失败')
|
||||||
|
} else if (data.code && data.code !== 20000 && data.message) {
|
||||||
|
Message.error(data.message || '请求失败')
|
||||||
|
}
|
||||||
|
} else if (error && error.message) {
|
||||||
|
Message.error(error.message)
|
||||||
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user