vue-admin下拉框el-select最后一个显示不全,会出现margin-bottom: -17px;

.el-select-dropdown__wrap.el-scrollbar__wrap {
    margin-bottom: 0 !important;
}

问题所在是因为出现:margin-bottom: -17px;
在这里插入图片描述
在这里插入图片描述

<template> <el-dialog center width="600px" :title="title" v-model="visible" :close-on-click-modal="false" draggable :lock-scroll="false"> <div class="signerInfo"> <div ref="signerInfoRight" class="signerInfoRight"> <el-form ref="dataFormRef" :model="form" :disabled="readonly" label-position="left" label-width="80px"> <!-- 公告标题(必填) --> <el-form-item label="公告标题" prop="title" class="required-item"> <template #label> <span class="required-mark">*</span> <span>公告标题</span> </template> <el-input v-model="form.title" placeholder="请输入公告标题(限20字)" maxlength="20" show-word-limit /> </el-form-item> <!-- 公告内容(可选) --> <el-form-item label="公告内容" prop="content"> <el-input v-model="form.content" type="textarea" placeholder="请输入公告内容(限200字)" maxlength="200" show-word-limit rows="4" /> </el-form-item> <!-- 关联内容(必填) --> <el-form-item label="关联内容" prop="bizType" class="no-label required-item"> <template #label> <span class="required-mark">*</span> <span>关联内容</span> </template> <el-select v-model="form.bizType" placeholder="请选择关联类型" @change="handleBizTypeChange" style="width: 220px"> <el-option :key="item.value" :label="item.label" :value="item.value" v-for="item in bizTypeOptions" /> </el-select> <!-- 朋友圈下拉(bizType=1) --> <el-select style="width: 220px; margin-left: 7px" v-model="form.bizId" placeholder="请选择朋友圈关联内容" v-if="form.bizType == 1"> <el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in relatedList" /> </el-select> <!-- 课程下拉(bizType=3) --> <el-select style="width: 220px; margin-left: 7px" v-model="form.bizId" placeholder="请选择课程关联内容" v-if="form.bizType == 3"> <el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in relatedList" /> </el-select> <!-- 知识库下拉(bizType=6) --> <el-select style="width: 220px; margin-left: 7px" v-model="form.bizId" placeholder="请选择知识库关联内容" v-if="form.bizType == 6"> <el-option :key="item.id" :label="item.name" :value="item.id" v-for="item in relatedList" /> </el-select> </el-form-item> <!-- 发送用户(必填) --> <div style="display: flex"> <el-form-item label="发送用户" prop="userType" class="no-label required-item"> <template #label> <span class="required-mark">*</span> <span>发送用户</span> </template> <el-select v-model="form.userType" placeholder="部" @change="handleUserTypeChange" style="width: 220px"> <el-option :key="item.value" :label="item.label" :value="item.value" v-for="item in userTypeOptions" /> </el-select> <el-select v-if="form.userType == 3" v-model="form.groupTeamList" filterable multiple :clearable="true" placeholder="请选择团队" style="width: 220px; margin-left: 7px" > <el-option :key="item.account" :label="item.name" :value="item.account + ''" v-for="item in groupTeamList" /> </el-select> <el-select v-model="form.groupRoleList" filterable multiple :clearable="true" v-if="form.userType == 2" placeholder="请选择角色" style="width: 220px; margin-left: 7px" > <el-option :key="item.account" :label="item.name" :value="item.account + ''" v-for="item in groupRoleList" /> </el-select> </el-form-item> <el-form-item v-if="form.userType == 4" label="指定用户" prop="groupUsrList" style="margin-left: 7px"> <div> <el-tag style="margin-right: 4px; margin-bottom: 4px" v-for="tag in form.groupUsrList" :key="tag.userId" closable @close="handleRemoveUse(tag)" > {{ tag.nickName || tag.name }} </el-tag> </div> </el-form-item> </div> <div v-if="form.userType == 4" style="width: 27%; margin-left: 115px; margin-bottom: 13px"> <div class=""> <CustomerDragUpload class="fileItemUpload" action="/admin/v1/tenant/user/analysis" :limit="1" @singleSuccess="(val) => handleUploadSuccess('fileItemUpload', val)" > 上传用户名单 </CustomerDragUpload> </div> <div class="downTemplate" @click="fileTemplate('user')">下载用户名单模版</div> </div> <!-- 发送时间(可选) --> <el-form-item label="发送时间" prop="sendTime"> <template #label> <span class="required-mark"> </span> <span>发送时间</span> </template> <el-date-picker v-model="form.sendTime" type="datetime" placeholder="填写默认立即发送" value-format="yyyy-mm-dd HH:mm:ss" style="width: 220px" /> </el-form-item> </el-form> </div> </div> <template #footer> <span class="dialog-footer"> <el-button @click="close">取消</el-button> <el-button type="primary" :loading="submitting" @click="preSubmit" :disabled="loading"> 提交 </el-button> </span> </template> </el-dialog> </template> <script setup lang="ts" name="NoticeFormDialog"> import { useMessage } from '@/hooks/message'; import { useI18n } from 'vue-i18n'; import { useFormModal } from '@/hooks/useFormModal'; import { ref } from 'vue'; import { getFriendList, getCourseList, getKnowledgeList, saveNotice } from '@/api/admin/notice'; import { pageList as teamConfigPageList } from '@/api/admin/teamConfig'; import { pageFormList } from '@/api/admin/roleConfig'; import { downExcelTemp } from '@/api/admin/tool'; import CustomerDragUpload from '@/components/customerDragUpload/index.vue'; const emit = defineEmits(['refresh']); const { t } = useI18n(); const dataFormRef = ref(); const message = useMessage(); // 响应式数据 const groupTeamList = ref<{ account: string; name: string }[]>([]); const groupRoleList = ref<{ account: string; name: string }[]>([]); const relatedList = ref<any[]>([]); interface NoticeForm { id?: number; noticeId?: number; // 统一为 noticeId(大写I),和列表、接口一致 title: string; content: string; bizType: number | ''; bizId: number | ''; userType: number | ''; groupTeamList: string[]; groupRoleList: string[]; groupUsrList: any[]; audienceIds: number[]; sendTime?: string; } // 关联类型选项 const bizTypeOptions = ref([ { label: '朋友圈', value: 1 }, { label: '课程', value: 3 }, { label: '知识库', value: 6 }, ]); // 发送用户类型选项 const userTypeOptions = ref([ { label: '员', value: 1 }, { label: '指定角色', value: 2 }, { label: '指定团队', value: 3 }, { label: '指定用户', value: 4 }, ]); /** * 关联类型变更:加载对应下拉列表 */ const handleBizTypeChange = async () => { form.value.bizId = ''; relatedList.value = []; try { if (form.value.bizType === 1) { const res = await getFriendList({ pageNum: 1, pageSize: 100, bizType: 1 }); relatedList.value = res.data.list.map((item: any) => ({ id: item.articleId, name: item.content || '无内容', })); } else if (form.value.bizType === 3) { const res = await getCourseList({ pageNum: 1, pageSize: 100, bizType: 3 }); relatedList.value = res.data.list.map((item: any) => ({ id: item.id, name: item.title || '无课程名称', })); } else if (form.value.bizType === 6) { const res = await getKnowledgeList({ pageNum: 1, pageSize: 100, bizType: 6 }); relatedList.value = res.data.list.map((item: any) => ({ id: item.articleId, name: item.title || '无知识库标题', })); } } catch (err) { const typeName = form.value.bizType === 1 ? '朋友圈' : form.value.bizType === 3 ? '课程' : '知识库'; message.error(`获取${typeName}列表失败,请重试`); } }; /** * 发送用户类型变更:重置选择项 */ const handleUserTypeChange = () => { form.value.groupTeamList = []; form.value.groupRoleList = []; form.value.groupUsrList = []; form.value.audienceIds = []; }; /** * 初始化团队/角色列表 */ const init = async () => { teamConfigPageList({ pageNum: 1, pageSize: 1000 }).then((res) => { groupTeamList.value = res.data.list.map((ele) => ({ account: ele.teamId, name: ele.teamName, })); }); pageFormList({ pageNum: 1, pageSize: 1000 }).then((res) => { groupRoleList.value = res.data.list.map((ele) => ({ account: ele.roleId, name: ele.roleName, })); }); }; /** * 编辑回显:强制给 form.noticeId 赋值(核心修复) */ const initDetail = async (row: any): Promise<NoticeForm> => { console.log('列表传递的row(编辑回显)1111:', row); console.log('row.noticeId(大写I)的值1111:', row.noticeId); // 验证row是否有noticeId debugger; const detail = row; let groupTeamList: string[] = []; let groupRoleList: string[] = []; let groupUsrList: any[] = []; const sendUserDesc = detail.sendUserDesc || ''; // 关联内容回显 if (detail.bizType) { form.value.bizType = detail.bizType; await handleBizTypeChange(); form.value.bizId = detail.bizId; } // 发送用户回显 const sendUserList = detail.sendUserList || []; // 从row中获取sendUserList if (detail.userType == 2) { // 指定角色:取sendUserList里的audienceId(对应角色ID) groupRoleList = sendUserList.map((item) => item.audienceId + ''); } else if (detail.userType == 3) { // 指定团队:取sendUserList里的audienceId(对应团队ID) groupTeamList = sendUserList.map((item) => item.audienceId + ''); } else if (detail.userType == 4) { groupUsrList = detail.userList || []; } // 【强制赋值】确保 noticeId 被赋值到表单 const noticeIdVal = detail.id; // 从row读取noticeId(大写I) console.log('赋值给form.noticeId的值:', noticeIdVal); // 验证赋值结果 return { id: detail.id, noticeId: noticeIdVal, // 明确赋值,避免遗漏 title: detail.title || '', content: detail.content || '', bizType: detail.bizType || '', bizId: detail.bizId || '', userType: detail.userType || '', groupTeamList, groupRoleList, groupUsrList, audienceIds: detail.audienceIds || [], sendTime: detail.sendTime || '', } as NoticeForm; }; /** * 新增公告:传递 noticeId */ const createApi = async (data: NoticeForm) => { const submitData = { title: data.title, content: data.content || '', bizType: Number(data.bizType), bizId: Number(data.bizId), userType: Number(data.userType), audienceIds: data.audienceIds, sendTime: data.sendTime || '', }; console.log('新增提交数据(无noticeId):', submitData); const res = await saveNotice(submitData); return res.data; }; /** * 编辑公告:强制携带 noticeId(大写I) */ const updateApi = async (id: any, data: NoticeForm) => { // 【双重保险】如果data.noticeId为空,直接从form取(避免fetchById赋值失败) const finalNoticeId = data.noticeId || form.value.noticeId; if (!finalNoticeId) { message.error('noticeId缺失,无法提交编辑'); throw new Error('noticeId is required for update'); } const submitData = { id: data.id, noticeId: finalNoticeId, // 强制携带,确保传参 title: data.title, content: data.content || '', bizType: Number(data.bizType), bizId: Number(data.bizId), userType: Number(data.userType), audienceIds: data.audienceIds, sendTime: data.sendTime || '', }; // 【关键日志】打印提交数据,让你直观看到noticeId是否存在 console.log('编辑提交数据(含noticeId):', submitData); const res = await saveNotice(submitData); return res.data; }; // 表单模态框初始化:确保initForm包含noticeId const { visible, title, form, readonly, loading, submitting, openDialog, close, submit } = useFormModal<NoticeForm, any>({ initForm: () => ({ id: undefined, noticeId: undefined, // 必须包含,保持响应式 title: '', content: '', bizType: '', bizId: '', userType: 1, groupTeamList: [], groupRoleList: [], groupUsrList: [], audienceIds: [], sendTime: '', }), initDetail, create: createApi, update: updateApi, titles: { create: t('添加通告'), edit: t('编辑通告'), }, afterSubmit: () => { message.success(t('common.optSuccessText')); emit('refresh'); }, beforeOpen: init, }); /** * 下载用户模板 */ const fileTemplate = (type: string) => { downExcelTemp('/admin/v1/system/template/getTemplate', { key: type }); }; /** * 上传用户名单成功回调 */ const handleUploadSuccess = (key: string, data: any) => { if (key === 'fileItemUpload') { form.value.groupUsrList = data; } }; /** * 移除指定用户 */ const handleRemoveUse = (item: any) => { const findIndex = form.value.groupUsrList.findIndex((sitem: any) => sitem.userId === item.userId); if (findIndex > -1) { form.value.groupUsrList.splice(findIndex, 1); } }; /** * 表单校验 */ const validateForm = (): boolean => { if (!form.value.title.trim()) { message.error('请输入公告标题'); return false; } if (form.value.title.length > 20) { message.error('公告标题能超过20字'); return false; } if (!form.value.bizType) { message.error('请选择关联类型'); return false; } if (!form.value.bizId || isNaN(Number(form.value.bizId))) { const typeName = form.value.bizType === 1 ? '朋友圈' : form.value.bizType === 3 ? '课程' : '知识库'; message.error(`请选择有效的${typeName}关联内容`); return false; } if (!form.value.userType) { message.error('请选择发送用户类型'); return false; } if (form.value.userType === 2 && !form.value.groupRoleList.length) { message.error('请选择指定角色'); return false; } if (form.value.userType === 3 && !form.value.groupTeamList.length) { message.error('请选择指定团队'); return false; } if (form.value.userType === 4 && !form.value.groupUsrList.length) { message.error('请上传指定用户名单'); return false; } // 编辑时校验noticeId(双重保险) // if (title.value === t('编辑通告') && !form.value.noticeId) { // message.error('公告ID缺失,无法编辑'); // return false; // } return true; }; /** * 提交前预处理 */ const preSubmit = async () => { if (!validateForm()) return; // 组装受众ID if (form.value.userType === 2) { form.value.audienceIds = form.value.groupRoleList.map((id) => Number(id)); } else if (form.value.userType === 3) { form.value.audienceIds = form.value.groupTeamList.map((id) => Number(id)); } else if (form.value.userType === 4) { form.value.audienceIds = form.value.groupUsrList.map((item) => item.userId); } else { form.value.audienceIds = []; } // 转换字段类型 form.value.bizType = Number(form.value.bizType); form.value.bizId = Number(form.value.bizId); form.value.userType = Number(form.value.userType); // 打印form完整数据,确认noticeId存在 console.log('提交前form数据:', form.value); submit(form.value); }; // 暴露方法给父组件 defineExpose({ openDialog }); </script> <style scoped lang="scss"> .signerInfoRight { padding: 10px 0; } .dialog-footer { display: flex; justify-content: center; gap: 10px; } .required-mark { color: #ff4d4f; margin-right: 4px; font-size: 14px; } .required-item .el-form-item__label { display: flex; align-items: center; } .no-label.required-item .el-form-item__label { padding-right: 12px; } .downTemplate { margin-top: 10px; color: blue; cursor: pointer; } ::v-deep .el-form .el-form-item:last-of-type { margin-bottom: 17px !important; } </style> 为啥下拉角色和团队,指定用户 没有返显点编辑的时候
最新发布
12-03
<template> <div class="navbar" :style="{ backgroundColor: sideTheme === 'theme-dark' ? variables.menuBackground : variables.headerBackgroundColor, width: settingsStore.topNav ? '' : '600px', }" > <!-- width:showSearchs? '745px' : '300px' --> <!-- <hamburge id="hamburger-container" :is-active="appStore.sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" /> --> <!-- <breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!settingsStore.topNav" /> --> <top-nav id="topmenu-container" class="topmenu-container" v-if="settingsStore.topNav" /> <div class="right-menu"> <template v-if="appStore.device !== 'mobile'"> <div class="inputDemo notice-box"> <el-dropdown trigger="click" @command="updateBubgPermissions" :max-height="300" > <span class="el-dropdown-link"> <span class="dept_text"> {{ bubg }} </span> <el-icon class="el-icon--right"> <arrow-down /> </el-icon> </span> <template #dropdown> <el-dropdown-menu> <el-dropdown-item v-for="(item, index) in bubgList" :key="index" :command="item" :disabled="item.disabled" >{{ item.label }}</el-dropdown-item > </el-dropdown-menu> </template> </el-dropdown> </div> <!-- <el-switch v-if="isAdmin" v-model="isShould" @change="switchChange" class="ml-2" inline-prompt style="--el-switch-on-color: #13ce66; --el-switch-off-color: #ff4949" active-text="V1" inactive-text="V2" /> --> <el-badge is-dot class="item" :hidden="reddotsIndicateMessage"> <el-icon class="icon_message" @click="openMessage"><Bell /></el-icon> </el-badge> <header-search id="header-search" class="right-menu-item" @showSearch="showSearch" /> <!-- <screenfull id="screenfull" class="right-menu-item hover-effect" /> --> <!-- <el-button @click="openAiBtn">Ai</el-button> --> <!-- <span ><img @click="openAiBtn" style="width: 32px; cursor: pointer" src="../../assets/images/AItubiao.png" alt="" /></span> --> <LangSelect @selectCallback="langSelectCallback" /> <!-- <el-tooltip content="布局大小" effect="dark" placement="bottom"> <size-select id="size-select" class="right-menu-item hover-effect" /> </el-tooltip> --> </template> <div class="avatar-container"> <el-dropdown @command="handleCommand" class="right-menu-item hover-effect" trigger="click" > <div class="avatar-wrapper"> <img v-if="userStore.avatar" :src="userStore.avatar" class="user-avatar" /> <img v-else src="@/assets/images/profile.jpg" class="user-avatar" /> <!-- <el-icon><caret-bottom /></el-icon> --> <div class="userName">{{ userStore.nickName }}</div> </div> <template #dropdown> <el-dropdown-menu> <router-link to="/user/profile"> <el-dropdown-item>个人中心</el-dropdown-item> </router-link> <el-dropdown-item command="changeSys"> <span>切换后台</span> </el-dropdown-item> <el-dropdown-item command="setLayout"> <span>布局设置</span> </el-dropdown-item> <a data-v-bd143a29="" href="https://hiway.feishu.cn/wiki/WgiDw97BmiNYHKkEBZvclRE5nce" class=""> <li data-el-collection-item="" aria-disabled="false" class="el-dropdown-menu__item" tabindex="-1" role="menuitem"> 更新日志 </li> </a> <el-dropdown-item v-if="!isFeishu()" divided command="logout"> <span>退出登录</span> </el-dropdown-item> <el-dropdown-item v-else divided command="logoutFeishu"> <span>重新进入</span> </el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </div> <!-- <p class="user_name">{{ userStore.nickName }}</p> --> </div> <el-drawer v-model="messageVisi" title="消息列表" size="60%"> <MessageDrawer v-if="messageVisi" ref="messageDrawer" @messageCount="getMessageCount" /> </el-drawer> <el-dialog ref="aiContainer" class="ai-contaoner" v-model="aiDialogVisible" title="向 Ai 请教" width="45%" :before-close="handleClose" > <!-- <template #header="{ close, titleId, titleClass }"> <div class="my-header"> <div>向 Ai 请教</div> </div> </template> --> <AiMessage @scrollToBottom="scrollToBottomCak"></AiMessage> <!-- <template #footer> <div class="dialog-footer"> <el-button type="primary" @click="aiDialogVisible = false"> 取消 </el-button> </div> </template> --> </el-dialog> </div> </template> <script setup> import { ref, watch, onMounted, onUnmounted, computed } from 'vue' import { messages, connect, disconnect } from './websocket-client' // 引入WebSocket客户端代码 import AiMessage from './aiMessage.vue' import { ElNotification, ElMessageBox, ElMessage, ElLoading, } from 'element-plus' import MessageDrawer from '@/components/messageDrawer' import { getUserNotifyCount } from '@/api/bpm/notify' import Breadcrumb from '@/components/Breadcrumb' import TopNav from '@/components/TopNav' // import Hamburger from "@/components/Hamburger"; import Screenfull from '@/components/Screenfull' import SizeSelect from '@/components/SizeSelect' import HeaderSearch from '@/components/HeaderSearch' import useAppStore from '@/store/modules/app' import useUserStore from '@/store/modules/user' import useSettingsStore from '@/store/modules/settings' import variables from '@/assets/styles/variables.module.scss' import LangSelect from '@/components/LangSelect' import { getDeptByBuDeptTreeselect } from '@/api/login' import useTagsViewStore from '@/store/modules/tagsView' const { proxy } = getCurrentInstance() const router = useRouter() const appStore = useAppStore() const userStore = useUserStore() const settingsStore = useSettingsStore() const showSearchs = ref(false) const bubg = ref(null) const bubgList = ref([]) const route = useRoute() const sideTheme = computed(() => settingsStore.sideTheme) let messageVisi = ref(false) const aiDialogVisible = ref(false) let reddotsIndicateMessage = ref(true) const visitedViews = computed(() => useTagsViewStore().visitedViews) const isShould = ref(false) const aiContainer = ref() const isShoulds = computed(() => { const flag = localStorage.getItem('isShould') return flag }) watch( () => isShoulds, (nval, oval) => { if (nval.value === '2') { isShould.value = false } else { isShould.value = true } }, { immediate: true } ) const isAdmin = computed(() => { if (userStore.userName === 'admin') { return true } else { return false } }) function toggleSideBar() { appStore.toggleSideBar() } function handleCommand(command) { switch (command) { case 'changeSys': window.open(`${window.location.origin}/qms-base-web/index`, '_self') break case 'setLayout': setLayout() break case 'logout': logout() break case 'logoutFeishu': logoutFeishu() break default: break } } // 国际化回调 function langSelectCallback() { // 头部信息 // 强制刷新子组件 this.$emit('selectCallback') } function scrollToBottomCak() { var elDialogBody = document.querySelector('.el-dialog__body') elDialogBody.scrollTop = elDialogBody.scrollHeight } function logout() { ElMessageBox.confirm('确定注销并退出系统吗?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }) .then(() => { userStore.LogOut().then(() => { location.href = '/qmsMain/loginDefault?v=' + new Date().getTime() }) }) .catch(() => {}) } function logoutFeishu() { ElMessageBox.confirm('确定重新登入系统么?', '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning', }) .then(() => { userStore.LogOut().then(() => { location.href = '/qmsMain/login' }) }) .catch(() => {}) } function openMessage() { messageVisi.value = true } function handleLookClick() {} const emits = defineEmits(['setLayout']) function setLayout() { emits('setLayout') } // watch(showSearchs, (value) => { // showSearchs.value = value // }) function isFeishu() { return /Lark|Feishu/i.test(navigator.userAgent) } function updateBubgPermissions(e) { bubg.value = e.label localStorage.setItem('groupName', e.label) localStorage.setItem('groupId', e.code) // this.$store.commit("SET_GROUP_ID", selectedItem.code); // this.$store.commit("SET_GROUP_NAME", selectedItem.label); // this.refreshView(); refreshSelectedTag() // 刷新当前页面 // closeAllTags() //关闭所有页面 } function showSearch(flag) { showSearchs.value = flag } function getBubgData() { getDeptByBuDeptTreeselect().then((response) => { let checkList = [] let isAdmin = userStore.userName === 'admin' ? true : false if (userStore.permissionsDataBubgDtos.length == 0) { checkList.push(userStore.groupId) } else { checkList = userStore.permissionsDataBubgDtos } bubgList.value = response.data bubg.value = userStore.groupName || '' if (!isAdmin) { bubgList.value.forEach((bubg) => { if (checkList == null) { bubg.disabled = true } else { if (checkList.indexOf(bubg.code) == -1) { bubg.disabled = true } else { bubg.disabled = false } } }) } else { bubgList.value.forEach((bubg) => { bubg.disabled = false }) } bubgList.value = bubgList.value.filter(item => !item.disabled) }) } // 获取消息数量 function getMessageCount(count) { showReddotsIndicateMessage(count) } // 控制消息红点是否显示 function showReddotsIndicateMessage(count) { reddotsIndicateMessage.value = count <= 0 } function refreshSelectedTag(view) { if (route.meta.link) { // useTagsViewStore().delIframeView(route); proxy.$bus.$emit('refreshIframe', route.path) // 触发刷新当前页面(iframe) return } let pathStr = route.path // 必须要配置 if (pathStr.includes('bpm')) { proxy.$bus.$emit('refreshPage-bpm', route.path) // 触发刷新当前页面 } else { proxy.$tab.refreshPage(route) } } function openAiBtn() { aiDialogVisible.value = true } function switchChange(e) { if (e) { localStorage.setItem('isShould', '1') } else { localStorage.setItem('isShould', '2') } closeAllTags() } function toLastView(visitedViews, view) { const latestView = visitedViews.slice(-1)[0] if (latestView) { router.push(latestView.fullPath) } else { // now the default is to redirect to the home page if there is no tags-view, // you can adjust it according to your needs. if (view.name === 'Dashboard') { // to reload home page router.replace({ path: '/redirect' + view.fullPath }) } else { router.push('/') } } } function closeAllTags(view) { const originObj = { fullPath: '/index', path: '/index', name: 'Index', meta: { title: '首页', icon: 'dashboard', affix: true, }, title: '首页', } proxy.$tab.closeAllPage().then(({ visitedViews }) => { toLastView(visitedViews, originObj) }) } watch( () => messages.value, (newMessages) => { if (newMessages.length > 0) { const latestMessage = newMessages[newMessages.length - 1] const message = JSON.parse(latestMessage.text) // 播放提示音 const audio = new Audio('/sounds/sound.mp3') // 这里放置提示音文件的路径 audio.play() const notificationInstance = ElNotification({ title: message.title, message: message.content, type: message.type.toLowerCase() || 'info', position: 'top-right', // 设置弹出位置为右上角 duration: 30000, // 30秒 showClose: true, // 显示关闭按钮 onClick: () => { messageVisi.value = true // 打开消息抽屉 // 延时 2 秒后关闭通知 setTimeout(() => { notificationInstance.close() // 手动关闭特定的通知实例 }, 2000) // 2000 毫秒 = 2 秒 }, }) } }, { deep: true } // 设置深度监听 ) // 在组件挂载时连接 WebSocket onMounted(() => { connect() getUserNotifyCount() .then((res) => { showReddotsIndicateMessage(res.data) }) .catch((err) => { console.error('Error fetching notifications:', err) }) }) // 在组件卸载时断开 WebSocket 连接 onUnmounted(() => { disconnect() }) getBubgData() </script> <style lang="scss" scoped> .navbar { height: 34px; overflow: hidden; position: relative; background: #eff2fb !important; box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); .hamburger-container { line-height: 46px; height: 100%; float: left; cursor: pointer; transition: background 0.3s; -webkit-tap-highlight-color: transparent; &:hover { background: rgba(0, 0, 0, 0.025); } } .breadcrumb-container { float: left; } .topmenu-container { position: absolute; background-color: #eff2fb; } .errLog-container { display: inline-block; vertical-align: top; } .right-menu { float: right; height: 100%; line-height: 34px; display: flex; &:focus { outline: none; } .right-menu-item { display: inline-block; padding-right: 8px; height: 100%; font-size: 18px; color: #5a5e66; vertical-align: text-bottom; // color: #fff; &.hover-effect { cursor: pointer; transition: background 0.3s; &:hover { background: rgba(0, 0, 0, 0.025); } } } .avatar-container { // margin-right: 40px; .avatar-wrapper { // margin-top: 5px; position: relative; display: flex; align-items: center; height: 100%; .user-avatar { cursor: pointer; width: 25px; height: 25px; border-radius: 20px; } i { cursor: pointer; position: absolute; right: -20px; top: 25px; font-size: 12px; } } } } } ::v-deep .el-badge__content.is-fixed { top: 10px; } ::v-deep .el-badge__content.is-fixed.is-dot { right: 13px; } .icon_message { height: 100%; margin: 0px 10px; cursor: pointer; } .header_title { display: inline-block; height: 100%; width: 300px; line-height: 50px; padding-left: 10px; font-family: 'Microsoft YaHei'; // line-height: 1em; color: #f0f0f0; font-weight: bold; font-size: 30px; text-shadow: 0px 0px 0 rgb(216, 216, 216), 1px 1px 0 rgb(192, 192, 192), 2px 2px 0 rgb(168, 168, 168), 3px 3px 0 rgb(144, 144, 144), 4px 4px 0 rgb(120, 120, 120), 5px 5px 0 rgb(96, 96, 96), 6px 6px 5px rgba(0, 0, 0, 0.35), 6px 6px 1px rgba(0, 0, 0, 0.5), 0px 0px 5px rgba(0, 0, 0, 0.2); } .user_name { display: inline-block; height: 100%; line-height: 34px; margin: 0px; } .inputDemo { display: flex; align-items: center; white-space: nowrap; input { width: 150px; font-size: 12px; border: none; background: none; text-align: center; font-weight: bold; } .el-input__suffix { i { margin-left: 0.06rem; font-weight: bold; } } /* WebKit browsers */ ::-webkit-input-placeholder { font-weight: bold; } } ::v-deep .ai-contaoner .el-dialog__body { height: calc(100vh - 180px); overflow-y: auto; padding: 0px; background-color: #292a2d; // position: relative; } ::v-deep .el-select .el-input__wrapper { background-color: #eff2fb !important; } ::v-deep .ai-contaoner .el-dialog__header { color: #fff; margin-right: 0px; background-image: linear-gradient( to right, rgb(96, 62, 132), rgb(91, 96, 195) ); } ::v-deep .ai-contaoner .el-dialog__title { color: #fff; } ::v-deep .ai-contaoner .el-dialog__close { color: #fff; } .userName { height: 100%; width: 80px; line-height: 35px; // display: flex; // align-items: center; padding-left: 5px; font-size: 14px; white-space: nowrap; /* 确保文本在一行内显示 */ overflow: hidden; /* 隐藏溢出的内容 */ text-overflow: ellipsis; /* 使用打点表示文字溢出 */ } .el-dropdown-link { .dept_text { display: inline-block; white-space: nowrap; width: 200px; text-align: right; //overflow: hidden; /* 隐藏溢出的内容 */ //text-overflow: ellipsis; /* 使用打点表示文字溢出 */ } } @keyframes gradient-blink-animation { 0% { color: #ff0000; /* 红色 */ } 20% { color: #ffaa00; /* 橙色 */ } 40% { color: #ffff00; /* 黄色 */ } 60% { color: #00ff00; /* 绿色 */ } 80% { color: #0000ff; /* 蓝色 */ } 100% { color: #aa00ff; /* 紫色 */ } } </style> dept_text下拉选择自适应宽度
09-29
<template> <el-dialog :append-to-body="true" :title="titleText === 'Add' ? '新增' : '编辑'" v-if="hasLoaded" :close-on-click-modal="false" v-model="dialogVisible" width="1000px" center @close="handleDialogVisible" > <div class="line"></div> <!-- 主表单区域 --> <el-form ref="form" :model="form" label-width="120px" size="default" :rules="rules"> <el-form-item label="提成类型" prop="commissionType"> <el-radio-group v-model="form.commissionType"> <el-radio value="operation" @change="handleChanne">运营提成</el-radio> <el-radio value="channel" @change="handleChannelChange">渠道提成</el-radio> </el-radio-group> </el-form-item> <el-form-item label="负责人类型" prop="responsibleType"> <el-radio-group v-model="form.responsibleType"> <el-radio value="operator">运营人员</el-radio> <el-radio value="merchant" :key="`merchant-radio-${showMerchant}`" v-if="showMerchant">商户</el-radio> </el-radio-group> </el-form-item> <el-form-item label="负责人" prop="responsible"> <el-select v-model="form.responsible" placeholder="请输入商户名称或者ID"> <el-option v-for="item in responsibleOptions" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="有效期开始时间" prop="validStartTime"> <el-date-picker v-model="form.validStartTime" type="datetime" placeholder="选择开始时间" value-format="YYYY-MM-DD HH:mm:ss"></el-date-picker> </el-form-item> <el-form-item label="有效期结束时间" prop="validEndTime"> <el-date-picker v-model="form.validEndTime" type="datetime" format="YYYY-MM-DD 23:59:59" placeholder="选择结束时间" value-format="YYYY-MM-DD" @change="handleEndDateChange" :disabled="isEndTimeDisabled" ></el-date-picker> <el-checkbox v-model="isUnlimited" class="radio-style-checkbox" @change="handleUnlimitedChange"> 限 </el-checkbox> </el-form-item> </el-form> <!-- 商户操作区域 --> <el-button type="primary" @click="showMerchantForm(false)" style="margin: 10px 0"> 新增商户 </el-button> <el-table :data="merchantList" border> <el-table-column label="商户编码" prop="merchantCode" align="center" min-width="150" /> <el-table-column label="商户名称" prop="name" min-width="100" show-overflow-tooltip align="center" /> <el-table-column label="经纪公司" min-width="100" show-overflow-tooltip align="center"> <template #default="{ row }"> {{ row.brokerageText || '限' }} </template> </el-table-column> <el-table-column label="销售区域" min-width="100" show-overflow-tooltip align="center"> <template #default="{ row }"> {{ row.salesArea.length > 0 ? row.salesArea .map((areaId) => { const area = this.salesAreaOptions.find((item) => item.id === areaId); return area ? area.name : ''; }) .filter(Boolean) .join('、') : '限' }} </template> </el-table-column> <el-table-column label="提成比例" prop="commissionRatio" min-width="120" show-overflow-tooltip align="center" /> <el-table-column label="操作" width="150" align="center"> <template #default="{ row, $index }"> <div style="display: flex; justify-content: center; align-items: center; height: 100%; padding: 6px 0"> <el-button type="primary" link @click="showMerchantForm(true, row, $index)" style="color: #b29350">修改</el-button> <el-button type="primary" link @click="deleteMerchant($index)" style="color: #b29350">删除</el-button> </div> </template> </el-table-column> </el-table> <!-- 主表单按钮 --> <div class="dialog-footer"> <el-button @click="dialogVisible = false">取消</el-button> <el-button type="primary" @click="handleSave" v-if="titleText === 'Add'">保存</el-button> <el-button type="primary" @click="handleSave" v-if="titleText === 'Edit'">保存</el-button> </div> <el-dialog :title="isEditMerchant ? '修改商户' : '新增商户'" v-model="merchantFormVisible" width="600px" :close-on-click-modal="false" center> <div class="line"></div> <el-form ref="merchantForm" :model="merchantForm" label-width="100px" :rules="merchantRules"> <el-form-item label="商户" prop="id"> <el-select v-model="merchantForm.id" placeholder="请选择商户" @change="handleMerchantSelect" clearable multiple> <el-option v-for="item in merchantOptions" :key="item.id" :label="item.name" :value="item.id" /> </el-select> </el-form-item> <el-form-item label="销售区域" prop="salesArea"> <el-checkbox-group v-model="merchantForm.salesArea" :disabled="salesAreaUnlimited" @change="handleSalesAreaChange"> <el-checkbox v-for="item in salesAreaOptions" :key="item.id" :value="item.id" :label="item.name"> {{ item.name }} </el-checkbox> </el-checkbox-group> <el-checkbox v-model="salesAreaUnlimited" :value="true" style="position: absolute; right: 0; top: 1px" class="radio-style-checkbox" @change="handleSalesAreaUnlimited" > 限 </el-checkbox> </el-form-item> <el-form-item label="经纪公司" prop="brokerageIds"> <el-checkbox-group v-model="merchantForm.brokerageIds" :disabled="brokerageUnlimited" @change="handleBrokerageSelect"> <el-checkbox v-for="item in userBrokerCompanies" :key="item.brokerCompanyId" :value="item.brokerCompanyId" :label="item.brokerCompanyAbbr" /> </el-checkbox-group> <el-checkbox v-model="brokerageUnlimited" value="true" class="radio-style-checkbox" style="position: absolute; right: 0; top: 1px" @change="handleBrokerageUnlimited" > 限 </el-checkbox> </el-form-item> <el-form-item label="提成比例" prop="commissionRatio"> <el-input v-model.number="merchantForm.commissionRatio" placeholder="请输入提成比例" suffix-icon="el-icon-percentage" clearable></el-input> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button @click="merchantFormVisible = false">取消</el-button> <el-button type="primary" @click="saveMerchant" v-if="isEditMerchant">保存</el-button> <el-button type="primary" @click="saveMerchant" v-else>保存</el-button> </span> </template> </el-dialog> </el-dialog> </template> <script> import _ from 'lodash'; import { ElMessageBox, ElMessage } from 'element-plus'; import { ArrowRight, ArrowLeft, Money } from '@element-plus/icons-vue'; import { userBrokerCompanyList } from '/@/api/admin/signer'; import { getListAll as merchantListAll } from '/@/api/admin/merchant'; export default { components: { ArrowRight, ArrowLeft }, props: { id: { type: String, default: '', }, titleText: { type: String, default: 'Add', // 默认为新增 }, }, data() { return { // 主弹窗状态 dialogVisible: true, hasLoaded: false, showMerchant: false, // 主表单数据 form: { commissionType: '', responsibleType: '', responsible: '', validStartTime: '', validEndTime: '', }, isUnlimited: false, isEndTimeDisabled: false, // 下拉选项数据 responsibleOptions: [], userBrokerCompanies: [], merchantOptions: [], // 销售区域数据源(包含ID和名称) salesAreaOptions: [ { id: 1, name: '香港' }, { id: 2, name: '澳门' }, { id: 3, name: '新加坡' }, { id: 4, name: '百慕大' }, ], // 商户列表数据 merchantList: [], currentEditIndex: -1, // 商户表单相关(适配多选) merchantFormVisible: false, isEditMerchant: false, merchantForm: { id: [], // 改为数组存储选中的商户ID(多选) name: '', // 存储选中的商户名称,用于显示 salesArea: [], // 销售区域ID数组 brokerageIds: [], // 经纪公司ID数组 brokerageText: '', // 经纪公司名称(文字) commissionRatio: null, }, salesAreaUnlimited: false, brokerageUnlimited: false, // 验证规则(调整商户选择的验证) rules: { commissionType: [{ required: true, message: '请选择提成类型', trigger: 'change' }], responsibleType: [{ required: true, message: '请选择负责人类型', trigger: 'change' }], responsible: [{ required: true, message: '请选择负责人', trigger: 'change' }], validStartTime: [{ required: true, message: '请选择有效期开始时间', trigger: 'change' }], validEndTime: [ { required: true, message: '请选择有效期结束时间', trigger: 'change', validator: (rule, value, callback) => { if (this.isUnlimited) { callback(); } else if (!value) { callback(new Error('请选择有效期结束时间')); } else { callback(); } }, }, ], }, merchantRules: { // 调整商户选择的验证规则,支持数组长度判断 id: [ { required: true, message: '请选择商户', trigger: ['blur', 'change'], validator: (rule, value, callback) => { if (Array.isArray(value) && value.length > 0) { callback(); } else { callback(new Error('请选择至少一个商户')); } }, }, ], salesArea: [ { required: true, message: '请选择销售区域或选择限', trigger: ['blur', 'change'], validator: (rule, value, callback) => { if (this.salesAreaUnlimited || value.length > 0) { callback(); } else { callback(new Error('请选择销售区域或选择限')); } }, }, ], brokerageIds: [ { required: true, message: '请选择经纪公司或选择限', trigger: ['blur', 'change'], validator: (rule, value, callback) => { if (this.brokerageUnlimited || value.length > 0) { callback(); } else { callback(new Error('请选择经纪公司或选择限')); } }, }, ], commissionRatio: [ { required: true, message: '请输入提成比例', trigger: 'blur' }, { type: 'number', min: 0, max: 100, message: '提成比例必须在0-100之间', trigger: 'blur' }, ], }, }; }, created() { this.initData(); // 加载经纪公司列表 userBrokerCompanyList().then((res) => { this.userBrokerCompanies = res.data || []; }); // 加载商户列表 merchantListAll().then((res) => { this.merchantOptions = (res.data || []).filter((item) => item.id !== 1); }); }, methods: { // 初始化数据(适配多选商户) initData() { // 模拟负责人数据 this.responsibleOptions = [ { value: 'merchant1', label: '商户1' }, { value: 'merchant2', label: '商户2' }, { value: 'operator1', label: '运营人员1' }, { value: 'operator2', label: '运营人员2' }, ]; // 模拟初始商户数据(id改为数组) this.merchantList = [ { merchantCode: 'MER001', id: [1, 2], name: '商户A、商户B', brokerageIds: ['1'], brokerageText: 'BWM经纪公司', salesArea: [1, 2], commissionRatio: 15, }, // { // merchantCode: 'MER002', // merchantId: [3], // 单个商户也用数组 // merchantNames: '商户C', // brokerageIds: [], // brokerageText: '限', // salesArea: [], // commissionRatio: 8, // }, // { // merchantCode: 'MER003', // merchantId: [4, 5], // merchantNames: '商户D、商户E', // brokerageIds: ['2'], // brokerageText: 'BIB经纪公司', // salesArea: [3], // 新加坡的ID // commissionRatio: 12, // }, ]; this.hasLoaded = true; }, // 提成类型切换 handleChannelChange(val) { this.showMerchant = val === 'channel'; }, handleChanne(val) { this.showMerchant = val !== 'operation'; }, // 有效期结束日期处理 handleEndDateChange(selectedDate) { if (selectedDate) { this.form.validEndTime = `${selectedDate} 23:59:59`; } else { this.form.validEndTime = ''; } }, // 有效期限切换 handleUnlimitedChange(val) { if (val) { this.form.validEndTime = ''; this.isEndTimeDisabled = true; } else { this.isEndTimeDisabled = false; } }, // 显示商户表单(适配多选) showMerchantForm(isEdit, row = null, index = -1) { this.isEditMerchant = isEdit; this.merchantFormVisible = true; this.currentEditIndex = index; // 重置表单 this.$nextTick(() => { if (this.$refs.merchantForm) { this.$refs.merchantForm.resetFields(); } }); if (isEdit && row) { this.merchantForm = { id: [...row.id], // 保留 ID 用于提交 name: row.name, // 显示名称,修改此处 salesArea: [...row.salesArea], brokerageIds: [...row.brokerageIds], brokerageText: row.brokerageText || '', commissionRatio: row.commissionRatio, }; this.salesAreaUnlimited = row.salesArea.length === 0; this.brokerageUnlimited = row.brokerageIds.length === 0; } else { // 新增状态:重置表单 this.merchantForm = { id: [], name: '', salesArea: [], brokerageIds: [], brokerageText: '', commissionRatio: null, }; this.salesAreaUnlimited = false; this.brokerageUnlimited = false; } }, // 选择商户后同步名称(适配多选) handleMerchantSelect(merchantIds) { if (!merchantIds || !merchantIds.length) { this.merchantForm.name = ''; return; } // 筛选所有选中的商户并拼接名称 const selectedMerchants = this.merchantOptions.filter((item) => merchantIds.includes(item.id)); this.merchantForm.name = selectedMerchants.map((item) => item.name).join('、'); }, // 选择经纪公司后同步文字名称 handleBrokerageSelect(ids) { if (!ids || ids.length === 0) { this.merchantForm.brokerageText = ''; return; } // 从所有经纪公司中筛选选中的项 const selectedBrokers = this.userBrokerCompanies.filter((item) => ids.includes(item.brokerCompanyId)); // 拼接选中的经纪公司简称 this.merchantForm.brokerageText = selectedBrokers.map((item) => item.brokerCompanyAbbr).join('、'); }, // 销售区域选择变化 handleSalesAreaChange() { if (this.merchantForm.salesArea.length > 0) { this.salesAreaUnlimited = false; } }, // 经纪公司选择变化 handleBrokerageChange() { if (this.merchantForm.brokerageIds.length > 0) { this.brokerageUnlimited = false; } }, // 销售区域限切换 handleSalesAreaUnlimited(val) { if (val) { this.merchantForm.salesArea = []; } }, // 经纪公司限切换 handleBrokerageUnlimited(val) { if (val) { this.merchantForm.brokerageIds = []; this.merchantForm.brokerageText = '限'; } }, // 保存商户数据(适配多选) saveMerchant() { this.$refs.merchantForm.validate((valid) => { if (valid) { // 处理经纪公司文字显示限状态) const brokerageText = this.brokerageUnlimited ? '限' : this.merchantForm.brokerageText; if (this.isEditMerchant && this.currentEditIndex !== -1) { // 修改操作 const updatedData = { ...this.merchantList[this.currentEditIndex], id: [...this.merchantForm.id], // 保存ID数组 name: this.merchantForm.name, // 保存名称拼接 salesArea: this.salesAreaUnlimited ? [] : [...this.merchantForm.salesArea], brokerageIds: this.brokerageUnlimited ? [] : [...this.merchantForm.brokerageIds], brokerageText, commissionRatio: this.merchantForm.commissionRatio, }; this.merchantList.splice(this.currentEditIndex, 1, updatedData); const params = { id: [...this.merchantForm.id], id: this.merchantForm.id, salesArea: this.salesAreaUnlimited ? [] : [...this.merchantForm.salesArea], brokerageIds: this.brokerageUnlimited ? [] : [...this.merchantForm.brokerageIds], commissionRatio: this.merchantForm.commissionRatio, }; console.log('9999999', params); // this.$http // .post(this.$api.merchant.config, params) // .then((res) => { // if (res.code == '1') { // this.$message.success('配置人员成功'); // this.$emit('onSuccess'); // } else { // this.$message.error(res.message); // } // }) // .catch((err) => { // this.$message.error('配置人员失败'); // this.$emit('onClose'); // }); ElMessage.success('商户修改成功'); } else { // 新增操作:生成唯一编码 const maxCode = this.merchantList.reduce((max, item) => { const num = parseInt(item.merchantCode?.replace('MER', '') || '0'); return num > max ? num : max; }, 0); const newCode = `MER${String(maxCode + 1).padStart(3, '0')}`; const newMerchant = { merchantCode: newCode, id: [...this.merchantForm.id], name: this.merchantForm.name, salesArea: this.salesAreaUnlimited ? [] : [...this.merchantForm.salesArea], brokerageIds: this.brokerageUnlimited ? [] : [...this.merchantForm.brokerageIds], brokerageText, commissionRatio: this.merchantForm.commissionRatio, }; this.merchantList.push(newMerchant); console.log('4444444444444', newMerchant); const params = { merchantCode: newCode, id: [...this.merchantForm.id], id: this.merchantForm.id, salesArea: this.salesAreaUnlimited ? [] : [...this.merchantForm.salesArea], brokerageIds: this.brokerageUnlimited ? [] : [...this.merchantForm.brokerageIds], commissionRatio: this.merchantForm.commissionRatio, }; console.log('22222222222', params); // this.$http // .post(this.$api.merchant.config, params) // .then((res) => { // if (res.code == '1') { // this.$message.success('配置人员成功'); // this.$emit('onSuccess'); // } else { // this.$message.error(res.message); // } // }) // .catch((err) => { // this.$message.error('配置人员失败'); // this.$emit('onClose'); // }); ElMessage.success('商户新增成功'); } this.merchantFormVisible = false; } }); }, // 删除商户 async deleteMerchant(index) { const result = await ElMessageBox.confirm(`确定要删除【${this.merchantList[index].name}】吗?`, '删除确认', { confirmButtonText: '确认删除', cancelButtonText: '取消', type: 'warning', }).catch(() => false); if (result) { this.merchantList.splice(index, 1); ElMessage.success('删除成功'); } }, // 保存主表单 handleSave() { this.$refs.form.validate((valid) => { if (valid) { if (this.merchantList.length === 0) { ElMessage.warning('请至少新增一条商户数据'); return; } // 构建提交数据(商户ID为数组) const submitData = { ...this.form, validEndTime: this.isUnlimited ? '' : this.form.validEndTime, merchantList: this.merchantList.map((merchant) => ({ ...merchant, id: merchant.id, // 提交ID数组 salesArea: merchant.salesArea, brokerageIds: merchant.brokerageIds, })), }; console.log('提交的数据:', submitData); ElMessage.success('保存成功'); this.$emit('onSuccess'); } }); }, // 关闭弹窗 handleDialogVisible() { this.$emit('onClose'); }, }, }; </script> <style lang="scss" scoped> ::v-deep .el-input { width: 240px; } ::v-deep .el-select { width: 240px; } .dialog-footer { display: flex; justify-content: center; margin-top: 20px; } /* 商户表单样式 */ ::v-deep .el-checkbox-group { margin-bottom: 10px; } /* 表格样式优化 */ ::v-deep .el-table { margin-bottom: 20px; } /* 操作按钮样式 */ ::v-deep .el-button--text { padding: 5px 10px; } ::v-deep .radio-style-checkbox { margin-left: 10px; .el-checkbox__inner { border-radius: 50% !important; /* 圆形边框 */ width: 16px !important; height: 16px !important; } .el-checkbox__inner::after { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 4px; height: 4px; border-radius: 50%; background-color: #ffff; opacity: 0; } &.is-checked .el-checkbox__inner::after { opacity: 1; } } .line { margin-top: -20px; margin-bottom: 23px; border-bottom: 1px solid #3333 !important; } .text-btn { color: var(--el-color-primary); } </style> this.merchantForm = { id: [...row.id], // 保留 ID 用于提交 name: row.name, // 显示名称,修改此处 salesArea: [...row.salesArea], brokerageIds: [...row.brokerageIds], brokerageText: row.brokerageText || '', commissionRatio: row.commissionRatio, };为什么点击修改商户返显的是id 改成name
09-10
<template> <div class="app-container"> <!-- 查询表单 --> <div class="filter-container"> <el-date-picker v-model="dateRange" type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 280px; margin-right: 10px" /> <el-input v-model="queryParams.userName" placeholder="员工姓名/账号" clearable style="width: 180px; margin-right: 10px" /> <el-select v-model="queryParams.deptId" placeholder="所属部门" clearable style="width: 160px" > <el-option v-for="dept in deptOptions" :key="dept.deptId" :label="dept.deptName" :value="dept.deptId" /> </el-select> <el-button type="primary" icon="el-icon-search" @click="getList"> 搜索 </el-button> <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> </div> <!-- 操作按钮 --> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" @click="openAddDialog" v-hasPermi="['system:schedule:add']" > 新增排班 </el-button> </el-col> <el-col :span="1.5"> <el-button type="danger" plain icon="el-icon-delete" :disabled="selectedSchedules.length === 0" @click="handleDelete(null)" v-hasPermi="['system:schedule:remove']" > 批量删除 </el-button> </el-col> </el-row> <!-- 排班列表 --> <el-table ref="scheduleTable" v-loading="loading" :data="list" @selection-change="handleSelectionChange" border > <el-table-column type="selection" width="50" align="center" /> <el-table-column label="员工" width="200"> <template slot-scope="scope"> <div style="display: flex; align-items: center"> <el-avatar size="32" :src="scope.row.avatar || 'https://via.placeholder.com/32'" style="margin-right: 8px" ></el-avatar> <div> <div> <strong>{{ scope.row.nickName }}</strong> </div> <div style="font-size: 12px; color: #999"> {{ scope.row.user_name }} </div> </div> </div> </template> </el-table-column> <el-table-column label="部门" prop="deptName" width="150" /> <el-table-column label="排班日期" width="120"> <template slot-scope="scope"> {{ parseTime(scope.row.scheduleDate, "{y}-{m}-{d}") }} </template> </el-table-column> <el-table-column label="班次" width="100"> <template slot-scope="scope"> <el-tag :type="getShiftType(scope.row.shiftType)"> {{ getShiftText(scope.row.shiftType) }} </el-tag> </template> </el-table-column> <el-table-column label="备注" prop="remark" min-width="120" show-overflow-tooltip /> <el-table-column label="操作" fixed="right" align="center" width="180"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleEdit(scope.row)" v-hasPermi="['system:schedule:edit']" > 修改 </el-button> <el-button size="mini" type="text" icon="el-icon-view" @click="handleViewDetail(scope.row)" > 详情 </el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['system:schedule:remove']" > 删除 </el-button> </template> </el-table-column> </el-table> <!-- 分页 --> <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList" /> <!-- 新增/编辑弹窗 --> <el-dialog :title="dialogTitle" :visible.sync="open" width="800px" append-to-body destroy-on-close @closed="resetDialogForm" > <el-form :model="tempSchedule" label-width="100px"> <!-- 员工选择 --> <el-form-item label="选择员工" required> <el-select v-model="tempSchedule.userIds" multiple filterable placeholder="请选择员工" style="width: 100%" > <el-option v-for="user in availableUserList" :key="user.userId" :label="`${user.nickName} (${user.userName})`" :value="user.user_id" /> </el-select> </el-form-item> <!-- 时间选择 --> <el-form-item label="排班时间" required> <el-date-picker v-model="tempSchedule.dates" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" value-format="yyyy-MM-dd" style="width: 100%" /> </el-form-item> <!-- 班次选择 --> <el-form-item label="班次类型" required> <el-radio-group v-model="tempSchedule.shiftType"> <el-radio label="morning">早班 08:00-16:00</el-radio> <el-radio label="afternoon">晚班 16:00-24:00</el-radio> <el-radio label="night">夜班 00:00-08:00</el-radio> <el-radio label="off">休息</el-radio> </el-radio-group> </el-form-item> <!-- 备注 --> <el-form-item label="备注"> <el-input v-model="tempSchedule.remark" type="textarea" rows="2" /> </el-form-item> </el-form> <div slot="footer" class="dialog-footer"> <el-button @click="open = false">取 消</el-button> <el-button type="primary" :loading="submitLoading" @click="submitSchedule" > 确 定 </el-button> </div> </el-dialog> <!-- 详情弹窗 --> <el-dialog title="排班详情" :visible.sync="detailOpen" width="600px" append-to-body destroy-on-close > <div style="line-height: 2" v-if="currentRow"> <p> <b>员工:</b>{{ currentRow.nickName }} ({{ currentRow.user_name }}) </p> <p><b>部门:</b>{{ currentRow.deptName }}</p> <p> <b>排班日期:</b >{{ parseTime(currentRow.scheduleDate, "{y}-{m}-{d}") }} </p> <p> <b>班次:</b> <el-tag :type="getShiftType(currentRow.shiftType)"> {{ getShiftText(currentRow.shiftType) }} </el-tag> </p> <p><b>备注:</b>{{ currentRow.remark || "-" }}</p> <p><b>创建人:</b>{{ currentRow.create_by }}</p> <p><b>创建时间:</b>{{ parseTime(currentRow.create_time) }}</p> </div> <div v-else> <el-empty description="暂无数据"></el-empty> </div> </el-dialog> </div> </template> <script> import { listUser } from "@/api/system/user"; import { listDept } from "@/api/system/dept"; import { listSchedule, addSchedule, updateSchedule, delSchedule, } from "@/api/system/schedule"; import { parseTime } from "@/utils"; // 引入工具函数 export default { name: "ScheduleManagement", data() { return { loading: false, submitLoading: false, list: [], total: 0, queryParams: { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }, dateRange: [], selectedSchedules: [], currentRow: null, open: false, detailOpen: false, dialogTitle: "", tempSchedule: { userIds: [], dates: [], shiftType: "morning", remark: "", }, deptOptions: [], allUserList: [], availableUserList: [], }; }, computed: { isSuperAdmin() { return this.$store.getters.roles.includes("admin"); }, }, created() { this.getDepts(); this.getAllUsers(); this.getList(); }, methods: { parseTime, // 注册工具方法供模板使用 getDepts() { listDept().then((res) => { this.deptOptions = res.data || []; }); }, getAllUsers() { listUser(this.queryParams).then((res) => { this.allUserList = res.rows || []; const userDeptId = this.$store.getters.deptId; this.availableUserList = this.isSuperAdmin ? this.allUserList : this.allUserList.filter((u) => u.dept_id == userDeptId); }); }, getList() { this.loading = true; const params = { ...this.queryParams, startTime: this.dateRange?.[0], endTime: this.dateRange?.[1], }; listSchedule(params) .then((res) => { this.list = res.rows || []; this.total = res.total || 0; }) .finally(() => { this.loading = false; }); }, resetQuery() { this.dateRange = []; this.queryParams = { pageNum: 1, pageSize: 10, userName: undefined, deptId: undefined, }; this.getList(); }, handleSelectionChange(selection) { this.selectedSchedules = selection; }, openAddDialog() { this.dialogTitle = "新增排班"; this.open = true; }, handleEdit(row) { this.dialogTitle = "修改排班"; this.tempSchedule = { userIds: [row.user_id], dates: [row.scheduleDate, row.scheduleDate], shiftType: row.shiftType, remark: row.remark, }; this.open = true; }, handleViewDetail(row) { this.currentRow = row; this.detailOpen = true; }, submitSchedule() { if (!this.tempSchedule.userIds.length) { this.$message.warning("请至少选择一名员工"); return; } if (!this.tempSchedule.dates || this.tempSchedule.dates.length !== 2) { this.$message.warning("请选择完整的日期范围"); return; } this.submitLoading = true; const [start, end] = this.tempSchedule.dates; const scheduleData = []; const currentDate = new Date(start); const endDate = new Date(end); while (currentDate <= endDate) { const dateStr = this.formatDate(currentDate); this.tempSchedule.userIds.forEach((userId) => { const userData = this.allUserList.find((u) => u.user_id === userId); scheduleData.push({ user_id: userId, dept_id: userData?.dept_id, schedule_date: dateStr, shift_type: this.tempSchedule.shiftType, remark: this.tempSchedule.remark, }); }); currentDate.setDate(currentDate.getDate() + 1); } addSchedule(scheduleData) .then(() => { this.$modal.msgSuccess?.("排班创建成功") || this.$message.success("排班创建成功"); this.open = false; this.getList(); }) .catch(() => { this.$message.error("保存失败,请检查网络或数据"); }) .finally(() => { this.submitLoading = false; }); }, handleDelete(row) { const ids = row ? [row.id] : this.selectedSchedules.map((s) => s.id); this.$confirm(`确认删除 ${ids.length} 条排班记录?`, "警告", { type: "warning", }).then(() => { this.loading = true; delSchedule(ids) .then(() => { this.$modal.msgSuccess?.("删除成功") || this.$message.success("删除成功"); this.getList(); }) .finally(() => { this.loading = false; }); }); }, formatDate(date) { const d = new Date(date); const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, "0"); const day = String(d.getDate()).padStart(2, "0"); return `${year}-${month}-${day}`; }, getShiftText(type) { const map = { morning: "早班", afternoon: "晚班", night: "夜班", off: "休息", }; return map[type] || "未知"; }, getShiftType(type) { return ( { morning: "success", afternoon: "warning", night: "danger", off: "info", }[type] || "" ); }, resetDialogForm() { this.tempSchedule = { userIds: [], dates: [], shiftType: "morning", remark: "", }; }, }, }; </script> <style scoped> ::v-deep .el-table th { background-color: #f5f7fa; font-weight: bold; } .mb8 { margin-bottom: 15px; } .dialog-footer { text-align: right; } </style> 点击新增->打开用户列表弹窗->多选用户->选择时间->确定新增
09-28
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

诸葛亮写代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值