| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div> |
| | | |
| | | <!-- ç³è¯·ç±»åéæ© --> |
| | | <el-card class="type-card"> |
| | | <div class="type-selector"> |
| | | <div |
| | | v-for="type in applicationTypes" |
| | | :key="type.value" |
| | | class="type-item" |
| | | :class="{ active: currentType === type.value }" |
| | | @click="changeType(type.value)" |
| | | > |
| | | <div class="type-icon"> |
| | | <el-icon :size="24"><component :is="type.icon"/></el-icon> |
| | | </div> |
| | | <div class="type-info"> |
| | | <div class="type-name">{{ type.name }}</div> |
| | | <div class="type-desc">{{ type.desc }}</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-card> |
| | | |
| | | <!-- ä¼è®®ç³è¯·è¡¨å --> |
| | | <el-card> |
| | | <div class="form-header"> |
| | | <h3>{{ getCurrentTypeName() }}ç³è¯·</h3> |
| | | </div> |
| | | |
| | | <el-form |
| | | ref="meetingFormRef" |
| | | :model="meetingForm" |
| | | :rules="rules" |
| | | label-width="100px" |
| | | > |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®ä¸»é¢" prop="title"> |
| | | <el-input v-model="meetingForm.title" placeholder="请è¾å
¥ä¼è®®ä¸»é¢"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®å®¤" prop="roomId"> |
| | | <el-select v-model="meetingForm.roomId" placeholder="è¯·éæ©ä¼è®®å®¤" style="width: 100%"> |
| | | <el-option |
| | | v-for="room in meetingRooms" |
| | | :key="room.id" |
| | | :label="`${room.name} (${room.location})`" |
| | | :value="room.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="主æäºº" prop="host"> |
| | | <el-input v-model="meetingForm.host" placeholder="请è¾å
¥ä¸»æäººå§å"/> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¼è®®æ¥æ" prop="meetingDate"> |
| | | <el-date-picker |
| | | v-model="meetingForm.meetingDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©ä¼è®®æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | :disabled-date="disabledDate" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <!-- 空åï¼ä¿æå¸å± --> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-row :gutter="20"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å¼å§æ¶é´" prop="startTime"> |
| | | <el-time-picker |
| | | v-model="meetingForm.startTime" |
| | | placeholder="è¯·éæ©å¼å§æ¶é´" |
| | | value-format="HH:mm" |
| | | format="HH:mm" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»ææ¶é´" prop="endTime"> |
| | | <el-time-picker |
| | | v-model="meetingForm.endTime" |
| | | placeholder="è¯·éæ©ç»ææ¶é´" |
| | | value-format="HH:mm" |
| | | format="HH:mm" |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | |
| | | <el-form-item label="åä¼äººå" prop="participants"> |
| | | <el-select |
| | | v-model="meetingForm.participants" |
| | | multiple |
| | | filterable |
| | | placeholder="è¯·éæ©åä¼äººå" |
| | | style="width: 100%" |
| | | > |
| | | <el-option |
| | | v-for="person in employees" |
| | | :key="person.userId" |
| | | :label="`${person.nickName || person.userName}${person.dept?.deptName ? ` (${person.dept.deptName})` : ''}`" |
| | | :value="person.userId" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="ä¼è®®è¯´æ" prop="description"> |
| | | <el-input |
| | | v-model="meetingForm.description" |
| | | type="textarea" |
| | | :rows="4" |
| | | placeholder="请è¾å
¥ä¼è®®è¯´æ" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="form-footer"> |
| | | <el-button @click="resetForm">éç½®</el-button> |
| | | <el-button type="primary" @click="submitForm">æäº¤</el-button> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, reactive, onActivated} from 'vue' |
| | | import {ElMessage} from 'element-plus' |
| | | import {Document, Promotion, Bell} from '@element-plus/icons-vue' |
| | | import {getRoomEnum, saveMeetingApplication} from '@/api/collaborativeApproval/meeting.js' |
| | | import {userListNoPageByTenantId} from "@/api/system/user.js"; |
| | | |
| | | // å½åç³è¯·ç±»å |
| | | const currentType = ref('department') // approval: å®¡æ¹æµç¨, department: é¨é¨çº§, notification: éç¥åå¸ |
| | | |
| | | // ç³è¯·ç±»åé项 |
| | | const applicationTypes = ref([ |
| | | { |
| | | value: 'approval', |
| | | name: 'å®¡æ¹æµç¨ä¼è®®', |
| | | desc: 'éè¦ç»è¿å¤çº§å®¡æ¹çä¼è®®ç³è¯·', |
| | | icon: Document |
| | | }, |
| | | { |
| | | value: 'department', |
| | | name: 'é¨é¨çº§ä¼è®®', |
| | | desc: 'é¨é¨å
é¨ä¼è®®ç³è¯·æµç¨', |
| | | icon: Promotion |
| | | }, |
| | | { |
| | | value: 'notification', |
| | | name: 'ä¼è®®éç¥', |
| | | desc: 'æ é审æ¹ç´æ¥åå¸çä¼è®®éç¥', |
| | | icon: Bell |
| | | } |
| | | ]) |
| | | |
| | | // è¡¨åæ°æ® |
| | | const meetingForm = reactive({ |
| | | title: '', |
| | | type: '', |
| | | roomId: '', |
| | | host: '', |
| | | meetingDate: '', |
| | | startTime: '', |
| | | endTime: '', |
| | | participants: [], |
| | | description: '' |
| | | }) |
| | | |
| | | // 表åå¼ç¨ |
| | | const meetingFormRef = ref(null) |
| | | |
| | | // ä¼è®®å®¤å表 |
| | | const meetingRooms = ref([]) |
| | | |
| | | // åå·¥å表 |
| | | const employees = ref([]) |
| | | |
| | | // è¡¨åæ ¡éªè§å |
| | | const rules = { |
| | | title: [{required: true, message: '请è¾å
¥ä¼è®®ä¸»é¢', trigger: 'blur'}], |
| | | roomId: [{required: true, message: 'è¯·éæ©ä¼è®®å®¤', trigger: 'change'}], |
| | | host: [{required: true, message: '请è¾å
¥ä¸»æäºº', trigger: 'blur'}], |
| | | meetingDate: [{required: true, message: 'è¯·éæ©ä¼è®®æ¥æ', trigger: 'change'}], |
| | | startTime: [{required: true, message: 'è¯·éæ©å¼å§æ¶é´', trigger: 'change'}], |
| | | endTime: [{required: true, message: 'è¯·éæ©ç»ææ¶é´', trigger: 'change'}], |
| | | participants: [{required: true, message: 'è¯·éæ©åä¼äººå', trigger: 'change'}] |
| | | } |
| | | |
| | | // ç¦ç¨æ¥æï¼ç¦ç¨ä»å¤©ä¹åçæ¥æï¼ |
| | | const disabledDate = (time) => { |
| | | // ç¦ç¨ä»å¤©ä¹åçæ¥æ |
| | | return time.getTime() < Date.now() - 86400000 |
| | | } |
| | | |
| | | // 忢ç³è¯·ç±»å |
| | | const changeType = (type) => { |
| | | currentType.value = type |
| | | } |
| | | |
| | | // è·åå½åç±»ååç§° |
| | | const getCurrentTypeName = () => { |
| | | const type = applicationTypes.value.find(t => t.value === currentType.value) |
| | | return type ? type.name : '' |
| | | } |
| | | |
| | | // é置表å |
| | | const resetForm = () => { |
| | | meetingFormRef.value?.resetFields() |
| | | } |
| | | |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | meetingFormRef.value?.validate((valid) => { |
| | | if (valid) { |
| | | |
| | | let formData = {...meetingForm} |
| | | formData.applicationType = currentType.value |
| | | formData.startTime = `${meetingForm.meetingDate} ${meetingForm.startTime}:00` |
| | | formData.endTime = `${meetingForm.meetingDate} ${meetingForm.endTime}:00` |
| | | formData.participants = JSON.stringify(formData.participants) |
| | | console.log(formData) |
| | | saveMeetingApplication(formData).then(() => { |
| | | |
| | | // 模ææäº¤æä½ |
| | | ElMessage.success(`${getCurrentTypeName()}æäº¤æå`) |
| | | resetForm() |
| | | }) |
| | | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | // 页é¢å è½½æ¶åå§å |
| | | onActivated(() => { |
| | | getRoomEnum().then(res => { |
| | | meetingRooms.value = res.data |
| | | }) |
| | | userListNoPageByTenantId().then(res => { |
| | | employees.value = res.data || [] |
| | | }) |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | } |
| | | |
| | | .page-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .type-card { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .type-selector { |
| | | display: flex; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .type-item { |
| | | flex: 1; |
| | | display: flex; |
| | | align-items: center; |
| | | padding: 20px; |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 8px; |
| | | cursor: pointer; |
| | | transition: all 0.3s; |
| | | } |
| | | |
| | | .type-item:hover { |
| | | border-color: #409eff; |
| | | box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .type-item.active { |
| | | border-color: #409eff; |
| | | background-color: #ecf5ff; |
| | | } |
| | | |
| | | .type-icon { |
| | | margin-right: 15px; |
| | | color: #409eff; |
| | | } |
| | | |
| | | .type-name { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | color: #303133; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .type-desc { |
| | | font-size: 14px; |
| | | color: #909399; |
| | | } |
| | | |
| | | .form-header { |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 1px solid #ebeef5; |
| | | } |
| | | |
| | | .form-header h3 { |
| | | margin: 0; |
| | | color: #303133; |
| | | } |
| | | |
| | | .form-footer { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | gap: 10px; |
| | | margin-top: 30px; |
| | | padding-top: 20px; |
| | | border-top: 1px solid #ebeef5; |
| | | } |
| | | </style> |