莳松-行政管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ss-oa-manage-web/src/views/OKR/Meeting/MeetingInfo.vue

511 lines
17 KiB

3 months ago
<template>
<div>
2 months ago
<!-- <el-affix postion="top" :offset="95" v-if="!isDetail"> -->
<div class="flex justify-between mb-4 bg-white" v-if="!isDetail">
<b class="text-20px">{{ form.meetingId ? '修改会议' : '新增会议' }}</b>
2 weeks ago
<div>
1 week ago
<el-button @click="submit(true)">保存至草稿</el-button>
<el-button type="success" @click="submit(false)">保存</el-button>
2 weeks ago
</div>
2 months ago
</div>
<!-- </el-affix> -->
2 months ago
<el-form
:model="form"
ref="formRef"
:rules="rules"
label-width="120px"
v-loading="loading"
:disabled="!!isDetail"
>
3 months ago
<el-row :gutter="20">
<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
2 months ago
<el-form-item label="会议主题" prop="meetingSubject">
2 months ago
<el-input v-model="form.meetingSubject" placeholder="请输入会议主题" clearable />
3 months ago
</el-form-item>
</el-col>
<el-col :xl="12" :lg="12" :md="12" :sm="24" :xs="24">
2 months ago
<el-form-item label="okr节点" prop="nodeId">
<el-tree-select
v-model="form.nodeId"
:data="peroidList"
:props="defaultProps"
:render-after-expand="false"
:default-expand-all="false"
check-strictly
clearable
placeholder="选择OKR节点"
style="width: 100%"
/>
</el-form-item>
3 months ago
</el-col>
<el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
2 months ago
<el-form-item label="会议时间" prop="startTime">
3 months ago
<el-date-picker
2 months ago
v-model="form.startTime"
3 months ago
type="datetime"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm"
placeholder="请选择会议开始时间"
/>
</el-form-item>
</el-col>
<el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
2 months ago
<el-form-item label="预计结束时间" prop="expectEndTime">
3 months ago
<el-date-picker
2 months ago
v-model="form.expectEndTime"
3 months ago
type="datetime"
format="YYYY-MM-DD HH:mm"
value-format="YYYY-MM-DD HH:mm"
placeholder="请选择预计结束时间"
/>
</el-form-item>
</el-col>
<el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
2 months ago
<el-form-item label="会议地点" prop="meetingRoom">
2 months ago
<el-input v-model="form.meetingRoom" placeholder="请输入会议地点" clearable />
3 months ago
</el-form-item>
</el-col>
<el-col :xl="6" :lg="6" :md="12" :sm="12" :xs="24">
<el-form-item label="会议状态" prop="status">
<el-select v-model="form.status" placeholder="请选择会议状态" style="width: 100%">
2 months ago
<el-option label="未开始" value="1" />
<el-option label="已结束" value="2" />
2 months ago
<el-option label="已取消" value="3" disabled />
3 months ago
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" :offset="0">
<el-form-item label="预约参会人员" prop="expectUsers">
<el-select
v-model="form.expectUsers"
placeholder="选择参会人员"
filterable
style="width: 100%"
multiple
@change="handleUserChange"
>
<el-option
v-for="item in userOptions"
2 months ago
:key="item.id"
:label="item.name"
:value="item.id"
2 weeks ago
:disabled="item.status == 1 || item.id == userStore.getUser.id"
3 months ago
/>
</el-select>
</el-form-item>
</el-col>
2 months ago
<el-col :span="24" :offset="0" v-if="form.meetingId">
3 months ago
<el-form-item label="实际参会人员" prop="actualUsers">
<el-checkbox-group v-model="form.actualUsers">
<el-checkbox
v-for="item in expectUserOptions"
2 months ago
:key="item.id"
:label="item.name"
:value="item.id"
3 months ago
>
2 months ago
{{ item.name }}
3 months ago
</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
1 week ago
<el-col :span="24" :offset="0" v-if="isDetail && !isAllActived">
2 months ago
<el-form-item label="缺席原因" prop="absentReason">
<el-input v-model="form.absentReason" placeholder="请输入缺席原因" />
3 months ago
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
2 months ago
<el-col :xl="16" :lg="16" :md="24" :sm="24" :xs="24">
1 week ago
<el-tabs v-model="currentUserId" tab-position="top" @tab-click="userTabChange">
2 weeks ago
<el-tab-pane
1 week ago
v-for="item in form.meetingContentList"
:key="item.userId"
:label="item.userName"
:name="item.userId + ''"
2 weeks ago
/>
</el-tabs>
<el-tabs v-model="currentContentId" tab-position="left" addable @edit="handleTabsEdit">
<el-tab-pane
1 week ago
v-for="(item, index) in form.meetingContentList.find(
(it) => it.userId == currentUserId
)?.userMeetingContentList"
:key="index"
:label="'内容' + (index + 1)"
:name="index"
2 weeks ago
:closable="index > 0"
>
<div v-if="!!isDetail" v-dompurify-html="item.content" class="w-full"></div>
<Editor v-else v-model="item.content" height="500px" style="width: 100%" />
</el-tab-pane>
</el-tabs>
<!-- <el-form-item label="会议内容" prop="meetingContent">
2 months ago
<div v-if="!!isDetail" v-dompurify-html="form.meetingContent" class="w-full"></div>
2 months ago
<Editor v-else v-model="form.meetingContent" height="500px" style="width: 100%" />
2 weeks ago
</el-form-item> -->
3 months ago
</el-col>
2 months ago
<el-col :xl="8" :lg="8" :md="24" :sm="24" :xs="24" v-if="!!form.meetingId">
2 weeks ago
<div v-if="!!isDetail" v-dompurify-html="form.meetingSummary" class="w-full"></div>
<div v-else>
<el-tabs v-model="summaryIdx" addable @edit="meetingSummaryEdit">
<el-tab-pane
1 week ago
v-for="(item, index) in form.meetingSummaryList"
2 weeks ago
:key="index"
:label="`会议纪要${index || ''}`"
:name="index"
:closable="index > 0"
>
<Editor
1 week ago
v-model="item.summary"
2 weeks ago
:toolbarConfig="toolbarConfig"
1 week ago
height="350px"
2 weeks ago
placeholder="请输入会议纪要"
style="width: 100%"
/>
<div class="mt-10px">
<el-form-item label="是否创建待办" label-width="auto">
1 week ago
<el-radio-group v-model="item.isCreateAgentWork">
2 weeks ago
<el-radio :label="true" :value="true"> 创建待办 </el-radio>
<el-radio :label="false" :value="false"> 不创建待办 </el-radio>
</el-radio-group>
</el-form-item>
</div>
1 week ago
<div class="flex items-center" v-if="item.isCreateAgentWork">
2 weeks ago
<el-select
class="flex-1"
1 week ago
v-model="item.agentUserList"
2 weeks ago
placeholder="选择执行人"
clearable
filterable
multiple
>
<el-option
v-for="it in userOptions"
:key="it.id"
:label="it.name"
:value="it.id"
:disabled="it.status == 1"
/>
</el-select>
<el-date-picker
class="flex-1 ml-10px"
v-model="item.endDate"
type="date"
format="YYYY-MM-DD"
value-format="YYYY-MM-DD"
placeholder="选择截止时间"
/>
</div>
</el-tab-pane>
</el-tabs>
<el-divider />
<div class="text-black text-12px">
如果选择创建待办请选择执行人及截止日期默认每天9:00循环提醒可于待办中修改
</div>
<div class="mt-10px">
<el-form-item label="会议纪要发送至群聊:" label-width="auto">
1 week ago
<!-- <el-input v-model="form.wxId" placeholder="请输入群聊名称" /> -->
<el-select
filterable
clearable
v-model="form.wxId"
placeholder="请输入群聊名称"
style="width: 100%"
>
<el-option
v-for="item in groupOptions"
:key="item.wxGroupId"
:label="item.wxGroupName"
:value="item.wxGroupId"
/>
</el-select>
2 weeks ago
</el-form-item>
</div>
</div>
<!-- <el-form-item label="会议纪要" prop="meetingSummary" label-width="80px">
<div v-if="!!isDetail" v-dompurify-html="form.meetingSummary" class="w-full"></div>
<Editor
2 months ago
v-else
2 months ago
v-model="form.meetingSummary"
2 weeks ago
:toolbarConfig="toolbarConfig"
height="300px"
style="width: 100%"
2 months ago
/>
2 weeks ago
</el-form-item> -->
3 months ago
</el-col>
</el-row>
</el-form>
</div>
</template>
<script setup name="MeetingInfo">
3 months ago
import { listToTree } from '@/utils/tree'
import { getAllNodeTree } from '@/api/okr/okr'
2 months ago
import * as MeetingApi from '@/api/okr/meeting'
import { formatDate } from '@/utils/formatTime'
import { getEmployeeSimpleList } from '@/api/pers/employee'
import { useTagsViewStore } from '@/store/modules/tagsView'
2 weeks ago
import { useUserStore } from '@/store/modules/user'
3 months ago
3 months ago
const route = useRoute()
2 months ago
const message = useMessage()
const tagsViewStore = useTagsViewStore()
2 weeks ago
const userStore = useUserStore()
2 months ago
3 months ago
const defaultProps = {
value: 'nodeId',
label: 'nodeName',
children: 'children'
}
const isDetail = route.query.isDetail
2 weeks ago
const currentUserId = ref(undefined)
1 week ago
const currentContentId = ref(0) // 默认选中第一个标签页
2 weeks ago
const summaryIdx = ref(0) // 会议纪要的索引
const toolbarConfig = {
toolbarKeys: []
}
3 months ago
2 months ago
onMounted(async () => {
1 week ago
getWxGroupOptions()
2 months ago
await getOptions()
3 months ago
if (route.params.id && route.params.id != 0) {
// 这里可以调用API获取会议详情数据
2 months ago
getMeetingInfo(route.params.id)
3 months ago
} else {
1 week ago
form.value.meetingContentList = [
2 weeks ago
{
1 week ago
userId: userStore.getUser.id + '',
userName: userStore.getUser.nickname,
userMeetingContentList: [
2 weeks ago
{
content: ''
}
]
}
]
1 week ago
currentContentId.value = 0
3 months ago
}
})
3 months ago
const peroidList = ref([])
function getOptions() {
2 months ago
return Promise.all([getAllNodeTree(), getEmployeeSimpleList()])
.then(([okrResp, employeeResp]) => {
peroidList.value = listToTree(okrResp?.tree || [], {
id: 'nodeId',
pid: 'parentId',
children: 'children'
})
userOptions.value = employeeResp.map((it) => ({ ...it, id: it.id + '' }))
2 weeks ago
form.value.expectUsers = [userStore.getUser.id + ''] // 默认添加当前用户为预约参会人员
1 week ago
// form.value.actualUsers = [userStore.getUser.id + '']
2 weeks ago
currentUserId.value = userStore.getUser.id + '' // 默认选中当前用户
2 months ago
})
.catch((error) => {
console.error('获取数据失败:', error)
3 months ago
})
}
3 months ago
const form = ref({
2 months ago
meetingId: undefined,
meetingSubject: '',
startTime: '',
meetingRoom: '',
expectEndTime: '',
3 months ago
expectUsers: [],
actualUsers: [],
okrNodeName: '',
2 months ago
status: '1',
meetingContent: '',
meetingSummary: '',
2 weeks ago
absentReason: '',
1 week ago
meetingContentList: [],
meetingSummaryList: []
3 months ago
})
const rules = {
2 months ago
meetingSubject: [{ required: true, message: '请输入会议主题', trigger: 'blur' }],
startTime: [{ required: true, message: '请选择会议开始时间', trigger: 'change' }],
expectEndTime: [{ required: true, message: '请选择预计结束时间', trigger: 'change' }],
meetingRoom: [{ required: true, message: '请输入会议地点', trigger: 'blur' }],
expectUsers: [{ required: true, message: '请选择参会人员', trigger: 'change' }]
3 months ago
}
const formRef = ref(null)
2 months ago
const userOptions = ref([])
3 months ago
const expectUserOptions = ref([])
const isAllActived = computed(() => {
// 判断实际参会人员是否包含所有预约参会人员
return form.value.expectUsers.every((item) => form.value.actualUsers.includes(item))
})
2 months ago
const loading = ref(false)
3 months ago
// 获取详情
2 months ago
const getMeetingInfo = async (meetingId) => {
try {
loading.value = true
// 调用API获取会议详情
const resp = await MeetingApi.getMeetingDetail({ meetingId })
loading.value = false
if (resp) {
1 week ago
let summaryList = []
if (resp.meetingSummaryList && resp.meetingSummaryList.length > 0) {
summaryList = resp.meetingSummaryList.map((item) => ({
1 week ago
...item,
1 week ago
isCreateAgentWork: !!item.isCreateAgentWork,
agentUserList: item.agentUserList ? item.agentUserList.map((it) => it + '') : []
}))
} else {
summaryList = [
2 weeks ago
{
1 week ago
summary: resp.meetingSummary || '',
agentUserList: [],
2 weeks ago
endDate: '',
1 week ago
isCreateAgentWork: true
2 weeks ago
}
]
2 months ago
}
1 week ago
form.value = {
...form.value,
...resp,
startTime: formatDate(resp.startTime, 'YYYY-MM-DD HH:mm'),
expectEndTime: formatDate(resp.expectEndTime, 'YYYY-MM-DD HH:mm'),
expectUsers: resp.expectUsers || [],
actualUsers: resp.actualUsers || [],
meetingSummaryList: summaryList
}
1 week ago
currentContentId.value = 0
expectUserOptions.value = userOptions.value.filter((user) =>
form.value.expectUsers.some((it) => it == user.id)
)
3 months ago
}
2 months ago
} catch (error) {
loading.value = false
console.error('获取会议详情失败:', error)
}
3 months ago
}
1 week ago
const groupOptions = ref([])
function getWxGroupOptions() {
MeetingApi.refreshWxGroupList().then(() => {
MeetingApi.getWxGroupList()
.then((resp) => {
groupOptions.value = resp || []
})
.catch((error) => {
console.error('获取微信群列表失败:', error)
})
})
}
function userTabChange() {
currentContentId.value = 0
2 weeks ago
}
function handleTabsEdit(targetName, action) {
if (action === 'add') {
1 week ago
form.value.meetingContentList.forEach((item) => {
if (item.userId == currentUserId.value) {
item.userMeetingContentList.push({
2 weeks ago
content: ''
})
}
})
} else if (action === 'remove') {
1 week ago
form.value.meetingContentList.forEach((item) => {
if (item.userId == currentUserId.value) {
item.userMeetingContentList.splice(targetName, 1)
2 weeks ago
// 如果删除的是当前选中的标签页,则切换到下一个标签页
1 week ago
if (currentContentId.value == targetName) {
currentContentId.value = targetName - 1
2 weeks ago
}
}
})
}
}
function meetingSummaryEdit(targetName, action) {
if (action === 'add') {
1 week ago
form.value.meetingSummaryList.push({
summary: '',
agentUserList: [],
2 weeks ago
endDate: '',
1 week ago
isCreateAgentWork: true
2 weeks ago
})
} else if (action === 'remove') {
1 week ago
form.value.meetingSummaryList.splice(targetName, 1)
summaryIdx.value = targetName - 1
2 weeks ago
}
}
function handleUserChange(val) {
3 months ago
// 当预约参会人员变化时,更新实际参会人员选项
expectUserOptions.value = userOptions.value.filter((user) =>
2 months ago
form.value.expectUsers.some((it) => it == user.id)
3 months ago
)
2 months ago
if (!isDetail) {
form.value.actualUsers = [...form.value.expectUsers]
}
2 weeks ago
// 先过滤掉不存在的参会人员
1 week ago
form.value.meetingContentList = form.value.meetingContentList.filter((item) => {
return val.some((it) => it == item.userId)
2 weeks ago
})
// 再补充新增的
val.map((item) => {
1 week ago
if (!form.value.meetingContentList.some((it) => it.userId == item)) {
form.value.meetingContentList.push({
userId: item,
userName: userOptions.value.find((it) => it.id == item).name,
userMeetingContentList: [
2 weeks ago
{
content: ''
}
]
})
}
})
3 months ago
}
2 months ago
const router = useRouter()
1 week ago
async function submit(isDraft = false) {
2 months ago
// 校验表单
if (!formRef.value) return
const valid = await formRef.value.validate()
if (!valid) return
try {
1 week ago
form.value.isDraft = isDraft
2 months ago
// 提交表单数据
if (form.value.meetingId) {
1 week ago
if (
form.value.status == 2 &&
form.value.meetingSummaryList.some((it) => it.summary.trim() == '')
) {
2 months ago
message.error('会议结束时,会议纪要不能为空')
return
}
// 更新会议
await MeetingApi.updateMeeting(form.value)
message.success('会议更新成功')
3 months ago
} else {
2 months ago
form.value.actualUsers = []
2 months ago
// 新增会议
await MeetingApi.createMeeting(form.value)
message.success('会议创建成功')
3 months ago
}
2 months ago
tagsViewStore.delView(route)
const visitedViews = tagsViewStore.getVisitedViews
const latestView = visitedViews.slice(-1)[0]
router.push(latestView)
} catch (error) {
console.error('保存会议数据失败:', error)
}
3 months ago
}
</script>
<style lang="scss" scoped></style>