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