dev-cl
parent
b91fe3b05a
commit
b0573fdf17
@ -0,0 +1,246 @@ |
||||
<template> |
||||
<Dialog :title="title" v-model="show" :width="formType == 'create' ? '700px' : '1000px'"> |
||||
<div class="flex items-baseline"> |
||||
<el-form |
||||
:model="form" |
||||
ref="formRef" |
||||
:disabled="formType == 'do'" |
||||
:rules="rules" |
||||
label-width="80px" |
||||
class="flex-1" |
||||
> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="24" :offset="0"> |
||||
<el-form-item label="标题" prop="title"> |
||||
<el-input v-model="form.title" placeholder="请输入待办标题" /> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="24"> |
||||
<el-form-item label="内容" prop="content"> |
||||
<Editor |
||||
v-model:modelValue="form.content" |
||||
height="400px" |
||||
:disabled="formType == 'do'" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="优先级" prop="priority"> |
||||
<el-select v-model="form.priority" placeholder="选择优先级" filterable> |
||||
<el-option |
||||
v-for="item in props.priorityOptions" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="完成状态" prop="status"> |
||||
<el-select v-model="form.status" placeholder="选择完成状态" filterable> |
||||
<el-option |
||||
v-for="item in props.statusOptions" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
<el-row :gutter="20"> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="截止日期" prop="dueDate"> |
||||
<el-date-picker |
||||
v-model="form.dueDate" |
||||
type="date" |
||||
format="YYYY-MM-DD" |
||||
value-format="YYYY-MM-DD" |
||||
placeholder="选择日期时间" |
||||
/> |
||||
</el-form-item> |
||||
</el-col> |
||||
<el-col :span="12" :offset="0"> |
||||
<el-form-item label="执行人" prop="executorIds"> |
||||
<el-select |
||||
v-model="form.executorIds" |
||||
placeholder="选择执行人,可多选" |
||||
multiple |
||||
clearable |
||||
filterable |
||||
style="width: 100%" |
||||
> |
||||
<el-option |
||||
v-for="item in employeeOptions" |
||||
:key="item.id" |
||||
:label="item.name" |
||||
:value="item.id" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
</el-col> |
||||
</el-row> |
||||
</el-form> |
||||
<div v-if="formType != 'create'" class="w-350px ml-10px h-full"> |
||||
<div class="mb-10px" v-if="formType == 'do'"> |
||||
<Editor |
||||
v-model:modelValue="form.followUpContent" |
||||
height="150px" |
||||
:toolbarConfig="toolbarConfig" |
||||
/> |
||||
<el-button class="absolute" style="right: 20px; top: 195px" type="primary" @click="addDo"> |
||||
更新进度 |
||||
</el-button> |
||||
</div> |
||||
<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"> |
||||
今天成交了15个 |
||||
</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"> |
||||
下午跟进了100条线索 |
||||
</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"> |
||||
上午跟进了100条线索 |
||||
</div> |
||||
</el-timeline-item> |
||||
</el-timeline> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
<template #footer v-if="formType != 'do'"> |
||||
<span> |
||||
<el-button @click="show = false">取 消</el-button> |
||||
<el-button type="primary" :disabled="formLoading" @click="handleSave">保 存</el-button> |
||||
</span> |
||||
</template> |
||||
</Dialog> |
||||
</template> |
||||
|
||||
<script setup name="DialogWait"> |
||||
const props = defineProps({ |
||||
priorityOptions: { |
||||
type: Array, |
||||
default: () => [ |
||||
{ label: '高', value: 1 }, |
||||
{ label: '中', value: 2 }, |
||||
{ label: '低', value: 3 } |
||||
] |
||||
}, |
||||
statusOptions: { |
||||
type: Array, |
||||
default: () => [ |
||||
{ label: '未完成', value: 1, tagType: 'warning' }, |
||||
{ label: '已关闭', value: 2, tagType: 'success' } |
||||
] |
||||
} |
||||
}) |
||||
|
||||
const { t } = useI18n() // 国际化 |
||||
const message = useMessage() // 消息弹窗 |
||||
|
||||
const toolbarConfig = { |
||||
toolbarKeys: [] |
||||
} |
||||
|
||||
const show = ref(false) |
||||
const title = ref('') |
||||
const formType = ref('create') |
||||
|
||||
const form = ref({}) |
||||
const formLoading = ref(false) |
||||
const rules = ref({ |
||||
title: [{ required: true, message: '请输入标题', trigger: 'blur' }], |
||||
dueDate: [{ required: true, message: '请选择截止日期', trigger: 'change' }], |
||||
executorIds: [{ required: true, message: '请选择执行人', trigger: 'change' }] |
||||
}) |
||||
|
||||
async function open(type, id) { |
||||
show.value = true |
||||
title.value = { create: '新增待办', update: '修改待办', do: '更新待办进度' }[type] |
||||
formType.value = type |
||||
resetForm() |
||||
if (id) { |
||||
formLoading.value = true |
||||
try { |
||||
// 模拟表单数据 |
||||
form.value = { |
||||
title: '2025年1月20日,张三成交了15个', |
||||
content: '今天成交了15个', |
||||
priority: 1, |
||||
status: 1, |
||||
dueDate: '2025-01-20', |
||||
executorIds: [1, 2] |
||||
} |
||||
// form.value = await KpiApi.getKpiDetail(id) |
||||
} finally { |
||||
formLoading.value = false |
||||
} |
||||
} |
||||
getOptions() |
||||
} |
||||
|
||||
function getOptions() { |
||||
employeeOptions.value = [ |
||||
{ id: 1, name: '张三' }, |
||||
{ id: 2, name: '李四' }, |
||||
{ id: 3, name: '王五' } |
||||
] |
||||
} |
||||
|
||||
function resetForm() { |
||||
form.value = { |
||||
title: undefined, |
||||
content: undefined, |
||||
priority: 1, |
||||
status: 1, |
||||
dueDate: undefined, |
||||
executorIds: [] |
||||
} |
||||
} |
||||
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗 |
||||
|
||||
const formRef = ref() |
||||
|
||||
/** 提交表单 */ |
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调 |
||||
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 |
||||
} |
||||
} |
||||
|
||||
const employeeOptions = ref([]) |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
@ -0,0 +1,348 @@ |
||||
<template> |
||||
<div> |
||||
<el-form :model="searchForm" inline label-width="0" @submit.prevent="searchList"> |
||||
<el-form-item> |
||||
<el-input v-model="searchForm.title" placeholder="输入标题" /> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-select v-model="searchForm.priority" placeholder="选择优先级" clearable filterable> |
||||
<el-option |
||||
v-for="item in priorityOptions" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-select v-model="searchForm.status" placeholder="选择完成状态" clearable filterable> |
||||
<el-option |
||||
v-for="item in statusOptions" |
||||
:key="item.value" |
||||
:label="item.label" |
||||
:value="item.value" |
||||
/> |
||||
</el-select> |
||||
</el-form-item> |
||||
<el-form-item> |
||||
<el-button @click="searchList"> 搜索</el-button> |
||||
<el-button type="primary" @click="handleAdd"> 新增</el-button> |
||||
</el-form-item> |
||||
</el-form> |
||||
<div> |
||||
<Icon icon="ep:info-filled" /> |
||||
<span>开发注意:</span> |
||||
<div>列表排序 1 状态按照未完成在前、已关闭在后, 2优先级根据高中低排序 3截止日期正序</div> |
||||
<div> |
||||
表格全部操作按钮:创建人(修改、删除、催办->微信通知)、执行人(跟进);且与完成状态相关 |
||||
</div> |
||||
</div> |
||||
<el-tabs v-model="tabIndex" @tab-click="searchList"> |
||||
<el-tab-pane :name="1"> |
||||
<template #label> |
||||
<el-badge :value="9" :max="99"> |
||||
<el-tooltip content="截止日在今日及之前的未关闭事项" placement="top" effect="dark"> |
||||
<Icon icon="ep:question-filled" /> |
||||
</el-tooltip> |
||||
<span>今日截止</span> |
||||
</el-badge> |
||||
</template> |
||||
</el-tab-pane> |
||||
<el-tab-pane :name="2"> |
||||
<template #label> |
||||
<el-tooltip content="需要我执行的全部事项" placement="top" effect="dark"> |
||||
<Icon icon="ep:question-filled" /> |
||||
</el-tooltip> |
||||
<span>我的待办</span> |
||||
</template> |
||||
</el-tab-pane> |
||||
<el-tab-pane :name="3"> |
||||
<template #label> |
||||
<el-badge :value="3" :max="99"> |
||||
<el-tooltip content="指派他人去办的事项" placement="top" effect="dark"> |
||||
<Icon icon="ep:question-filled" /> |
||||
</el-tooltip> |
||||
<span>催办事项</span> |
||||
</el-badge> |
||||
</template> |
||||
</el-tab-pane> |
||||
<el-tab-pane :name="4"> |
||||
<template #label> |
||||
<el-badge :value="999" :max="99"> |
||||
<el-tooltip content="特指OKR中@我的消息" placement="top" effect="dark"> |
||||
<Icon icon="ep:question-filled" /> |
||||
</el-tooltip> |
||||
<span>通知我的</span> |
||||
</el-badge> |
||||
</template> |
||||
<el-table :data="mentionedList"> |
||||
<el-table-column type="index" width="50" /> |
||||
<el-table-column prop="content" label="okr标题" /> |
||||
<el-table-column prop="createUserName" label="创建人" /> |
||||
<el-table-column prop="createDate" label="创建日期" /> |
||||
<el-table-column fixed="right" label="操作" width="140"> |
||||
<template #default="{ row }"> |
||||
<el-button style="padding: 0" type="primary" text @click="handleShow(row)"> |
||||
查看 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
</el-tab-pane> |
||||
</el-tabs> |
||||
|
||||
<el-table v-if="tabIndex != 4" :data="tableList"> |
||||
<el-table-column type="index" width="50" /> |
||||
<el-table-column prop="title" label="标题" /> |
||||
<el-table-column prop="priority" label="优先级"> |
||||
<template #default="{ row }"> |
||||
<el-tag :type="priorityFilter(row.priority)"> |
||||
{{ priorityNameFilter(row.priority) }} |
||||
</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="createUserName" label="创建人" /> |
||||
<el-table-column prop="createDate" label="创建日期" /> |
||||
<el-table-column prop="executorNames" label="执行人" /> |
||||
<el-table-column prop="dueDate" label="截止日期" /> |
||||
<el-table-column label="状态"> |
||||
<template #default="{ row }"> |
||||
<el-tag :type="statusFilter(row.status)">{{ statusNameFilter(row.status) }}</el-tag> |
||||
</template> |
||||
</el-table-column> |
||||
<el-table-column prop="completeDate" label="关闭日期" /> |
||||
<el-table-column fixed="right" label="操作" width="140"> |
||||
<template #default="{ row }"> |
||||
<el-button |
||||
v-if="row.executorIds.includes(currentUserId) && row.status == 1" |
||||
style="padding: 0; margin-right: 10px" |
||||
type="primary" |
||||
text |
||||
@click="handleDo(row)" |
||||
> |
||||
跟进 |
||||
</el-button> |
||||
<el-button |
||||
v-if="row.createUserId == currentUserId && row.status == 1" |
||||
style="padding: 0; margin-right: 10px; margin-left: 0" |
||||
type="primary" |
||||
text |
||||
@click="handleEdit(row)" |
||||
> |
||||
修改 |
||||
</el-button> |
||||
<el-button |
||||
v-if="!row.executorIds.includes(currentUserId) && row.status == 1" |
||||
style="padding: 0; margin-right: 10px; margin-left: 0" |
||||
type="primary" |
||||
text |
||||
@click="handleNotice(row)" |
||||
> |
||||
催办 |
||||
</el-button> |
||||
<el-button |
||||
v-if="row.createUserId == currentUserId && row.status == 1" |
||||
style="padding: 0; margin-right: 10px; margin-left: 0" |
||||
type="danger" |
||||
text |
||||
@click="handleDelete(row)" |
||||
> |
||||
删除 |
||||
</el-button> |
||||
</template> |
||||
</el-table-column> |
||||
</el-table> |
||||
<Pagination |
||||
v-model:limit="searchForm.pageSize" |
||||
v-model:page="searchForm.pageNo" |
||||
:total="total" |
||||
@pagination="getList" |
||||
/> |
||||
|
||||
<DialogWait ref="waitDialogRef" @success="getList" /> |
||||
</div> |
||||
</template> |
||||
|
||||
<script setup name="WaitTarget"> |
||||
import { useUserStore } from '@/store/modules/user' |
||||
import DialogWait from './DialogWait.vue' |
||||
|
||||
const userStore = useUserStore() |
||||
const currentUserId = userStore.getUser.id |
||||
|
||||
const message = useMessage() |
||||
|
||||
const searchForm = ref({ |
||||
title: undefined, |
||||
status: undefined, |
||||
priority: undefined, |
||||
pageNo: 1, |
||||
pageSize: 50 |
||||
}) |
||||
|
||||
const statusOptions = [ |
||||
{ label: '未完成', value: 1, tagType: 'warning' }, |
||||
{ label: '已关闭', value: 2, tagType: 'success' } |
||||
] |
||||
|
||||
const statusFilter = (status) => { |
||||
return statusOptions.find((item) => item.value === status)?.tagType |
||||
} |
||||
|
||||
const statusNameFilter = (status) => { |
||||
return statusOptions.find((item) => item.value === status)?.label |
||||
} |
||||
|
||||
const priorityOptions = [ |
||||
{ label: '高', value: 1, tagType: 'danger' }, |
||||
{ label: '中', value: 2, tagType: 'warning' }, |
||||
{ label: '低', value: 3, tagType: 'info' } |
||||
] |
||||
|
||||
const priorityFilter = (priority) => { |
||||
return priorityOptions.find((item) => item.value === priority)?.tagType |
||||
} |
||||
|
||||
const priorityNameFilter = (priority) => { |
||||
return priorityOptions.find((item) => item.value === priority)?.label |
||||
} |
||||
|
||||
const tabIndex = ref(1) |
||||
|
||||
onMounted(() => { |
||||
searchList() |
||||
}) |
||||
|
||||
function searchList() { |
||||
searchForm.value.pageNo = 1 |
||||
getList() |
||||
} |
||||
|
||||
const loading = ref(false) |
||||
const tableList = ref([]) |
||||
const mentionedList = ref([]) |
||||
const total = ref(0) |
||||
function getList() { |
||||
loading.value = true |
||||
try { |
||||
// 用settimeout模拟网络请求 |
||||
setTimeout(() => { |
||||
loading.value = false |
||||
if (tabIndex.value == 4) { |
||||
mentionedList.value = [ |
||||
{ |
||||
id: 1, |
||||
content: '我是老六@张三', |
||||
createUserName: '王二', |
||||
createDate: '2025-03-07' |
||||
} |
||||
] |
||||
} else { |
||||
const list = [ |
||||
{ |
||||
id: 1, |
||||
title: '今日跟进数量达到100', |
||||
description: '今日成交数量达到10', |
||||
priority: 1, |
||||
createUserId: 1, |
||||
createUserName: '系统', |
||||
createDate: '2025-03-07', |
||||
executorIds: ['1818599239840960512'], |
||||
executorNames: '张三', |
||||
dueDate: '2025-03-07', |
||||
status: 1, |
||||
completeDate: '' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
title: '今日跟进数量达到100', |
||||
description: '今日成交数量达到10', |
||||
priority: 1, |
||||
createUserId: '1818599239840960512', |
||||
createUserName: '张三', |
||||
createDate: '2025-03-07', |
||||
executorIds: ['1818599239840960512', '123'], |
||||
executorNames: '张三,李四', |
||||
dueDate: '2025-02-07', |
||||
status: 1, |
||||
completeDate: '' |
||||
}, |
||||
{ |
||||
id: 3, |
||||
title: '今日跟进数量达到100', |
||||
description: '今日成交数量达到10', |
||||
priority: 1, |
||||
createUserId: '1818599239840960512', |
||||
createUserName: '张三', |
||||
createDate: '2025-03-07', |
||||
executorIds: ['1818599239840960512'], |
||||
executorNames: '张三', |
||||
dueDate: '2025-03-17', |
||||
status: 2, |
||||
completeDate: '2025-03-07' |
||||
}, |
||||
{ |
||||
id: 2, |
||||
title: '今日跟进数量达到100', |
||||
description: '今日成交数量达到10', |
||||
priority: 1, |
||||
createUserId: '1818599239840960512', |
||||
createUserName: '张三', |
||||
createDate: '2025-03-07', |
||||
executorIds: ['123'], |
||||
executorNames: '李四', |
||||
dueDate: '2025-02-07', |
||||
status: 1, |
||||
completeDate: '' |
||||
} |
||||
] |
||||
tableList.value = list.filter((item) => { |
||||
if (tabIndex.value == 1) { |
||||
return item.status == 1 |
||||
} else { |
||||
return item |
||||
} |
||||
}) |
||||
} |
||||
total.value = 1 |
||||
}, 1000) |
||||
// getWaitTargetList(searchForm.value).then((res) => { |
||||
// tableList.value = res.data |
||||
// total.value = res.total |
||||
// loading.value = false |
||||
// }) |
||||
} catch (error) {} |
||||
} |
||||
|
||||
function handleDo(row) { |
||||
waitDialogRef.value.open('do', row.id) |
||||
} |
||||
|
||||
const waitDialogRef = ref() |
||||
function handleAdd() { |
||||
waitDialogRef.value.open('create') |
||||
} |
||||
|
||||
function handleEdit(row) { |
||||
waitDialogRef.value.open('update', row.id) |
||||
} |
||||
|
||||
function handleDelete(row) { |
||||
console.log(row) |
||||
} |
||||
|
||||
function handleNotice(row) { |
||||
console.log(row) |
||||
|
||||
message.confirm('即将发送微信通知提醒执行人,是否继续?').then(() => { |
||||
message.success('发送成功') |
||||
}) |
||||
} |
||||
|
||||
function handleShow(row) { |
||||
console.log(row) |
||||
message.success('打开okr详情页') |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss" scoped></style> |
Loading…
Reference in new issue