Compare commits
2 Commits
a712e3f85f
...
b91fe3b05a
Author | SHA1 | Date |
---|---|---|
![]() |
b91fe3b05a | 1 month ago |
![]() |
75572f6104 | 1 month ago |
@ -0,0 +1,236 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="flex items-center justify-between"> |
||||||
|
<el-row> |
||||||
|
<el-popover placement="bottom" width="500px" trigger="click" @show="handleSearchPeroid"> |
||||||
|
<template #reference> |
||||||
|
<div class="flex items-center border-1px w-300px h-32px p-10px peroid-select"> |
||||||
|
<Icon icon="ep:calendar" style="color: #aaa" /> |
||||||
|
<span class="text-14px ml-10px" style="color: #aaa"> |
||||||
|
{{ searchForm.peroidName ? searchForm.peroidName : '选择周期' }} |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<div> |
||||||
|
<div class="mt-10px" style="height: 400px"> |
||||||
|
<el-table :data="peroidList" @row-click="handleSelectPeroid"> |
||||||
|
<el-table-column label="节点名称"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-radio v-model="searchForm.peroidId" :label="row.id">{{ |
||||||
|
row.name |
||||||
|
}}</el-radio> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="开始日期" prop="startDate" width="120" /> |
||||||
|
<el-table-column label="截止日期" prop="endDate" width="120" /> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-popover> |
||||||
|
<el-button class="ml-10px" type="primary" @click="handleAddNode">新建节点</el-button> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-button type="warning" @click="handleEditOkr(searchForm.peroidId)"> |
||||||
|
修改当前节点 |
||||||
|
</el-button> |
||||||
|
<el-button type="success" @click="handleUpdateProcess">更新进度</el-button> |
||||||
|
</el-row> |
||||||
|
</div> |
||||||
|
|
||||||
|
<OkrTable ref="okrTableRef" @row-click="handleShowOkr" /> |
||||||
|
<DialogOkr ref="dialogOkr" @edit="handleEditOkr" /> |
||||||
|
<DialogOkrInfo ref="dialogOkrInfo" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="AllTarget"> |
||||||
|
import OkrTable from './OkrTable.vue' |
||||||
|
import DialogOkrInfo from './DialogOkrInfo.vue' |
||||||
|
import DialogOkr from './DialogOkr.vue' |
||||||
|
|
||||||
|
const message = useMessage() |
||||||
|
|
||||||
|
const okrTableRef = ref(null) |
||||||
|
const searchForm = ref({ |
||||||
|
peroidName: '', |
||||||
|
peroidId: null |
||||||
|
}) |
||||||
|
|
||||||
|
const peroidList = ref([]) |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
handleSearchPeroid() |
||||||
|
if (!searchForm.value.peroidId && peroidList.value.length) { |
||||||
|
searchForm.value.peroidId = peroidList.value[0].id |
||||||
|
searchForm.value.peroidName = peroidList.value[0].name |
||||||
|
} |
||||||
|
getOkrList() |
||||||
|
}) |
||||||
|
|
||||||
|
async function handleSearchPeroid() { |
||||||
|
peroidList.value = [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '2025年寻驾okr', |
||||||
|
startDate: '2022-01-01', |
||||||
|
endDate: '2022-01-31' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: '2024年寻驾okr', |
||||||
|
startDate: '2022-02-01', |
||||||
|
endDate: '2022-02-28' |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
|
||||||
|
function handleSelectPeroid(row) { |
||||||
|
searchForm.value.peroidName = row.name |
||||||
|
searchForm.value.peroidId = row.id |
||||||
|
handleSearchOkr() |
||||||
|
} |
||||||
|
|
||||||
|
function handleSearchOkr() { |
||||||
|
console.log(searchForm.value) |
||||||
|
} |
||||||
|
|
||||||
|
async function getOkrList() { |
||||||
|
const list = [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '销售成交额达到1000万,总体成交率15%', |
||||||
|
process: 60, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 11, |
||||||
|
type: 'keyresult', |
||||||
|
channelName: '抖音', |
||||||
|
target: '线索目标', |
||||||
|
targetType: 'value', |
||||||
|
isSystem: true, |
||||||
|
targetNum: 10000, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 5000, |
||||||
|
currentValue: false, |
||||||
|
process: 60, |
||||||
|
users: '张三、李四' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 12, |
||||||
|
type: 'keyresult', |
||||||
|
channelName: '抖音', |
||||||
|
target: '成交数', |
||||||
|
isSystem: true, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 2500, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 500, |
||||||
|
currentValue: false, |
||||||
|
process: 60, |
||||||
|
users: '张三、李四' |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: '运营消耗预算控制在20万以内,获得10万条线索', |
||||||
|
process: 80, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 21, |
||||||
|
type: 'keyresult', |
||||||
|
target: '本月抖音运营投入相较上月少10%', |
||||||
|
targetType: 'radio', |
||||||
|
isSystem: false, |
||||||
|
targetNum: 0, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 0, |
||||||
|
currentValue: false, |
||||||
|
process: 0, |
||||||
|
users: '' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 22, |
||||||
|
type: 'keyresult', |
||||||
|
target: '累计输出作品', |
||||||
|
process: 15, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 200, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 30, |
||||||
|
currentValue: false |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
name: '目标3', |
||||||
|
process: 40, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 31, |
||||||
|
type: 'keyresult', |
||||||
|
target: '关键成果1', |
||||||
|
process: 100, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'radio', |
||||||
|
targetNum: 0, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 0, |
||||||
|
currentValue: true |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 22, |
||||||
|
type: 'keyresult', |
||||||
|
target: '关键成果2', |
||||||
|
process: 15, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 200, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 30, |
||||||
|
currentValue: false |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
nextTick(() => { |
||||||
|
okrTableRef.value.prepareData(list) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const dialogOkrInfo = ref(null) |
||||||
|
function handleAddNode() { |
||||||
|
dialogOkrInfo.value.open('create', null) |
||||||
|
} |
||||||
|
|
||||||
|
function handleEditOkr() { |
||||||
|
dialogOkr.value.close() |
||||||
|
dialogOkrInfo.value.open('update', 1) |
||||||
|
} |
||||||
|
|
||||||
|
function handleUpdateProcess() { |
||||||
|
message.success('更新进度成功') |
||||||
|
getOkrList() |
||||||
|
} |
||||||
|
|
||||||
|
const dialogOkr = ref(null) |
||||||
|
function handleShowOkr(row) { |
||||||
|
dialogOkr.value.open(row.id) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
:deep(.el-overlay-dialog) { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,236 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<div class="flex items-center justify-between"> |
||||||
|
<el-row> |
||||||
|
<el-popover placement="bottom" width="500px" trigger="click" @show="handleSearchPeroid"> |
||||||
|
<template #reference> |
||||||
|
<div class="flex items-center border-1px w-300px h-32px p-10px peroid-select"> |
||||||
|
<Icon icon="ep:calendar" style="color: #aaa" /> |
||||||
|
<span class="text-14px ml-10px" style="color: #aaa"> |
||||||
|
{{ searchForm.peroidName ? searchForm.peroidName : '选择周期' }} |
||||||
|
</span> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
<div> |
||||||
|
<div class="mt-10px" style="height: 400px"> |
||||||
|
<el-table :data="peroidList" @row-click="handleSelectPeroid"> |
||||||
|
<el-table-column label="节点名称"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-radio v-model="searchForm.peroidId" :label="row.id">{{ |
||||||
|
row.name |
||||||
|
}}</el-radio> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column label="开始日期" prop="startDate" width="120" /> |
||||||
|
<el-table-column label="截止日期" prop="endDate" width="120" /> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</el-popover> |
||||||
|
<el-button class="ml-10px" type="primary" @click="handleAddNode">新建节点</el-button> |
||||||
|
</el-row> |
||||||
|
<el-row> |
||||||
|
<el-button type="warning" @click="handleEditOkr(searchForm.peroidId)"> |
||||||
|
修改当前节点 |
||||||
|
</el-button> |
||||||
|
<el-button type="success" @click="handleUpdateProcess">更新进度</el-button> |
||||||
|
</el-row> |
||||||
|
</div> |
||||||
|
|
||||||
|
<OkrTable ref="okrTableRef" @row-click="handleShowOkr" /> |
||||||
|
<DialogOkr ref="dialogOkr" @edit="handleEditOkr" /> |
||||||
|
<DialogOkrInfo ref="dialogOkrInfo" /> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="MyDuty"> |
||||||
|
import OkrTable from './OkrTable.vue' |
||||||
|
import DialogOkrInfo from './DialogOkrInfo.vue' |
||||||
|
import DialogOkr from './DialogOkr.vue' |
||||||
|
|
||||||
|
const message = useMessage() |
||||||
|
|
||||||
|
const okrTableRef = ref(null) |
||||||
|
const searchForm = ref({ |
||||||
|
peroidName: '', |
||||||
|
peroidId: null |
||||||
|
}) |
||||||
|
|
||||||
|
const peroidList = ref([]) |
||||||
|
|
||||||
|
onMounted(() => { |
||||||
|
handleSearchPeroid() |
||||||
|
if (!searchForm.value.peroidId && peroidList.value.length) { |
||||||
|
searchForm.value.peroidId = peroidList.value[0].id |
||||||
|
searchForm.value.peroidName = peroidList.value[0].name |
||||||
|
} |
||||||
|
getOkrList() |
||||||
|
}) |
||||||
|
|
||||||
|
async function handleSearchPeroid() { |
||||||
|
peroidList.value = [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '2025年寻驾okr', |
||||||
|
startDate: '2022-01-01', |
||||||
|
endDate: '2022-01-31' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: '2024年寻驾okr', |
||||||
|
startDate: '2022-02-01', |
||||||
|
endDate: '2022-02-28' |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
|
||||||
|
function handleSelectPeroid(row) { |
||||||
|
searchForm.value.peroidName = row.name |
||||||
|
searchForm.value.peroidId = row.id |
||||||
|
handleSearchOkr() |
||||||
|
} |
||||||
|
|
||||||
|
function handleSearchOkr() { |
||||||
|
console.log(searchForm.value) |
||||||
|
} |
||||||
|
|
||||||
|
async function getOkrList() { |
||||||
|
const list = [ |
||||||
|
{ |
||||||
|
id: 1, |
||||||
|
name: '销售成交额达到1000万,总体成交率15%', |
||||||
|
process: 60, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 11, |
||||||
|
type: 'keyresult', |
||||||
|
channelName: '抖音', |
||||||
|
target: '线索目标', |
||||||
|
targetType: 'value', |
||||||
|
isSystem: true, |
||||||
|
targetNum: 10000, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 5000, |
||||||
|
currentValue: false, |
||||||
|
process: 60, |
||||||
|
users: '张三、李四' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 12, |
||||||
|
type: 'keyresult', |
||||||
|
channelName: '抖音', |
||||||
|
target: '成交数', |
||||||
|
isSystem: true, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 2500, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 500, |
||||||
|
currentValue: false, |
||||||
|
process: 60, |
||||||
|
users: '张三、李四' |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 2, |
||||||
|
name: '运营消耗预算控制在20万以内,获得10万条线索', |
||||||
|
process: 80, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 21, |
||||||
|
type: 'keyresult', |
||||||
|
target: '本月抖音运营投入相较上月少10%', |
||||||
|
targetType: 'radio', |
||||||
|
isSystem: false, |
||||||
|
targetNum: 0, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 0, |
||||||
|
currentValue: false, |
||||||
|
process: 0, |
||||||
|
users: '' |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 22, |
||||||
|
type: 'keyresult', |
||||||
|
target: '累计输出作品', |
||||||
|
process: 15, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 200, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 30, |
||||||
|
currentValue: false |
||||||
|
} |
||||||
|
] |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 3, |
||||||
|
name: '目标3', |
||||||
|
process: 40, |
||||||
|
type: 'object', |
||||||
|
children: [ |
||||||
|
{ |
||||||
|
id: 31, |
||||||
|
type: 'keyresult', |
||||||
|
target: '关键成果1', |
||||||
|
process: 100, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'radio', |
||||||
|
targetNum: 0, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 0, |
||||||
|
currentValue: true |
||||||
|
}, |
||||||
|
{ |
||||||
|
id: 22, |
||||||
|
type: 'keyresult', |
||||||
|
target: '关键成果2', |
||||||
|
process: 15, |
||||||
|
users: '', |
||||||
|
isSystem: false, |
||||||
|
targetType: 'value', |
||||||
|
targetNum: 200, |
||||||
|
targetValue: false, |
||||||
|
currentNum: 30, |
||||||
|
currentValue: false |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
] |
||||||
|
nextTick(() => { |
||||||
|
okrTableRef.value.prepareData(list) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
const dialogOkrInfo = ref(null) |
||||||
|
function handleAddNode() { |
||||||
|
dialogOkrInfo.value.open('create', null) |
||||||
|
} |
||||||
|
|
||||||
|
function handleEditOkr() { |
||||||
|
dialogOkr.value.close() |
||||||
|
dialogOkrInfo.value.open('update', 1) |
||||||
|
} |
||||||
|
|
||||||
|
function handleUpdateProcess() { |
||||||
|
message.success('更新进度成功') |
||||||
|
getOkrList() |
||||||
|
} |
||||||
|
|
||||||
|
const dialogOkr = ref(null) |
||||||
|
function handleShowOkr(row) { |
||||||
|
dialogOkr.value.open(row.id) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
:deep(.el-overlay-dialog) { |
||||||
|
display: flex; |
||||||
|
justify-content: center; |
||||||
|
align-items: center; |
||||||
|
} |
||||||
|
</style> |
@ -0,0 +1,127 @@ |
|||||||
|
<template> |
||||||
|
<div> |
||||||
|
<el-table |
||||||
|
ref="tableRef" |
||||||
|
:data="okrList" |
||||||
|
default-expand-all |
||||||
|
row-key="id" |
||||||
|
size="large" |
||||||
|
@row-click="handleRowClick" |
||||||
|
@expand-change="handleExpand" |
||||||
|
> |
||||||
|
<el-table-column label="目标/关键成果"> |
||||||
|
<template #default="{ row, $index }"> |
||||||
|
<span |
||||||
|
v-if="!expandedRows[row.id]" |
||||||
|
class="line1" |
||||||
|
:style="{ |
||||||
|
top: row.type == 'object' ? '30px' : 0, |
||||||
|
height: getHeight(row, $index) |
||||||
|
}" |
||||||
|
></span> |
||||||
|
<span v-if="row.type === 'object'">【目标】{{ row.name }}</span> |
||||||
|
<template v-else> |
||||||
|
<span class="line2"></span> |
||||||
|
<span> |
||||||
|
【关键成果】{{ row.channelName }} {{ row.target }} |
||||||
|
<span v-if="row.targetType == 'value'">{{ row.targetNum }}</span> |
||||||
|
</span> |
||||||
|
<div class="flex items-center mt-10px ml-50px"> |
||||||
|
<span>当前进度:</span> |
||||||
|
<span v-if="row.isSystem">{{ row.currentNum }}</span> |
||||||
|
<el-input |
||||||
|
v-else-if="row.targetType == 'value'" |
||||||
|
v-model="row.currentNum" |
||||||
|
clearable |
||||||
|
size="small" |
||||||
|
style="width: 200px" |
||||||
|
/> |
||||||
|
<el-radio-group |
||||||
|
v-else-if="row.targetType == 'radio'" |
||||||
|
v-model="row.currentValue" |
||||||
|
size="small" |
||||||
|
> |
||||||
|
<el-radio :label="true">是</el-radio> |
||||||
|
<el-radio :label="false">否</el-radio> |
||||||
|
</el-radio-group> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="process" label="进度" width="200px"> |
||||||
|
<template #default="{ row }"> |
||||||
|
<el-progress :percentage="row.process" /> |
||||||
|
</template> |
||||||
|
</el-table-column> |
||||||
|
<el-table-column prop="users" label="执行人" width="200px" /> |
||||||
|
</el-table> |
||||||
|
</div> |
||||||
|
</template> |
||||||
|
|
||||||
|
<script setup name="OkrTable"> |
||||||
|
const emit = defineEmits(['rowClick']) |
||||||
|
|
||||||
|
const okrList = ref([]) |
||||||
|
const helpList = ref([]) |
||||||
|
|
||||||
|
function prepareData(list) { |
||||||
|
okrList.value = list |
||||||
|
helpList.value = [] |
||||||
|
okrList.value.map((item) => { |
||||||
|
helpList.value.push(item) |
||||||
|
item.children.map((child) => { |
||||||
|
helpList.value.push(child) |
||||||
|
}) |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
defineExpose({ |
||||||
|
prepareData |
||||||
|
}) |
||||||
|
|
||||||
|
function getHeight(row, index) { |
||||||
|
if (helpList.value.length - 1 == index || helpList.value[index + 1].type == 'object') { |
||||||
|
return '22px' |
||||||
|
} else { |
||||||
|
return '100%' |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
const expandedRows = ref({}) |
||||||
|
function handleExpand(row, expanded) { |
||||||
|
expandedRows.value[row.id] = !expanded |
||||||
|
} |
||||||
|
|
||||||
|
function handleRowClick(row) { |
||||||
|
emit('rowClick', row) |
||||||
|
} |
||||||
|
</script> |
||||||
|
|
||||||
|
<style lang="scss" scoped> |
||||||
|
.line1 { |
||||||
|
position: absolute; |
||||||
|
width: 1px; |
||||||
|
left: 21px; |
||||||
|
border-left: 1px dashed #ccc; |
||||||
|
} |
||||||
|
.line2 { |
||||||
|
position: absolute; |
||||||
|
width: 26px; |
||||||
|
height: 1px; |
||||||
|
left: 21px; |
||||||
|
top: 22px; |
||||||
|
border-bottom: 1px dashed #ccc; |
||||||
|
&::after { |
||||||
|
position: absolute; |
||||||
|
left: 25px; |
||||||
|
top: -3px; |
||||||
|
display: block; |
||||||
|
width: 6px; |
||||||
|
height: 6px; |
||||||
|
border-radius: 6px; |
||||||
|
margin: 0 auto; |
||||||
|
border: 1px solid #ddd; |
||||||
|
content: ''; |
||||||
|
} |
||||||
|
} |
||||||
|
</style> |
Loading…
Reference in new issue