|
@@ -202,11 +202,14 @@
|
|
|
height="100%"
|
|
height="100%"
|
|
|
stripe
|
|
stripe
|
|
|
style="width: 100%"
|
|
style="width: 100%"
|
|
|
- @row-click="handleRowClick">
|
|
|
|
|
|
|
+ @row-dblclick="handleRowClick">
|
|
|
<el-table-column align="center" type="index" width="50" />
|
|
<el-table-column align="center" type="index" width="50" />
|
|
|
- <el-table-column v-if="isColumnVisible('taskNo')" label="任务编号" show-overflow-tooltip width="140">
|
|
|
|
|
|
|
+ <el-table-column v-if="isColumnVisible('taskNo')" label="任务编号" show-overflow-tooltip width="180">
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- {{ row.taskNo || '-' }}
|
|
|
|
|
|
|
+ <span class="cell-with-copy">
|
|
|
|
|
+ <span>{{ row.taskNo || '-' }}</span>
|
|
|
|
|
+ <i v-if="row.taskNo" class="el-icon-document-copy copy-btn" @click.stop="handleCopy(row.taskNo)" />
|
|
|
|
|
+ </span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
<el-table-column
|
|
@@ -216,7 +219,13 @@
|
|
|
:render-header="renderSortableHeader('任务标题', 'taskTitle')"
|
|
:render-header="renderSortableHeader('任务标题', 'taskTitle')"
|
|
|
show-overflow-tooltip>
|
|
show-overflow-tooltip>
|
|
|
<template slot-scope="{ row }">
|
|
<template slot-scope="{ row }">
|
|
|
- <span class="task-title-text">{{ row.taskTitle || '-' }}</span>
|
|
|
|
|
|
|
+ <span class="cell-with-copy">
|
|
|
|
|
+ <span class="task-title-text">{{ row.taskTitle || '-' }}</span>
|
|
|
|
|
+ <i
|
|
|
|
|
+ v-if="row.taskTitle"
|
|
|
|
|
+ class="el-icon-document-copy copy-btn"
|
|
|
|
|
+ @click.stop="handleCopy(row.taskTitle)" />
|
|
|
|
|
+ </span>
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
<el-table-column
|
|
<el-table-column
|
|
@@ -324,6 +333,11 @@
|
|
|
{{ selectDictLabel(defectTypeOptions, row.defectType) }}
|
|
{{ selectDictLabel(defectTypeOptions, row.defectType) }}
|
|
|
</template>
|
|
</template>
|
|
|
</el-table-column>
|
|
</el-table-column>
|
|
|
|
|
+ <el-table-column v-if="isColumnVisible('attribute2')" label="历史遗留" width="100">
|
|
|
|
|
+ <template slot-scope="{ row }">
|
|
|
|
|
+ {{ row.attribute2 === '10' ? '是' : row.attribute2 === '20' ? '否' : '-' }}
|
|
|
|
|
+ </template>
|
|
|
|
|
+ </el-table-column>
|
|
|
<el-table-column
|
|
<el-table-column
|
|
|
v-if="isColumnVisible('releaseVersion')"
|
|
v-if="isColumnVisible('releaseVersion')"
|
|
|
label="发布版本"
|
|
label="发布版本"
|
|
@@ -334,7 +348,7 @@
|
|
|
<div class="release-version-cell">
|
|
<div class="release-version-cell">
|
|
|
<span>{{ row.releaseVersion || '-' }}</span>
|
|
<span>{{ row.releaseVersion || '-' }}</span>
|
|
|
<el-tooltip
|
|
<el-tooltip
|
|
|
- v-if="String(row.taskType) === '40' && row.releaseVersion"
|
|
|
|
|
|
|
+ v-if="String(row.taskType) === '38' && row.releaseVersion"
|
|
|
content="查看关联任务"
|
|
content="查看关联任务"
|
|
|
placement="top">
|
|
placement="top">
|
|
|
<el-button
|
|
<el-button
|
|
@@ -449,7 +463,7 @@
|
|
|
:preset-project="currentProjectOption"
|
|
:preset-project="currentProjectOption"
|
|
|
:task-data="editData"
|
|
:task-data="editData"
|
|
|
:visible.sync="editDialogVisible"
|
|
:visible.sync="editDialogVisible"
|
|
|
- @refresh="fetchData" />
|
|
|
|
|
|
|
+ @refresh="handleEditDialogRefresh" />
|
|
|
|
|
|
|
|
<!-- 排期使用 TaskDetailDialog 的排期模式 -->
|
|
<!-- 排期使用 TaskDetailDialog 的排期模式 -->
|
|
|
<complete-dialog
|
|
<complete-dialog
|
|
@@ -482,7 +496,9 @@
|
|
|
|
|
|
|
|
<work-hour-dialog
|
|
<work-hour-dialog
|
|
|
v-if="workHourDialogVisible"
|
|
v-if="workHourDialogVisible"
|
|
|
|
|
+ :current-actual-work-hour="currentRow ? currentRow.actualWorkHour || 0 : 0"
|
|
|
:task-id="currentTaskId"
|
|
:task-id="currentTaskId"
|
|
|
|
|
+ :task-status="currentRow ? currentRow.taskStatus : ''"
|
|
|
:visible.sync="workHourDialogVisible"
|
|
:visible.sync="workHourDialogVisible"
|
|
|
@refresh="fetchData" />
|
|
@refresh="fetchData" />
|
|
|
|
|
|
|
@@ -540,6 +556,7 @@
|
|
|
{ key: 'estimateWorkHour', label: '预估工时' },
|
|
{ key: 'estimateWorkHour', label: '预估工时' },
|
|
|
{ key: 'actualWorkHour', label: '实际工时' },
|
|
{ key: 'actualWorkHour', label: '实际工时' },
|
|
|
{ key: 'defectType', label: '缺陷类型' },
|
|
{ key: 'defectType', label: '缺陷类型' },
|
|
|
|
|
+ { key: 'attribute2', label: '历史遗留' },
|
|
|
{ key: 'releaseVersion', label: '发布版本' },
|
|
{ key: 'releaseVersion', label: '发布版本' },
|
|
|
{ key: 'projectName', label: '项目名称' },
|
|
{ key: 'projectName', label: '项目名称' },
|
|
|
{ key: 'createdTime', label: '创建时间' },
|
|
{ key: 'createdTime', label: '创建时间' },
|
|
@@ -614,6 +631,8 @@
|
|
|
isOpeningFailTask: false, // 标记是否是从不通过按钮打开的流程
|
|
isOpeningFailTask: false, // 标记是否是从不通过按钮打开的流程
|
|
|
failTaskRow: null, // 保存不通过时的任务行数据
|
|
failTaskRow: null, // 保存不通过时的任务行数据
|
|
|
testResult: '', // 测试结果:pass/fail
|
|
testResult: '', // 测试结果:pass/fail
|
|
|
|
|
+ pendingBugParentTaskId: null, // 待更新attribute1的父测试任务ID
|
|
|
|
|
+ editDialogOpenedForBug: false, // 编辑弹窗是否是为BUG登记打开的
|
|
|
// 项目信息弹窗
|
|
// 项目信息弹窗
|
|
|
projectInfoDialogVisible: false,
|
|
projectInfoDialogVisible: false,
|
|
|
selectedProjectId: '',
|
|
selectedProjectId: '',
|
|
@@ -662,6 +681,15 @@
|
|
|
return this.projects.find((project) => project.id === this.selectedProject) || null
|
|
return this.projects.find((project) => project.id === this.selectedProject) || null
|
|
|
},
|
|
},
|
|
|
},
|
|
},
|
|
|
|
|
+ watch: {
|
|
|
|
|
+ editDialogVisible(val) {
|
|
|
|
|
+ // BUG登记弹窗关闭时(取消未保存),清理pending状态
|
|
|
|
|
+ if (!val && this.editDialogOpenedForBug) {
|
|
|
|
|
+ this.pendingBugParentTaskId = null
|
|
|
|
|
+ this.editDialogOpenedForBug = false
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ },
|
|
|
mounted() {
|
|
mounted() {
|
|
|
this.initVisibleColumns()
|
|
this.initVisibleColumns()
|
|
|
this.getOptions()
|
|
this.getOptions()
|
|
@@ -956,6 +984,8 @@
|
|
|
getRowActions(row) {
|
|
getRowActions(row) {
|
|
|
const status = String(row.taskStatus)
|
|
const status = String(row.taskStatus)
|
|
|
const taskType = String(row.taskType)
|
|
const taskType = String(row.taskType)
|
|
|
|
|
+ // 支持工时登记的任务类型:20功能开发 25缺陷修复 30功能测试 35BUG
|
|
|
|
|
+ const ALLOW_WORK_HOUR_TYPES = ['20', '25', '30', '35']
|
|
|
const actionMap = {
|
|
const actionMap = {
|
|
|
10: [{ key: 'schedule', label: '排期' }],
|
|
10: [{ key: 'schedule', label: '排期' }],
|
|
|
20: [
|
|
20: [
|
|
@@ -965,7 +995,8 @@
|
|
|
{ key: 'fail', label: '不通过', tone: 'warning' },
|
|
{ key: 'fail', label: '不通过', tone: 'warning' },
|
|
|
]
|
|
]
|
|
|
: [{ key: 'complete', label: '完成' }]),
|
|
: [{ key: 'complete', label: '完成' }]),
|
|
|
- { key: 'workHour', label: '工时' },
|
|
|
|
|
|
|
+ // 只对支持工时登记的任务类型显示工时按钮
|
|
|
|
|
+ ...(ALLOW_WORK_HOUR_TYPES.includes(taskType) ? [{ key: 'workHour', label: '工时' }] : []),
|
|
|
{ key: 'pause', label: '暂停' },
|
|
{ key: 'pause', label: '暂停' },
|
|
|
{ key: 'block', label: '阻塞', tone: 'warning' },
|
|
{ key: 'block', label: '阻塞', tone: 'warning' },
|
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
@@ -975,9 +1006,12 @@
|
|
|
{ key: 'block', label: '阻塞', tone: 'warning' },
|
|
{ key: 'block', label: '阻塞', tone: 'warning' },
|
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
|
],
|
|
],
|
|
|
|
|
+ 30: [
|
|
|
|
|
+ // 功能测试已完成且未登记BUG,显示BUG按钮
|
|
|
|
|
+ ...(taskType === '30' && String(row.attribute1) !== '10' ? [{ key: 'bug', label: 'BUG' }] : []),
|
|
|
|
|
+ ],
|
|
|
70: [
|
|
70: [
|
|
|
{ key: 'start', label: '开始' },
|
|
{ key: 'start', label: '开始' },
|
|
|
- { key: 'pause', label: '暂停' },
|
|
|
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
{ key: 'cancel', label: '作废', tone: 'danger' },
|
|
|
],
|
|
],
|
|
|
}
|
|
}
|
|
@@ -1045,6 +1079,8 @@
|
|
|
estimateWorkHour: pick('estimateWorkHour', 'estimate_work_hour'),
|
|
estimateWorkHour: pick('estimateWorkHour', 'estimate_work_hour'),
|
|
|
actualWorkHour: pick('actualWorkHour', 'actual_work_hour'),
|
|
actualWorkHour: pick('actualWorkHour', 'actual_work_hour'),
|
|
|
defectType: pick('defectType', 'defect_type'),
|
|
defectType: pick('defectType', 'defect_type'),
|
|
|
|
|
+ attribute1: pick('attribute1'),
|
|
|
|
|
+ attribute2: pick('attribute2'),
|
|
|
releaseVersion: pick('releaseVersion', 'release_version'),
|
|
releaseVersion: pick('releaseVersion', 'release_version'),
|
|
|
projectName: pick('projectName', 'project_name'),
|
|
projectName: pick('projectName', 'project_name'),
|
|
|
createdName: pick('createdName', 'created_name'),
|
|
createdName: pick('createdName', 'created_name'),
|
|
@@ -1060,6 +1096,7 @@
|
|
|
schedule: this.handleSchedule,
|
|
schedule: this.handleSchedule,
|
|
|
complete: this.handleComplete,
|
|
complete: this.handleComplete,
|
|
|
workHour: this.handleWorkHour,
|
|
workHour: this.handleWorkHour,
|
|
|
|
|
+ bug: this.handleBug,
|
|
|
pass: () => {
|
|
pass: () => {
|
|
|
this.handleComplete(row, 'pass')
|
|
this.handleComplete(row, 'pass')
|
|
|
}, // 通过按钮传参数
|
|
}, // 通过按钮传参数
|
|
@@ -1086,7 +1123,7 @@
|
|
|
// 点击行显示详情(支持编辑)
|
|
// 点击行显示详情(支持编辑)
|
|
|
handleRowClick(row) {
|
|
handleRowClick(row) {
|
|
|
this.detailData = this.normalizeTaskDetail(row)
|
|
this.detailData = this.normalizeTaskDetail(row)
|
|
|
- this.detailDialogMode = 'edit'
|
|
|
|
|
|
|
+ this.detailDialogMode = ['30', '90'].includes(String(row.taskStatus)) ? 'view' : 'edit'
|
|
|
this.detailDialogVisible = true
|
|
this.detailDialogVisible = true
|
|
|
},
|
|
},
|
|
|
// 查看发布版本关联任务详情
|
|
// 查看发布版本关联任务详情
|
|
@@ -1107,10 +1144,79 @@
|
|
|
this.editData = null
|
|
this.editData = null
|
|
|
this.editDialogVisible = true
|
|
this.editDialogVisible = true
|
|
|
},
|
|
},
|
|
|
|
|
+ // BUG登记弹窗保存成功后,刷新列表并更新父测试任务attribute1
|
|
|
|
|
+ handleEditDialogRefresh() {
|
|
|
|
|
+ this.fetchData()
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ if (this.pendingBugParentTaskId && this.editDialogOpenedForBug) {
|
|
|
|
|
+ this.updateTestTaskAttribute1(this.pendingBugParentTaskId)
|
|
|
|
|
+ this.pendingBugParentTaskId = null
|
|
|
|
|
+ this.editDialogOpenedForBug = false
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 通过当前任务ID逐级查找父父功能开发任务的负责人
|
|
|
|
|
+ async fetchParentTaskOwner(currentTaskId) {
|
|
|
|
|
+ if (!currentTaskId) return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1)取当前任务完整详情(确保拿到 taskParentId)
|
|
|
|
|
+ const curRes = await opsEventTaskApi.getById(currentTaskId)
|
|
|
|
|
+ if (curRes.code !== 200 || !curRes.data) return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ // 响应格式为 { code, data: { data: { ...任务数据... } } }
|
|
|
|
|
+ const taskDetail = curRes.data && curRes.data.data ? curRes.data.data : curRes.data
|
|
|
|
|
+ const firstPid = taskDetail.taskParentId || taskDetail.task_parent_id
|
|
|
|
|
+ if (!firstPid) return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ // 2)取父任务
|
|
|
|
|
+ const parentRes = await opsEventTaskApi.getById(firstPid)
|
|
|
|
|
+ if (parentRes.code !== 200 || !parentRes.data) return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ const parentDetail = parentRes.data && parentRes.data.data ? parentRes.data.data : parentRes.data
|
|
|
|
|
+ const secondPid = parentDetail.taskParentId || parentDetail.task_parent_id
|
|
|
|
|
+ if (!secondPid) return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ // 3)取祖父任务(功能开发任务)的负责人
|
|
|
|
|
+ const grandRes = await opsEventTaskApi.getById(secondPid)
|
|
|
|
|
+ if (grandRes.code === 200 && grandRes.data) {
|
|
|
|
|
+ const grandDetail = grandRes.data && grandRes.data.data ? grandRes.data.data : grandRes.data
|
|
|
|
|
+ return {
|
|
|
|
|
+ opsUserId: grandDetail.opsUserId || grandDetail.ops_user_id || null,
|
|
|
|
|
+ opsUserName: grandDetail.opsUserName || grandDetail.ops_user_name || '',
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('获取父任务负责人失败:', error)
|
|
|
|
|
+ }
|
|
|
|
|
+ return { opsUserId: null, opsUserName: '' }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 从操作栏直接打开BUG登记
|
|
|
|
|
+ async handleBug(row) {
|
|
|
|
|
+ this.pendingBugParentTaskId = row.id
|
|
|
|
|
+ this.editDialogOpenedForBug = true
|
|
|
|
|
+ // 两层查找获取功能开发任务的负责人(当前→父测试→父功能开发)
|
|
|
|
|
+ const owner = await this.fetchParentTaskOwner(row.id)
|
|
|
|
|
+ this.editData = {
|
|
|
|
|
+ taskParentId: row.id,
|
|
|
|
|
+ projectId: row.projectId,
|
|
|
|
|
+ taskTitle: row.taskTitle || '',
|
|
|
|
|
+ functionName: row.functionName || '',
|
|
|
|
|
+ taskType: '35',
|
|
|
|
|
+ isBugTask: true,
|
|
|
|
|
+ opsUserId: owner.opsUserId ? parseInt(owner.opsUserId) : null,
|
|
|
|
|
+ opsUserName: owner.opsUserName,
|
|
|
|
|
+ }
|
|
|
|
|
+ this.editDialogVisible = true
|
|
|
|
|
+ },
|
|
|
|
|
+ // 更新测试任务的attribute1为10(标记已登记BUG)
|
|
|
|
|
+ async updateTestTaskAttribute1(taskId) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ await opsEventTaskApi.update({ id: taskId, attribute1: '10' })
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('更新测试任务attribute1失败:', error)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
// 测试不通过:先完成当前任务,再创建新的缺陷任务
|
|
// 测试不通过:先完成当前任务,再创建新的缺陷任务
|
|
|
handleFail(row) {
|
|
handleFail(row) {
|
|
|
this.isOpeningFailTask = true
|
|
this.isOpeningFailTask = true
|
|
|
this.failTaskRow = row
|
|
this.failTaskRow = row
|
|
|
|
|
+ this.pendingBugParentTaskId = row.id // 记录待更新attribute1的父任务
|
|
|
// Add testResult to currentRow
|
|
// Add testResult to currentRow
|
|
|
this.currentRow = { ...row, testResult: 'fail' }
|
|
this.currentRow = { ...row, testResult: 'fail' }
|
|
|
this.currentTaskId = row.id
|
|
this.currentTaskId = row.id
|
|
@@ -1118,17 +1224,24 @@
|
|
|
this.completeDialogVisible = true
|
|
this.completeDialogVisible = true
|
|
|
},
|
|
},
|
|
|
// 完成任务成功后,打开新增缺陷任务弹窗
|
|
// 完成任务成功后,打开新增缺陷任务弹窗
|
|
|
- handleCompleteSuccess() {
|
|
|
|
|
|
|
+ async handleCompleteSuccess() {
|
|
|
this.testResult = '' // 重置测试结果
|
|
this.testResult = '' // 重置测试结果
|
|
|
if (this.isOpeningFailTask && this.failTaskRow) {
|
|
if (this.isOpeningFailTask && this.failTaskRow) {
|
|
|
|
|
+ // 两层查找获取功能开发任务的负责人(当前→父测试→父功能开发)
|
|
|
|
|
+ const owner = await this.fetchParentTaskOwner(this.failTaskRow.id)
|
|
|
this.editData = {
|
|
this.editData = {
|
|
|
taskParentId: this.failTaskRow.id,
|
|
taskParentId: this.failTaskRow.id,
|
|
|
projectId: this.failTaskRow.projectId,
|
|
projectId: this.failTaskRow.projectId,
|
|
|
|
|
+ taskTitle: this.failTaskRow.taskTitle || '',
|
|
|
|
|
+ functionName: this.failTaskRow.functionName || '',
|
|
|
taskType: '35', // 默认是BUG类型
|
|
taskType: '35', // 默认是BUG类型
|
|
|
isBugTask: true, // 标记这是从不通过按钮创建的BUG任务,用于禁用任务类型选择
|
|
isBugTask: true, // 标记这是从不通过按钮创建的BUG任务,用于禁用任务类型选择
|
|
|
|
|
+ opsUserId: owner.opsUserId ? parseInt(owner.opsUserId) : null,
|
|
|
|
|
+ opsUserName: owner.opsUserName,
|
|
|
}
|
|
}
|
|
|
this.isOpeningFailTask = false
|
|
this.isOpeningFailTask = false
|
|
|
this.failTaskRow = null
|
|
this.failTaskRow = null
|
|
|
|
|
+ this.editDialogOpenedForBug = true // 标记为BUG登记
|
|
|
this.editDialogVisible = true
|
|
this.editDialogVisible = true
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
@@ -1161,7 +1274,7 @@
|
|
|
this.testResult = testResult
|
|
this.testResult = testResult
|
|
|
|
|
|
|
|
// 系统发版任务使用专门的完成弹窗
|
|
// 系统发版任务使用专门的完成弹窗
|
|
|
- if (String(row.taskType) === '40') {
|
|
|
|
|
|
|
+ if (String(row.taskType) === '38') {
|
|
|
this.releaseCompleteDialogVisible = true
|
|
this.releaseCompleteDialogVisible = true
|
|
|
} else {
|
|
} else {
|
|
|
this.completeDialogVisible = true
|
|
this.completeDialogVisible = true
|
|
@@ -1239,6 +1352,18 @@
|
|
|
this.selectedProjectId = project.id
|
|
this.selectedProjectId = project.id
|
|
|
this.projectInfoDialogVisible = true
|
|
this.projectInfoDialogVisible = true
|
|
|
},
|
|
},
|
|
|
|
|
+ // 复制文本到剪贴板
|
|
|
|
|
+ handleCopy(text) {
|
|
|
|
|
+ if (!text) return
|
|
|
|
|
+ navigator.clipboard
|
|
|
|
|
+ .writeText(text)
|
|
|
|
|
+ .then(() => {
|
|
|
|
|
+ this.$message.success('已复制: ' + text)
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch(() => {
|
|
|
|
|
+ this.$message.error('复制失败')
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
},
|
|
},
|
|
|
}
|
|
}
|
|
|
</script>
|
|
</script>
|
|
@@ -1916,4 +2041,23 @@
|
|
|
padding: 0;
|
|
padding: 0;
|
|
|
line-height: 32px;
|
|
line-height: 32px;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ .cell-with-copy {
|
|
|
|
|
+ display: inline-flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ gap: 4px;
|
|
|
|
|
+ max-width: 100%;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .copy-btn {
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ color: #c0c4cc;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ transition: color 0.2s;
|
|
|
|
|
+
|
|
|
|
|
+ &:hover {
|
|
|
|
|
+ color: #409eff;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
</style>
|
|
</style>
|