Compare commits
8 Commits
34a1fc56d3
...
a712e3f85f
Author | SHA1 | Date |
---|---|---|
![]() |
a712e3f85f | 2 months ago |
![]() |
a5a64b7131 | 2 months ago |
![]() |
b196135ddb | 3 months ago |
![]() |
34de068ffa | 3 months ago |
![]() |
b1feb33c00 | 3 months ago |
![]() |
853a18df9b | 4 months ago |
![]() |
288770adce | 4 months ago |
![]() |
7bb3a74095 | 4 months ago |
Before Width: | Height: | Size: 341 B |
Before Width: | Height: | Size: 357 B |
Before Width: | Height: | Size: 353 B |
Before Width: | Height: | Size: 350 B |
Before Width: | Height: | Size: 358 B |
Before Width: | Height: | Size: 355 B |
Before Width: | Height: | Size: 903 B |
Before Width: | Height: | Size: 958 B |
Before Width: | Height: | Size: 926 B |
Before Width: | Height: | Size: 926 B |
Before Width: | Height: | Size: 950 B |
Before Width: | Height: | Size: 970 B |
After Width: | Height: | Size: 309 KiB |
After Width: | Height: | Size: 192 KiB |
@ -0,0 +1,611 @@ |
||||
<template> |
||||
<el-dialog |
||||
v-if="show" |
||||
v-model="show" |
||||
width="94vw" |
||||
class="dialog-okr" |
||||
:show-close="false" |
||||
:close-on-click-modal="false" |
||||
> |
||||
<template #header> |
||||
<div class="dialog-okr-header"> |
||||
<div class="flex-1 flex items-center" style="line-height: 50px"> |
||||
<div class="dialog-okr-title"> |
||||
<Icon icon="ep:circle-check-filled" color="#30d1fc" :size="14" /> |
||||
<span>目标</span> |
||||
</div> |
||||
<el-divider direction="vertical" /> |
||||
<span class="text-14px ml-0.25">ork落地</span> |
||||
<div class="ml-20px text-14px"> |
||||
<span>【节点】</span> |
||||
<span>寻驾全年目标 -> 1月</span> |
||||
</div> |
||||
</div> |
||||
<div class="flex items-center"> |
||||
<el-button link @click="emit('edit')"> |
||||
<el-tooltip content="编辑" placement="top" effect="dark"> |
||||
<Icon icon="ep:edit" :size="16" /> |
||||
</el-tooltip> |
||||
</el-button> |
||||
|
||||
<el-button link @click="show = false"> |
||||
<el-tooltip content="关闭" placement="top" effect="dark"> |
||||
<Icon icon="ep:close" :size="16" /> |
||||
</el-tooltip> |
||||
</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<template #default> |
||||
<div class="dialog-okr-body"> |
||||
<div class="dialog-okr-content pr-10px"> |
||||
<div class="dialog-okr-content-detail"> |
||||
<div class="detail-basic-title"> |
||||
<div class="basic-title-item"> |
||||
<div class="basic-title-label">创建人</div> |
||||
<div class="basic-title-value">张三</div> |
||||
</div> |
||||
<div class="basic-title-item"> |
||||
<div class="basic-title-label">执行人</div> |
||||
<div class="basic-title-value">张三、李四</div> |
||||
</div> |
||||
<div class="basic-title-item"> |
||||
<div class="basic-title-label">目标数</div> |
||||
<div class="basic-title-value">3</div> |
||||
</div> |
||||
<div class="basic-title-item" style="min-width: 200px"> |
||||
<div class="basic-title-label">总体进度</div> |
||||
<el-progress :percentage="60" :stroke-width="8" /> |
||||
</div> |
||||
</div> |
||||
<div class="flex detail-basic-info"> |
||||
<span>开始日期:2025-01-01</span> |
||||
<span>截止日期:2025-01-31</span> |
||||
<span>最新更新时间:2025-01-15</span> |
||||
</div> |
||||
</div> |
||||
<div class="flex" style="position: relative; flex: 1; height: 100px"> |
||||
<el-tabs v-model="workIndex" style="flex: 1"> |
||||
<el-tab-pane label="目标/关键成果" name="okr"> |
||||
<div class="content-wrap"> |
||||
<el-table :data="okrList" default-expand-all row-key="id" size="large"> |
||||
<el-table-column label="目标/关键成果"> |
||||
<template #default="{ row }"> |
||||
<span v-if="row.type === 'object'">【目标】{{ row.name }}</span> |
||||
<template v-else> |
||||
<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> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
<el-button class="sav-btn" type="primary" @click="handleSaveProcess"> |
||||
保存并更新 |
||||
</el-button> |
||||
</div> |
||||
</div> |
||||
<div class="dialog-okr-side pl-10px"> |
||||
<el-tabs v-model="sideIndex" style="flex: 1; height: 100%"> |
||||
<el-tab-pane label="子节点" name="subNode"> |
||||
<div class="overflow-y-auto" style="height: calc(100% - 50px)"> |
||||
<div |
||||
v-for="index in 12" |
||||
:key="index" |
||||
class="border-b-1 child-item" |
||||
style="padding: 10px 5px; cursor: pointer" |
||||
@click="handleChildItem" |
||||
> |
||||
<div |
||||
class="flex justify-between items-center overflow-hidden text-16px" |
||||
style="line-height: 30px" |
||||
> |
||||
<div class="child-label">【节点】子节点{{ index }}</div> |
||||
<el-progress |
||||
type="line" |
||||
:percentage="0" |
||||
:stroke-width="6" |
||||
style="width: 120px" |
||||
/> |
||||
</div> |
||||
<div class="ml-10px flex items-center text-13px" style="line-height: 30px"> |
||||
<span>目标数:</span> |
||||
<span style="color: #aaa">4</span> |
||||
<el-divider direction="vertical" style="margin: 0 20px" /> |
||||
<div |
||||
class="flex-1 overflow-hidden h-30px" |
||||
style="text-overflow: ellipsis; white-space: nowrap" |
||||
> |
||||
<span>执行人:</span> |
||||
<span style="color: #aaa">张三、李四、王二</span> |
||||
</div> |
||||
</div> |
||||
<div |
||||
class="ml-10px flex items-center text-12px" |
||||
style="line-height: 20px; color: #aaa" |
||||
> |
||||
<span>开始日期:2025-01-01</span> |
||||
<el-divider direction="vertical" style="margin: 0 20px" /> |
||||
<span>截止日期:2025-01-31</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="评论" name="conclusion"> |
||||
<div class="relative overflow-y-auto" style="height: calc(100% - 50px)"> |
||||
<div class="flex justify-between items-center"> |
||||
<el-select |
||||
v-if="addNewComment" |
||||
v-model="form.commentType" |
||||
filterable |
||||
size="small" |
||||
style="width: 120px" |
||||
@change="getCommentTemplate" |
||||
> |
||||
<el-option label="总结" :value="1" /> |
||||
<el-option label="日报" :value="2" /> |
||||
<el-option label="周报" :value="3" /> |
||||
<el-option label="月报" :value="4" /> |
||||
<!-- <el-option label="评论" :value="5" disabled /> --> |
||||
</el-select> |
||||
|
||||
<div v-if="addNewComment"> |
||||
<el-button size="small" @click="addNewComment = false"> 取消 </el-button> |
||||
<el-button type="primary" size="small" @click="handleSaveComment"> |
||||
发布 |
||||
</el-button> |
||||
</div> |
||||
<el-button v-else type="primary" size="small" @click="handleInsertComment"> |
||||
新增评论 |
||||
</el-button> |
||||
</div> |
||||
<div class="mt-10px" v-if="addNewComment"> |
||||
<Editor |
||||
v-model:modelValue="form.commentValue" |
||||
height="300px" |
||||
:toolbarConfig="toolbarConfig" |
||||
/> |
||||
</div> |
||||
<div v-for="index in 12" :key="index" class="border-b-1" style="padding: 10px 5px"> |
||||
<div |
||||
class="flex items-center justify-between overflow-hidden text-16px" |
||||
style="line-height: 30px" |
||||
> |
||||
<div class="flex items-center"> |
||||
<el-avatar |
||||
shape="circle" |
||||
style=" |
||||
background-color: var(--el-color-primary-light-3); |
||||
width: 30px; |
||||
height: 30px; |
||||
" |
||||
fit="fill" |
||||
> |
||||
<span class="text-12px">门庆</span> |
||||
</el-avatar> |
||||
<div class="ml-10px text-16px">西门庆</div> |
||||
</div> |
||||
<div class="ml-10px text-13px text-gray-400">01-01 12:15</div> |
||||
</div> |
||||
<div class="ml-10px" v-dompurify-html="commentListVal"></div> |
||||
<div |
||||
class="ml-10px mt-10px flex items-center text-12px" |
||||
style="line-height: 20px; color: #aaa" |
||||
> |
||||
<div class="flex items-center mr-50px"> |
||||
<el-button link @click="good(index)"> |
||||
<Icon icon="fa:thumbs-o-up" :size="16" /> |
||||
</el-button> |
||||
<span class="ml-5px">6</span> |
||||
</div> |
||||
<div class="flex items-center mr-50px"> |
||||
<el-button link @click="showComment(index)"> |
||||
<Icon icon="ep:chat-dot-square" :size="16" /> |
||||
</el-button> |
||||
<span class="ml-5px">1</span> |
||||
</div> |
||||
</div> |
||||
<!-- 评论 --> |
||||
<div |
||||
v-if="showCommentIndex == index" |
||||
class="bg-gray-100 pl-10px pr-10px pt-5px pb-5px" |
||||
style="margin: 10px 10px 0 10px; border-radius: 4px" |
||||
label="评论" |
||||
> |
||||
<div class="text-14px" style="line-height: 24px"> |
||||
<span class="font-bold">武大郎:</span> |
||||
<span> |
||||
大官人,你要脆饼不要,卖完最后一个我要回家了,我家婆娘熬了鸡汤给我补身子 |
||||
</span> |
||||
</div> |
||||
<div class="text-14px" style="line-height: 24px"> |
||||
<span class="font-bold">潘金莲:</span> |
||||
<span>西门大官人,我要给你生猴子❥(^_-)</span> |
||||
</div> |
||||
<div class="text-14px" style="line-height: 24px"> |
||||
<span class="font-bold">武二郎:</span> |
||||
<span>如同天上降魔主,真乃人间太岁</span> |
||||
</div> |
||||
<div class="mt-10px relative"> |
||||
<el-input |
||||
v-model="form.commentValue" |
||||
placeholder="请输入评论" |
||||
type="textarea" |
||||
:autosize="{ minRows: 4 }" |
||||
clearable |
||||
size="small" |
||||
style="width: 100%" |
||||
/> |
||||
<el-button |
||||
type="primary" |
||||
size="small" |
||||
style="position: absolute; right: 2px; bottom: 2px" |
||||
@click="handleSendCommnet" |
||||
> |
||||
发布 |
||||
</el-button> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="进度历史" name="history"> |
||||
<div class="overflow-y-auto pl-15px" style="height: calc(100% - 50px)"> |
||||
<el-timeline class="ml-10px"> |
||||
<el-timeline-item placement="bottom" timestamp="2025-01-20" color="#30d1fc"> |
||||
<div>张三</div> |
||||
<div class="mt-10px text-14px" style="line-height: 24px; color: #666"> |
||||
进度变化:40% -> 60% |
||||
(节点进度是读取目标进度计算的,目标进度根据关键成果计算,关键成果在提交跟新时会有) |
||||
</div> |
||||
</el-timeline-item> |
||||
<el-timeline-item placement="bottom" timestamp="2025-01-15" color="#30d1fc"> |
||||
<div>张三</div> |
||||
<div class="mt-10px text-14px" style="line-height: 24px; color: #666"> |
||||
更新节点 |
||||
</div> |
||||
</el-timeline-item> |
||||
<el-timeline-item placement="bottom" timestamp="2025-01-01" color="#30d1fc"> |
||||
<div>张三</div> |
||||
<div class="mt-10px text-14px" style="line-height: 24px; color: #666"> |
||||
创建节点 |
||||
</div> |
||||
</el-timeline-item> |
||||
</el-timeline> |
||||
</div> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script setup name="DialogOkr"> |
||||
const emit = defineEmits(['edit']) |
||||
|
||||
const show = ref(false) |
||||
|
||||
const toolbarConfig = { |
||||
toolbarKeys: [ |
||||
'bold', // 加粗 |
||||
'underline', // 下划线 |
||||
'italic', // 斜体 |
||||
'color', // 文字颜色 |
||||
'bgColor', // 背景色 |
||||
'fontSize', // 字号 |
||||
'bulletedList', // 无序列表 |
||||
'numberedList', // 有序列表 |
||||
'insertTable', // 插入表格 |
||||
'insertLink', // 插入链接 |
||||
'undo' // 撤销 |
||||
] |
||||
} |
||||
|
||||
const workIndex = ref('okr') |
||||
const okrList = ref([]) |
||||
const sideIndex = ref('subNode') |
||||
|
||||
async function open(id) { |
||||
show.value = true |
||||
// 获取数据详情 |
||||
console.log(id) |
||||
okrList.value = [ |
||||
{ |
||||
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 |
||||
} |
||||
] |
||||
} |
||||
] |
||||
} |
||||
|
||||
function close() { |
||||
show.value = false |
||||
} |
||||
|
||||
defineExpose({ open, close }) |
||||
|
||||
function handleSaveProcess() { |
||||
console.log(okrList.value) |
||||
} |
||||
|
||||
function handleChildItem() { |
||||
console.log('handleChildItem') |
||||
} |
||||
|
||||
const addNewComment = ref(false) |
||||
const form = ref({ |
||||
commentValue: '', |
||||
commentType: 1 |
||||
}) |
||||
function handleInsertComment() { |
||||
addNewComment.value = true |
||||
form.value = { |
||||
commentValue: '', |
||||
commentType: 1 |
||||
} |
||||
getCommentTemplate() |
||||
} |
||||
|
||||
function getCommentTemplate() { |
||||
form.value.commentValue = `<h2 style=\"text-align: start;\">一、工作概况</h2><p> </p><h2 style=\"text-align: start;\">二、数据统计</h2><ol><li>呼出电话数:</li><li>有效沟通数:</li><li>销售成果</li></ol><h2 style=\"text-align: start;\">三、问题与改进方案</h2><p><br></p>` |
||||
} |
||||
|
||||
function handleSaveComment() { |
||||
addNewComment.value = false |
||||
} |
||||
|
||||
const commentListVal = ref( |
||||
`<h2 style=\"text-align: start;\">一、工作概况</h2><p> 刷牙洗脸吃饭穿鞋出门开车上班捣台球 </p><h2 style=\"text-align: start;\">二、数据统计</h2><ol><li>呼出电话数:666</li><li>有效沟通数:123</li><li>销售成果:今日成交20,本月成交120,距离目标还差888</li></ol><h2 style=\"text-align: start;\">三、问题与改进方案</h2><p>无<br></p>` |
||||
) |
||||
|
||||
function good(index) { |
||||
console.log(index) |
||||
} |
||||
|
||||
const showCommentIndex = ref(-1) |
||||
function showComment(index) { |
||||
showCommentIndex.value = showCommentIndex.value == index ? -1 : index |
||||
} |
||||
|
||||
function handleSendCommnet() { |
||||
console.log(form.value.commentValue) |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.dialog-okr { |
||||
.dialog-okr-header { |
||||
display: flex; |
||||
height: 51px; |
||||
min-height: 51px; |
||||
vertical-align: middle; |
||||
justify-content: space-between; |
||||
-webkit-box-align: center; |
||||
-ms-flex-align: center; |
||||
align-items: center; |
||||
padding: 0 1.25rem; |
||||
.dialog-okr-title { |
||||
display: flex; |
||||
margin-right: 5px; |
||||
align-items: center; |
||||
background: rgba(48, 209, 252, 0.1); |
||||
border-radius: 3px; |
||||
padding: 0 10px; |
||||
line-height: 24px; |
||||
span { |
||||
color: #2a344b; |
||||
font-size: 12px; |
||||
margin-left: 6px; |
||||
} |
||||
} |
||||
} |
||||
.dialog-okr-body { |
||||
display: flex; |
||||
background: #f0f3fa; |
||||
overflow: hidden; |
||||
min-width: 1064px; |
||||
height: calc(94vh - 85px); |
||||
.dialog-okr-content { |
||||
display: flex; |
||||
flex-direction: column; |
||||
height: 100%; |
||||
width: 70%; |
||||
flex: auto; |
||||
min-width: 700px; |
||||
background: #fff; |
||||
margin: 0 1px 0 0; |
||||
justify-content: space-between; |
||||
overflow-y: hidden !important; |
||||
.dialog-okr-content-detail { |
||||
position: relative; |
||||
margin-bottom: 30px; |
||||
overflow-y: auto; |
||||
display: -webkit-box; |
||||
display: -ms-flexbox; |
||||
display: flex; |
||||
-webkit-box-orient: vertical; |
||||
-webkit-box-direction: normal; |
||||
-ms-flex-direction: column; |
||||
flex-direction: column; |
||||
.detail-basic-title { |
||||
display: flex; |
||||
font-size: 14px; |
||||
margin-bottom: 16px; |
||||
.basic-title-item { |
||||
margin-right: 50px; |
||||
.basic-title-label { |
||||
color: #aaa; |
||||
margin-bottom: 6px; |
||||
} |
||||
.basic-title-value { |
||||
color: #2a344b; |
||||
font-size: 14px; |
||||
} |
||||
} |
||||
} |
||||
.detail-basic-info { |
||||
font-size: 14px; |
||||
color: #aaa; |
||||
span { |
||||
margin-right: 40px; |
||||
} |
||||
} |
||||
} |
||||
.content-wrap { |
||||
overflow-y: auto; |
||||
max-height: calc(100% - 70px); |
||||
} |
||||
} |
||||
.dialog-okr-side { |
||||
padding-left: 10px; |
||||
display: flex; |
||||
flex-direction: column; |
||||
width: 30%; |
||||
overflow: hidden; |
||||
min-width: 364px; |
||||
max-width: 500px; |
||||
background: #fff; |
||||
margin: 0; |
||||
.child-item:hover { |
||||
background: #f0f3fa; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
.sav-btn { |
||||
position: absolute; |
||||
right: 10px; |
||||
top: 0; |
||||
width: auto; |
||||
} |
||||
</style> |
@ -0,0 +1,595 @@ |
||||
<template> |
||||
<el-dialog |
||||
v-if="show" |
||||
v-model="show" |
||||
width="900px" |
||||
class="dialog-okr" |
||||
:show-close="false" |
||||
:close-on-click-modal="false" |
||||
> |
||||
<template #header> |
||||
<div class="dialog-okr-header"> |
||||
<div class="flex-1 flex items-center" style="line-height: 50px"> {{ title }} </div> |
||||
<div class="flex items-center"> |
||||
<el-button type="primary" link :disabled="formLoading" @click="handleSave"> |
||||
保存 |
||||
</el-button> |
||||
<el-button link @click="show = false"> 关闭 </el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
<template #default> |
||||
<div class="dialog-okr-body"> |
||||
<el-form :model="form" ref="formRef" :rules="rules" label-width="0"> |
||||
<el-row :gutter="10"> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="parentId"> |
||||
<el-tree-select |
||||
v-model="form.parentId" |
||||
:data="parentNodeList" |
||||
check-strictly |
||||
:props="{ value: 'id', label: 'label', children: 'children' }" |
||||
:render-after-expand="false" |
||||
placeholder="父节点" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="name"> |
||||
<el-input v-model="form.name" placeholder="请输入节点名称" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="createTime"> |
||||
<el-date-picker |
||||
v-model="form.createTime" |
||||
type="date" |
||||
format="YYYY-MM-DD" |
||||
value-format="YYYY-MM-DD" |
||||
placeholder="开始日期" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="endTime"> |
||||
<el-date-picker |
||||
v-model="form.endTime" |
||||
type="date" |
||||
format="YYYY-MM-DD" |
||||
value-format="YYYY-MM-DD" |
||||
placeholder="截止日期" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="executor"> |
||||
<el-select |
||||
v-model="form.executor" |
||||
placeholder="选择执行人,可多选" |
||||
multiple |
||||
clearable |
||||
filterable |
||||
> |
||||
<el-option |
||||
v-for="item in userOptions" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:value="item.id" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="4" :offset="0"> |
||||
<el-form-item prop="persission"> |
||||
<el-select v-model="form.persission" placeholder="选择权限" clearable filterable> |
||||
<el-option label="公开" :value="0" /> |
||||
<el-option label="仅上级可见" :value="1" /> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<div class="relative"> |
||||
<el-button |
||||
v-if="okrKey === 'okr'" |
||||
style="position: absolute; right: 10px; top: 10px" |
||||
type="primary" |
||||
size="small" |
||||
@click="addObjective" |
||||
> |
||||
添加目标 |
||||
</el-button> |
||||
<el-button |
||||
v-else-if="okrKey === 'childNode'" |
||||
style="position: absolute; right: 10px; top: 10px" |
||||
type="primary" |
||||
size="small" |
||||
@click="addChildNode" |
||||
> |
||||
添加子节点 |
||||
</el-button> |
||||
<el-tabs v-model="okrKey"> |
||||
<el-tab-pane label="目标/关键成果" name="okr"> |
||||
<div> |
||||
<div |
||||
class="flex items-center w-full" |
||||
v-for="(item, i) in objectList" |
||||
:key="item.id" |
||||
> |
||||
<div class="flex-1 w-100px"> |
||||
<div class="flex items-center"> |
||||
<el-tag type="success" class="mr-10px">O{{ i + 1 }}</el-tag> |
||||
<el-input v-model="item.name" placeholder="目标名称" class="flex-1 w-150px" /> |
||||
<el-select |
||||
v-model="item.objExecutor" |
||||
placeholder="选择执行人,可多选" |
||||
multiple |
||||
clearable |
||||
filterable |
||||
style="min-width: 240px; margin-left: 10px" |
||||
> |
||||
<el-option |
||||
v-for="it in userOptions" |
||||
:key="it.id" |
||||
:label="it.name" |
||||
:value="it.id" |
||||
/> |
||||
</el-select> |
||||
<el-select |
||||
v-model="item.persission" |
||||
placeholder="选择权限" |
||||
clearable |
||||
filterable |
||||
style="width: 120px; margin-left: 10px" |
||||
> |
||||
<el-option label="公开" :value="0" /> |
||||
<el-option label="仅上级可见" :value="1" /> |
||||
</el-select> |
||||
<div class="ml-10px"> |
||||
<el-button type="primary" text @click="AddKR">新增关键成果</el-button> |
||||
<el-button type="danger" text @click="removeObj">删除目标</el-button> |
||||
</div> |
||||
</div> |
||||
<div style="background: #f0f3fa; padding-bottom: 15px"> |
||||
<div class="ml-50px" v-for="(kr, index) in item.children" :key="kr.id"> |
||||
<div class="flex flex-1 items-center pb-5px pt-5px"> |
||||
<el-tag class="mr-10px">KR{{ index + 1 }}</el-tag> |
||||
<el-select |
||||
v-model="kr.id" |
||||
placeholder="选择或输入" |
||||
filterable |
||||
:props="{ value: 'id', label: 'name' }" |
||||
allow-create |
||||
:reserve-keyword="false" |
||||
class="flex-1 w-150px" |
||||
> |
||||
<el-option |
||||
v-for="it in item.children" |
||||
:key="it.id" |
||||
:label="it.name" |
||||
:value="it.id" |
||||
/> |
||||
</el-select> |
||||
<el-button type="danger" text @click="removeKR">删除关键成果</el-button> |
||||
</div> |
||||
<div class="mt-5px flex items-center"> |
||||
<el-tree-select |
||||
v-model="kr.sourceId" |
||||
:data="sourceOptions" |
||||
:props="defaultProps" |
||||
check-strictly |
||||
clearable |
||||
filterable |
||||
node-key="sourceId" |
||||
placeholder="请选择渠道" |
||||
/> |
||||
<el-radio-group v-model="kr.targetType" class="ml-10px"> |
||||
<el-radio-button label="value">目标值</el-radio-button> |
||||
<el-radio-button label="radio">是/否</el-radio-button> |
||||
</el-radio-group> |
||||
|
||||
<el-input |
||||
v-if="kr.targetType === 'value'" |
||||
v-model="kr.targetNum" |
||||
type="number" |
||||
placeholder="目标值" |
||||
class="ml-10px" |
||||
style="width: 100px" |
||||
/> |
||||
|
||||
<el-select |
||||
v-model="kr.objExecutor" |
||||
placeholder="选择执行人,可多选" |
||||
multiple |
||||
clearable |
||||
filterable |
||||
style="min-width: 240px; margin-left: 10px" |
||||
> |
||||
<el-option |
||||
v-for="it in userOptions" |
||||
:key="it.id" |
||||
:label="it.name" |
||||
:value="it.id" |
||||
/> |
||||
</el-select> |
||||
<el-select |
||||
v-model="kr.persission" |
||||
placeholder="选择权限" |
||||
clearable |
||||
filterable |
||||
style="width: 120px; margin-left: 10px" |
||||
> |
||||
<el-option label="公开" :value="0" /> |
||||
<el-option label="仅上级可见" :value="1" /> |
||||
</el-select> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<!-- <div class="w-100px"></div> --> |
||||
</div> |
||||
</div> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="子节点" name="childNode"> |
||||
<el-table :data="childNodeList"> |
||||
<el-table-column label="名称"> |
||||
<template #default="{ row }"> |
||||
<el-input v-model="row.name" placeholder="子节点名称" /> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="开始日期" width="160px"> |
||||
<template #default="{ row }"> |
||||
<el-date-picker |
||||
v-model="row.createTime" |
||||
type="date" |
||||
format="YYYY-MM-DD" |
||||
value-format="YYYY-MM-DD" |
||||
placeholder="选择日期时间" |
||||
style="width: 130px" |
||||
/> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="截止日期" width="160px"> |
||||
<template #default="{ row }"> |
||||
<el-date-picker |
||||
v-model="row.endTime" |
||||
type="date" |
||||
format="YYYY-MM-DD" |
||||
value-format="YYYY-MM-DD" |
||||
placeholder="选择日期时间" |
||||
style="width: 130px" |
||||
/> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="权限" width="160px"> |
||||
<template #default="{ row }"> |
||||
<el-select v-model="row.permission" placeholder="请选择" style="width: 130px"> |
||||
<el-option label="公开" :value="0" /> |
||||
<el-option label="仅上级可见" :value="1" /> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column label="执行人" width="300px"> |
||||
<template #default="{ row }"> |
||||
<el-select |
||||
v-model="row.executor" |
||||
placeholder="选择执行人,可多选" |
||||
multiple |
||||
clearable |
||||
filterable |
||||
style="width: 100%" |
||||
> |
||||
<el-option |
||||
v-for="item in userOptions" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:value="item.id" |
||||
/> |
||||
</el-select> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column fixed="right" label="删除" :width="100"> |
||||
<template #default="{ $index }"> |
||||
<el-button type="danger" text @click="removeChildNode($index)">删除</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</el-dialog> |
||||
</template> |
||||
|
||||
<script setup name="DialogOkrInfo"> |
||||
const { t } = useI18n() // 国际化 |
||||
const message = useMessage() // 消息弹窗 |
||||
|
||||
const show = ref(false) |
||||
|
||||
watch( |
||||
() => show.value, |
||||
(newValue, oldValue) => { |
||||
if (oldValue && !newValue) { |
||||
emit('close') |
||||
} |
||||
} |
||||
) |
||||
|
||||
const title = ref('') |
||||
const formType = ref('create') |
||||
|
||||
const form = ref({}) |
||||
const formLoading = ref(false) |
||||
const rules = ref({}) |
||||
|
||||
const okrKey = ref('okr') |
||||
|
||||
const parentNodeList = ref([ |
||||
{ |
||||
id: 1, |
||||
label: '寻驾全年目标', |
||||
children: [ |
||||
{ id: 2, label: '1月' }, |
||||
{ id: 3, label: '2月' }, |
||||
{ id: 4, label: '3月' }, |
||||
{ id: 5, label: '4月' }, |
||||
{ id: 6, label: '5月' }, |
||||
{ id: 7, label: '6月' }, |
||||
{ id: 8, label: '7月' }, |
||||
{ id: 9, label: '8月' }, |
||||
{ id: 10, label: '9月' }, |
||||
{ id: 11, label: '10月' }, |
||||
{ id: 12, label: '11月' }, |
||||
{ id: 13, label: '12月' } |
||||
] |
||||
} |
||||
]) |
||||
|
||||
const childNodeList = ref([{}]) |
||||
|
||||
const userOptions = ref([ |
||||
{ id: 1, name: '张三' }, |
||||
{ id: 2, name: '李四' }, |
||||
{ id: 3, name: '王五' }, |
||||
{ id: 4, name: '赵六' } |
||||
]) |
||||
const defaultProps = { |
||||
children: 'children', |
||||
label: 'sourceName', |
||||
value: 'sourceId', |
||||
isLeaf: 'leaf' |
||||
} |
||||
const sourceOptions = ref([]) |
||||
const objectList = ref([ |
||||
{ |
||||
nodeId: 2, |
||||
name: '1月销售任务概述,例:销售额100万,成交率15%', |
||||
objExecutor: [1, 2], |
||||
id: 'a1', |
||||
children: [ |
||||
{ |
||||
id: 'a1-1', |
||||
name: '销售额', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a1-2', |
||||
name: '成交数', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a1-3', |
||||
name: '成交率', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a1-4', |
||||
name: '本月抖音运营投入相较上月少10%', |
||||
isSystem: false, |
||||
targetNum: 0, |
||||
targetValue: false, |
||||
targetType: 'radio' |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
nodeId: 3, |
||||
name: '1月运营目标', |
||||
objExecutor: [1, 2], |
||||
id: 'a2', |
||||
children: [ |
||||
{ |
||||
id: 'a2-1', |
||||
name: '销售额', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a2-2', |
||||
name: '成交数', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a1-3', |
||||
name: '成交率', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a1-4', |
||||
name: '本月抖音运营投入相较上月少10%', |
||||
isSystem: false, |
||||
targetNum: 0, |
||||
targetValue: false, |
||||
targetType: 'radio' |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
nodeId: 4, |
||||
name: '1月主播任务', |
||||
objExecutor: [1, 2], |
||||
id: 'a3', |
||||
children: [ |
||||
{ |
||||
id: 'a3-1', |
||||
name: '销售额', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a3-2', |
||||
name: '成交数', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a3-3', |
||||
name: '成交率', |
||||
isSystem: true, |
||||
targetNum: 10000, |
||||
targetValue: false, |
||||
targetType: 'value' |
||||
}, |
||||
{ |
||||
id: 'a3-4', |
||||
name: '本月抖音运营投入相较上月少10%', |
||||
isSystem: false, |
||||
targetNum: 0, |
||||
targetValue: false, |
||||
targetType: 'radio' |
||||
} |
||||
] |
||||
} |
||||
]) |
||||
|
||||
async function open(type, val) { |
||||
show.value = true |
||||
title.value = type == 'update' ? '修改Okr' : '新增Okr' |
||||
formType.value = type |
||||
resetForm() |
||||
if (val) { |
||||
formLoading.value = true |
||||
try { |
||||
// form.value = await KpiApi.getKpiDetail(val) |
||||
} finally { |
||||
formLoading.value = false |
||||
} |
||||
} |
||||
// getOptions() |
||||
} |
||||
function resetForm() { |
||||
form.value = { |
||||
parentId: '', |
||||
name: '', |
||||
createTime: '', |
||||
endTime: '', |
||||
executor: [] |
||||
} |
||||
} |
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||
|
||||
const formRef = ref() |
||||
/** 提交表单 */ |
||||
const emit = defineEmits(['success', 'close']) // 定义 success 事件,用于操作成功后的回调 |
||||
|
||||
function addObjective() { |
||||
objectList.value.push({ |
||||
name: '', |
||||
objExecutor: [], |
||||
children: [] |
||||
}) |
||||
} |
||||
|
||||
function AddKR() { |
||||
objectList.value.push({ |
||||
name: '', |
||||
objExecutor: [], |
||||
children: [] |
||||
}) |
||||
} |
||||
|
||||
function removeObj() { |
||||
objectList.value.pop() |
||||
} |
||||
|
||||
function removeKR() { |
||||
objectList.value.pop() |
||||
} |
||||
|
||||
function addChildNode() { |
||||
childNodeList.value.push({}) |
||||
} |
||||
|
||||
function removeChildNode(idx) { |
||||
childNodeList.value.splice(idx, 1) |
||||
} |
||||
|
||||
async function handleSave() { |
||||
// 校验表单 |
||||
if (!formRef.value) return |
||||
const valid = await formRef.value.validate() |
||||
if (!valid) return |
||||
// 提交请求 |
||||
formLoading.value = true |
||||
try { |
||||
if (formType.value === 'create') { |
||||
// await KpiApi.createKpi(form.value) |
||||
message.success(t('common.createSuccess')) |
||||
} else { |
||||
// await KpiApi.updateKpi(form.value) |
||||
message.success(t('common.updateSuccess')) |
||||
} |
||||
show.value = false |
||||
// 发送操作成功的事件 |
||||
emit('success') |
||||
} finally { |
||||
formLoading.value = false |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.dialog-okr { |
||||
.dialog-okr-header { |
||||
display: flex; |
||||
height: 51px; |
||||
min-height: 51px; |
||||
vertical-align: middle; |
||||
justify-content: space-between; |
||||
-webkit-box-align: center; |
||||
-ms-flex-align: center; |
||||
align-items: center; |
||||
padding: 0 1.25rem; |
||||
} |
||||
.dialog-okr-body { |
||||
overflow-x: hidden; |
||||
overflow-y: auto; |
||||
min-width: 1064px; |
||||
height: calc(94vh - 85px); |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,257 @@ |
||||
<template> |
||||
<div style="height: 100vh"> |
||||
<div class="flex items-center"> |
||||
<el-popover placement="bottom" width="500px" trigger="click"> |
||||
<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> |
||||
<el-date-picker |
||||
v-model="searchForm.year" |
||||
type="year" |
||||
format="YYYY" |
||||
value-format="YYYY" |
||||
:clearable="false" |
||||
style="width: 100%" |
||||
/> |
||||
<div class="mt-10px" style="height: 400px"> |
||||
<div class="flex items-center border-bottom-1" style="line-height: 32px"> |
||||
<div class="flex-1">节点名称</div> |
||||
<div class="w-120px">开始日期</div> |
||||
<div class="w-120px">截止日期</div> |
||||
</div> |
||||
<el-radio-group |
||||
v-model="searchForm.peroidId" |
||||
@change="peroidChange" |
||||
style="width: 100%" |
||||
> |
||||
<el-radio |
||||
v-for="item in peroidList" |
||||
:key="item.id" |
||||
:label="item.id" |
||||
class="h-44px" |
||||
style="width: 100%" |
||||
> |
||||
<div |
||||
class="flex items-center border-bottom-1" |
||||
style="width: 100%; line-height: 44px" |
||||
> |
||||
<div class="flex-1">{{ item.name }}</div> |
||||
<div class="w-120px">{{ item.startDate }}</div> |
||||
<div class="w-120px">{{ item.endDate }}</div> |
||||
</div> |
||||
</el-radio> |
||||
</el-radio-group> |
||||
</div> |
||||
</div> |
||||
</el-popover> |
||||
|
||||
<el-button class="ml-10px" type="primary" @click="handleAddNode">新建节点</el-button> |
||||
</div> |
||||
|
||||
<vue3-tree-org :data="dataList" center collapsable @on-node-click="handleClickNode"> |
||||
<template #default="{ node }"> |
||||
<div style="cursor: pointer"> |
||||
<div class="tree-org-node__text node-label"> |
||||
<el-popover placement="right" title="目标" width="270px" trigger="hover"> |
||||
<template #reference> |
||||
<div> |
||||
<div style="max-height: 40px; overflow: hidden">{{ node.label }}</div> |
||||
<div class="tip"> 目标数: 3</div> |
||||
</div> |
||||
</template> |
||||
<template #default> |
||||
<div style="font-size: 0.875rem; line-height: 1.5"> |
||||
<div v-for="i in 3" :key="i" class="mt-5"> |
||||
<span style="color: #aaa">0%</span> |
||||
<span style="margin-left: 0.5rem"> |
||||
成交数达到10个,且订单的利润不能低于成交价的30% |
||||
</span> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</el-popover> |
||||
</div> |
||||
<div class="p-5px"> |
||||
<el-progress type="line" :percentage="80" text-inside :stroke-width="12" /> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
</vue3-tree-org> |
||||
<DialogOkr ref="dialogOkr" @edit="handleEditOkr" /> |
||||
<DialogOkrInfo ref="dialogOkrInfo" @close="openOkr" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup name="ObjectList"> |
||||
import { Vue3TreeOrg } from 'vue3-tree-org' |
||||
import 'vue3-tree-org/lib/vue3-tree-org.css' |
||||
import DialogOkr from './DialogOkr.vue' |
||||
import DialogOkrInfo from './DialogOkrInfo.vue' |
||||
|
||||
const dataList = ref({ |
||||
id: 1, |
||||
label: '寻驾全年目标', |
||||
noDragging: true, |
||||
disabled: true, |
||||
children: [ |
||||
{ |
||||
id: 2, |
||||
pid: 1, |
||||
label: '1月', |
||||
noDragging: true, |
||||
disabled: true, |
||||
children: [ |
||||
{ id: 6, pid: 2, label: '第一周', noDragging: true, disabled: true }, |
||||
{ id: 8, pid: 2, label: '第二周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第三周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第四周', noDragging: true, disabled: true } |
||||
] |
||||
}, |
||||
{ |
||||
id: 3, |
||||
pid: 1, |
||||
label: '2月', |
||||
noDragging: true, |
||||
disabled: true, |
||||
children: [ |
||||
{ id: 6, pid: 2, label: '第一周', noDragging: true, disabled: true }, |
||||
{ id: 8, pid: 2, label: '第二周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第三周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第四周', noDragging: true, disabled: true } |
||||
] |
||||
}, |
||||
{ |
||||
id: 4, |
||||
pid: 1, |
||||
label: '3月', |
||||
noDragging: true, |
||||
disabled: true, |
||||
children: [ |
||||
{ id: 6, pid: 2, label: '第一周', noDragging: true, disabled: true }, |
||||
{ id: 8, pid: 2, label: '第二周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第三周', noDragging: true, disabled: true }, |
||||
{ id: 10, pid: 2, label: '第四周', noDragging: true, disabled: true } |
||||
] |
||||
} |
||||
] |
||||
}) |
||||
|
||||
const searchForm = ref({ |
||||
peroidName: '', |
||||
peroidId: null, |
||||
year: new Date().getFullYear() |
||||
}) |
||||
|
||||
const peroidList = ref([ |
||||
{ |
||||
id: 1, |
||||
name: '1月', |
||||
startDate: '2022-01-01', |
||||
endDate: '2022-01-31' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
name: '2月', |
||||
startDate: '2022-02-01', |
||||
endDate: '2022-02-28' |
||||
} |
||||
]) |
||||
|
||||
function peroidChange(val) { |
||||
searchForm.value.peroidName = peroidList.value.find((it) => it.id == val).name |
||||
} |
||||
|
||||
function toggleExpand(data, val) { |
||||
if (Array.isArray(data)) { |
||||
data.forEach((item) => { |
||||
item.expand = val |
||||
if (item.children) { |
||||
toggleExpand(item.children, val) |
||||
} |
||||
}) |
||||
} else { |
||||
data.expand = val |
||||
if (data.children) { |
||||
toggleExpand(data.children, val) |
||||
} |
||||
} |
||||
} |
||||
|
||||
toggleExpand(dataList.value, true) |
||||
|
||||
const dialogOkr = ref(null) |
||||
const okrId = ref(null) |
||||
function handleClickNode(node, data) { |
||||
okrId.value = data.id |
||||
openOkr() |
||||
} |
||||
|
||||
function openOkr() { |
||||
okrId.value && dialogOkr.value.open(okrId.value) |
||||
} |
||||
|
||||
function handleAddNode() { |
||||
okrId.value = null |
||||
dialogOkrInfo.value.open('create', null) |
||||
} |
||||
|
||||
const dialogOkrInfo = ref(null) |
||||
function handleEditOkr() { |
||||
dialogOkr.value.close() |
||||
dialogOkrInfo.value.open('update', 1) |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
.peroid-select { |
||||
border-radius: 4px; |
||||
cursor: pointer; |
||||
&:hover { |
||||
border-color: var(--el-color-primary-light-5); |
||||
} |
||||
} |
||||
|
||||
.tree-org-node__text { |
||||
min-width: 200px; |
||||
min-height: 80px; |
||||
text-align: left; |
||||
font-size: 14px; |
||||
border-bottom: 1px solid #ccc; |
||||
padding: 5px; |
||||
} |
||||
.tip { |
||||
position: relative; |
||||
color: #aaa; |
||||
font-size: 0.875rem; |
||||
} |
||||
:deep(.el-progress-bar__innerText) { |
||||
display: block; |
||||
font-size: 0.75rem !important; |
||||
} |
||||
:deep(.el-overlay-dialog) { |
||||
display: flex; |
||||
justify-content: center; |
||||
align-items: center; |
||||
} |
||||
:deep(.dialog-okr) { |
||||
width: 94vw; |
||||
height: 94vh; |
||||
max-width: 1800px; |
||||
max-height: 1000px; |
||||
margin: 0; |
||||
} |
||||
:deep(.dialog-okr .el-dialog__header) { |
||||
padding: 0 !important; |
||||
} |
||||
:deep(.okr-info-dialog) { |
||||
.el-dialog__body { |
||||
padding-top: 0; |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,53 @@ |
||||
<template> |
||||
<div :style="{ height: `${height}px` }"> |
||||
<el-tabs tab-position="left" v-model="tabIndex" style="height: 100%"> |
||||
<el-tab-pane disabled name="-1"> |
||||
<template #label> |
||||
<div class="w-full"> |
||||
<div style="text-align: left; transform: translateX(-10px)">目标</div> |
||||
</div> |
||||
</template> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="我负责的" name="0">我负责的</el-tab-pane> |
||||
<el-tab-pane label="我的待办" name="1">我的待办</el-tab-pane> |
||||
<el-tab-pane label="全部目标" name="2">全部目标</el-tab-pane> |
||||
<el-tab-pane label="目标关系树" name="3"> |
||||
<ObjectList v-if="tabIndex == 3" /> |
||||
</el-tab-pane> |
||||
<el-tab-pane disabled> |
||||
<template #label> |
||||
<div class="w-full"> |
||||
<el-divider |
||||
direction="horizontal" |
||||
style="width: calc(100% + 10px) !important; transform: translateX(-10px)" |
||||
/> |
||||
<div style="text-align: left; transform: translateX(-10px)">成员</div> |
||||
</div> |
||||
</template> |
||||
</el-tab-pane> |
||||
<el-tab-pane label="张三">张三</el-tab-pane> |
||||
<el-tab-pane label="李四">李四</el-tab-pane> |
||||
<el-tab-pane label="王二">王二</el-tab-pane> |
||||
</el-tabs> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup name="OkrManagement"> |
||||
import ObjectList from './Components/ObjectList.vue' |
||||
|
||||
const tabIndex = ref('0') |
||||
const height = ref(innerHeight - 115) |
||||
</script> |
||||
|
||||
<style lang="scss" scoped> |
||||
:deep(.el-tabs__content) { |
||||
height: 100%; |
||||
} |
||||
:deep(.el-tab-pane) { |
||||
height: 100%; |
||||
} |
||||
:deep(.el-popover__title) { |
||||
font-size: 0.875rem; |
||||
color: #aaa !important; |
||||
} |
||||
</style> |