Compare commits

..

No commits in common. 'b91fe3b05a726a8b8c420f19eac87b5ba24d6386' and 'a712e3f85fc0087a25fff3e921177fc317b4086d' have entirely different histories.

  1. 2
      package.json
  2. 17
      src/styles/index.scss
  3. 236
      src/views/OKR/Management/Components/AllTarget.vue
  4. 46
      src/views/OKR/Management/Components/DialogOkr.vue
  5. 236
      src/views/OKR/Management/Components/MyDuty.vue
  6. 116
      src/views/OKR/Management/Components/ObjectList.vue
  7. 127
      src/views/OKR/Management/Components/OkrTable.vue
  8. 10
      src/views/OKR/Management/index.vue

@ -1,6 +1,6 @@
{
"name": "ss-oa-manage",
"version": "1.0.1",
"version": "1.0.0",
"description": "莳松oa管理系统",
"author": "ss",
"private": false,

@ -69,20 +69,3 @@
width: 100%;
}
}
.dialog-okr {
width: 94vw;
height: 94vh;
max-width: 1800px;
max-height: 1000px;
margin: 0;
}
.dialog-okr .el-dialog__header {
padding: 0 !important;
}
.okr-info-dialog {
.el-dialog__body {
padding-top: 0;
}
}

@ -1,236 +0,0 @@
<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>

@ -68,7 +68,44 @@
<el-tabs v-model="workIndex" style="flex: 1">
<el-tab-pane label="目标/关键成果" name="okr">
<div class="content-wrap">
<OkrTable ref="okrTableRef" />
<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>
@ -274,8 +311,6 @@
</template>
<script setup name="DialogOkr">
import OkrTable from './OkrTable.vue'
const emit = defineEmits(['edit'])
const show = ref(false)
@ -300,8 +335,6 @@ const workIndex = ref('okr')
const okrList = ref([])
const sideIndex = ref('subNode')
const okrTableRef = ref(null)
async function open(id) {
show.value = true
//
@ -412,9 +445,6 @@ async function open(id) {
]
}
]
nextTick(() => {
okrTableRef.value.prepareData(okrList.value)
})
}
function close() {

@ -1,236 +0,0 @@
<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>

@ -1,7 +1,7 @@
<template>
<div style="height: 100vh">
<div class="flex items-center">
<el-popover placement="bottom" width="500px" trigger="click" @show="handleSearchPeroid">
<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" />
@ -11,19 +11,46 @@
</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">
<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 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>
@ -117,45 +144,27 @@ const dataList = ref({
const searchForm = ref({
peroidName: '',
peroidId: null
peroidId: null,
year: new Date().getFullYear()
})
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
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'
}
handleSearchOkr()
})
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)
function peroidChange(val) {
searchForm.value.peroidName = peroidList.value.find((it) => it.id == val).name
}
function toggleExpand(data, val) {
@ -187,12 +196,12 @@ function openOkr() {
okrId.value && dialogOkr.value.open(okrId.value)
}
const dialogOkrInfo = ref(null)
function handleAddNode() {
okrId.value = null
dialogOkrInfo.value.open('create', null)
}
const dialogOkrInfo = ref(null)
function handleEditOkr() {
dialogOkr.value.close()
dialogOkrInfo.value.open('update', 1)
@ -230,4 +239,19 @@ function handleEditOkr() {
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>

@ -1,127 +0,0 @@
<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>

@ -8,13 +8,9 @@
</div>
</template>
</el-tab-pane>
<el-tab-pane label="我负责的" name="0">
<MyDuty v-if="tabIndex == 0" />
</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">
<AllTarget v-if="tabIndex == 2" />
</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>
@ -37,8 +33,6 @@
</template>
<script setup name="OkrManagement">
import AllTarget from './Components/AllTarget.vue'
import MyDuty from './Components/MyDuty.vue'
import ObjectList from './Components/ObjectList.vue'
const tabIndex = ref('0')

Loading…
Cancel
Save