From dc7bc0db7f56e6b4f90d68166c71efe966fecb31 Mon Sep 17 00:00:00 2001 From: qiankanghui Date: Thu, 23 Apr 2026 15:18:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat(sys):=20=E6=96=B0=E5=A2=9E=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E7=AE=A1=E7=90=86=E5=92=8C=E7=94=A8=E6=88=B7=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E6=9F=A5=E7=9C=8B=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 创建accessDept API接口文件,包含成员列表、保存、更新、删除等方法 - 实现完整的部门管理界面,支持部门的增删改查操作 - 添加部门成员管理功能,支持成员的职位、上级设置 - 在用户界面添加查看部门按钮和用户部门详情弹窗 - 实现部门成员表格展示和交互功能 - 集成权限验证和数据导出功能 --- src/api/factory/accessDept.js | 7 + src/views/modules/sys/department.vue | 484 +++++++++++++++++++++++---- src/views/modules/sys/user.vue | 233 ++++++++----- 3 files changed, 562 insertions(+), 162 deletions(-) create mode 100644 src/api/factory/accessDept.js diff --git a/src/api/factory/accessDept.js b/src/api/factory/accessDept.js new file mode 100644 index 0000000..cdd332b --- /dev/null +++ b/src/api/factory/accessDept.js @@ -0,0 +1,7 @@ +import { createAPI } from '@/utils/httpRequest.js' + +export const listAccessDeptMembers = data => createAPI('/site/accessDept/listMembers', 'post', data) +export const saveAccessDeptMember = data => createAPI('/site/accessDept/saveMember', 'post', data) +export const updateAccessDeptMember = data => createAPI('/site/accessDept/updateMember', 'post', data) +export const deleteAccessDeptMember = data => createAPI('/site/accessDept/deleteMember', 'post', data) +export const listAccessDeptByUsername = data => createAPI('/site/accessDept/listByUsername', 'post', data) diff --git a/src/views/modules/sys/department.vue b/src/views/modules/sys/department.vue index 319aa35..fa1c91c 100644 --- a/src/views/modules/sys/department.vue +++ b/src/views/modules/sys/department.vue @@ -8,9 +8,9 @@ - - - + + + Query Add @@ -32,10 +32,13 @@ @@ -75,23 +85,110 @@ layout="total, sizes, prev, pager, next, jumper"> +
部门成员
+
+ + 当前部门:{{ currentDept.site }} / {{ currentDept.departmentId }} + — {{ currentDept.departmentName }} +
+
请在上方部门列表中点击一行,或使用操作列「新增成员」选择部门
+ + + + + + + + + + + + + + + + UserName + + + + + + + + + + + + + + + + + + + + + + + + Save + Cancel + + + + + - + - + + + + + Save @@ -109,13 +206,27 @@ import { departmentSearch, departmentDelete } from "@/api/department.js" +import { + listAccessDeptMembers, + saveAccessDeptMember, + updateAccessDeptMember, + deleteAccessDeptMember +} from '@/api/factory/accessDept.js' +import { searchUserList } from '@/api/taskManage/task.js' +import { isAuth } from '@/utils' + +// import { getSiteAndBuByUserName } from "@/api/auditManagement/auditIndicator.js" import {getTableDefaultListLanguage, getTableUserListLanguage} from "@/api/table.js" import {EventBus} from "../../../main"; import {updateColumnSize} from "../../../api/table"; +import ChooseListEam from '@/views/modules/common/Chooselist_eam.vue' export default { + components: { + ChooseListEam + }, watch: { searchData: { deep: true, @@ -128,10 +239,18 @@ export default { handler: function (newV, oldV) { this.modalData.departmentId = this.modalData.departmentId.toUpperCase() } + }, + memberDialogVisible (v) { + if (!v) { + this.memberPickerActive = false + } } }, data () { return { + /** 本项目不使用 BU;新建部门保存时 buNo 传此占位,后端按 site + '_' + buNo 解析 */ + departmentDefaultBuNo: '*', + userBuList: [], // 是否收藏 favorite: false, // 导出 start @@ -152,7 +271,21 @@ export default { }, responsibleDepartmentList: [], selectTypeFlag: [], - height: 200, + deptMainTableHeight: 220, + memberTableHeight: 260, + currentDept: null, + memberList: [], + memberLoading: false, + memberDialogVisible: false, + memberDialogTitle: '', + memberFormMode: 'add', + memberForm: { + username: '', + jobTitle: '', + deptManagerFlag: 'N', + superiorUsername: '' + }, + memberPickerActive: false, pageIndex: 1, pageSize: 20, totalPage: 0, @@ -182,7 +315,7 @@ export default { columnProp: 'departmentId', headerAlign: "center", align: "center", - columnLabel: 'DepartmentId', + columnLabel: 'Department Id', columnHidden: false, columnImage: false, columnSortable: false, @@ -200,7 +333,7 @@ export default { columnProp: 'departmentName', headerAlign: "center", align: "left", - columnLabel: 'DepartmentName', + columnLabel: 'Department Name', columnHidden: false, columnImage: false, columnSortable: false, @@ -209,42 +342,43 @@ export default { fixed: '', columnWidth: 120, }, - { - userId: this.$store.state.user.name, - functionId: 811020, - serialNumber: '811020Table1Site', - tableId: "811020Table1", - tableName: "部门管理表", - columnProp: 'site', - headerAlign: "center", - align: "left", - columnLabel: 'Site', - columnHidden: false, - columnImage: false, - columnSortable: false, - sortLv: 0, - status: true, - fixed: '', - columnWidth: 140, - }, - { - userId: this.$store.state.user.name, - functionId: 811020, - serialNumber: '811020Table1Bu', - tableId: "811020Table1", - tableName: "部门管理表", - columnProp: 'buNo', - headerAlign: "center", - align: "left", - columnLabel: 'BU', - columnHidden: false, - columnImage: false, - columnSortable: false, - sortLv: 0, - status: true, - fixed: '', - columnWidth: 160, - }, + // { + // userId: this.$store.state.user.name, + // functionId: 811020, + // serialNumber: '811020Table1Site', + // tableId: "811020Table1", + // tableName: "部门管理表", + // columnProp: 'site', + // headerAlign: "center", + // align: "left", + // columnLabel: 'Site', + // columnHidden: false, + // columnImage: false, + // columnSortable: false, + // sortLv: 0, + // status: true, + // fixed: '', + // columnWidth: 140, + // }, + // 本项目不使用 BU + // { + // userId: this.$store.state.user.name, + // functionId: 811020, + // serialNumber: '811020Table1Bu', + // tableId: "811020Table1", + // tableName: "部门管理表", + // columnProp: 'buNo', + // headerAlign: "center", + // align: "left", + // columnLabel: 'BU', + // columnHidden: false, + // columnImage: false, + // columnSortable: false, + // sortLv: 0, + // status: true, + // fixed: '', + // columnWidth: 160, + // }, { userId: this.$store.state.user.name, functionId: 811020, @@ -341,15 +475,14 @@ export default { trigger: ['blur','change'] } ], - buType:[ - { - required: true, - message: ' ', - trigger: ['blur','change'] - } - ], + // buType:[ + // { + // required: true, + // message: ' ', + // trigger: ['blur','change'] + // } + // ], }, - // userBuList: [], authSearch: false, authSave: false, authUpdate: false, @@ -358,9 +491,23 @@ export default { } }, + computed: { + superiorOptions () { + if (!this.memberList || !this.memberList.length) { + return [] + } + const self = (this.memberForm.username || '').trim().toLowerCase() + return this.memberList + .map(r => r.username) + .filter(u => u && u.trim().toLowerCase() !== self) + } + }, + mounted () { this.$nextTick(() => { - this.height = window.innerHeight - 210 + const h = window.innerHeight + this.deptMainTableHeight = Math.max(180, Math.floor(h * 0.32)) + this.memberTableHeight = Math.max(200, Math.floor(h * 0.4)) }) }, @@ -371,8 +518,9 @@ export default { created () { // 按钮控制 // this.getButtonAuthData() - // 获取用户的 site 和 bu + // 本项目不使用 BU // this.getSiteAndBuByUserName() + this.getDataList() // 动态列 // this.getTableUserColumn(this.$route.meta.menuId+'table1',1) @@ -381,6 +529,195 @@ export default { }, methods: { + isAuth, + clearDeptMemberSelection () { + this.currentDept = null + this.memberList = [] + this.$nextTick(() => { + if (this.$refs.deptMainTable) { + this.$refs.deptMainTable.setCurrentRow(null) + } + }) + }, + onMainDeptCurrentChange (row) { + this.currentDept = row + this.memberList = [] + if (row) { + this.loadMembers() + } + }, + onAddMemberClick (row) { + this.currentDept = row + this.$nextTick(() => { + if (this.$refs.deptMainTable) { + this.$refs.deptMainTable.setCurrentRow(row) + } + this.loadMembers().then(() => { + this.openAddMember() + }) + }) + }, + loadMembers () { + if (!this.currentDept) { + return Promise.resolve() + } + this.memberLoading = true + return listAccessDeptMembers({ + site: this.currentDept.site, + buNo: this.currentDept.buNo, + departmentId: this.currentDept.departmentId + }).then(({ data }) => { + this.memberLoading = false + if (data && data.code === 0) { + this.memberList = data.list || [] + } else { + this.memberList = [] + if (data && data.msg) { + this.$message.error(data.msg) + } + } + }).catch(() => { + this.memberLoading = false + this.memberList = [] + }) + }, + openAddMember () { + if (!this.currentDept) { + this.$message.warning('Please select a department first') + return + } + this.memberFormMode = 'add' + this.memberDialogTitle = 'Add Member' + this.memberForm = { + username: '', + jobTitle: '', + deptManagerFlag: 'N', + superiorUsername: '' + } + this.memberDialogVisible = true + }, + openEditMember (row) { + if (!this.currentDept) return + this.memberFormMode = 'edit' + this.memberDialogTitle = 'Edit Member' + const dm = (row.deptManagerFlag || 'N').toString().toUpperCase() + this.memberForm = { + username: row.username, + jobTitle: row.jobTitle || '', + deptManagerFlag: dm === 'Y' ? 'Y' : 'N', + superiorUsername: row.superiorUsername || '' + } + this.memberDialogVisible = true + }, + openMemberUserChooser () { + if (!this.currentDept || !this.currentDept.site) { + this.$message.warning('Please select a department first') + return + } + this.memberPickerActive = true + this.$nextTick(() => { + const strVal = (this.memberForm.username || '').trim() + if (this.$refs.memberBaseList) { + this.$refs.memberBaseList.init(519, strVal, '') + } + }) + }, + getMemberBaseData (val) { + if (!this.memberPickerActive) return + this.memberPickerActive = false + if (val && val.username) { + this.memberForm.username = val.username + } + }, + verifyUserExistsInSite (username) { + const u = (username || '').trim() + if (!u || !this.currentDept || !this.currentDept.site) { + return Promise.resolve(false) + } + return searchUserList({ + site: this.currentDept.site, + username: u + }).then(({ data }) => { + if (data && data.code === 0) { + const rows = data.rows || [] + return rows.some(r => (r.username || '').trim().toLowerCase() === u.toLowerCase()) + } + return false + }).catch(() => false) + }, + submitMember () { + if (!this.currentDept) return + const username = (this.memberForm.username || '').trim() + if (!username) { + this.$message.warning('Please pick an account (click Account)') + return + } + const payload = { + site: this.currentDept.site, + buNo: this.currentDept.buNo, + departmentId: this.currentDept.departmentId, + username, + jobTitle: this.memberForm.jobTitle || '', + deptManagerFlag: this.memberForm.deptManagerFlag === 'Y' ? 'Y' : 'N', + superiorUsername: this.memberForm.superiorUsername || '' + } + const doSave = () => { + const req = this.memberFormMode === 'add' ? saveAccessDeptMember(payload) : updateAccessDeptMember(payload) + req.then(({ data }) => { + if (data && data.code === 0) { + this.$message.success('Saved') + this.memberDialogVisible = false + this.loadMembers() + } else { + this.$message.error((data && data.msg) || 'Save failed') + } + }).catch(e => { + const msg = (e.response && e.response.data && e.response.data.msg) || e.message || 'Save failed' + this.$message.error(msg) + }) + } + if (this.memberFormMode === 'add') { + this.verifyUserExistsInSite(username).then(exists => { + if (!exists) { + this.$message.warning('User does not exist or has no access to this site') + return + } + const dup = this.memberList.some(m => (m.username || '').trim().toLowerCase() === username.toLowerCase()) + if (dup) { + this.$message.warning('This member is already in the department') + return + } + doSave() + }) + return + } + doSave() + }, + removeMember (row) { + if (!this.currentDept) return + this.$confirm('确定从该部门移除「' + row.username + '」?', '提示', { + confirmButtonText: '确定', + cancelButtonText: '取消', + type: 'warning' + }).then(() => { + deleteAccessDeptMember({ + site: this.currentDept.site, + buNo: this.currentDept.buNo, + departmentId: this.currentDept.departmentId, + username: row.username + }).then(({ data }) => { + if (data && data.code === 0) { + this.$message.success('已删除') + this.loadMembers() + } else { + this.$message.error((data && data.msg) || '删除失败') + } + }).catch(e => { + const msg = (e.response && e.response.data && e.response.data.msg) || e.message || '删除失败' + this.$message.error(msg) + }) + }).catch(() => {}) + }, handleColumnResize(newWidth, oldWidth, column, event){ let inData= this.columnList.filter(item => item.columnProp === column.property)[0] inData.columnWidth=newWidth @@ -392,6 +729,16 @@ export default { // }) }, + // getSiteAndBuByUserName () { + // let tempData = { + // username: this.$store.state.user.name + // } + // getSiteAndBuByUserName(tempData).then(({ data }) => { + // if (data.code === 0) { + // this.userBuList = data.rows + // } + // }) + // }, //导出excel @@ -430,6 +777,7 @@ export default { this.pageIndex = data.page.currPage this.pageSize = data.page.pageSize this.totalPage = data.page.totalCount + this.clearDeptMemberSelection() } }) }, @@ -451,6 +799,7 @@ export default { this.pageIndex = data.page.currPage this.pageSize = data.page.pageSize this.totalPage = data.page.totalCount + this.clearDeptMemberSelection() } }) }, @@ -482,8 +831,7 @@ export default { this.modalData = { flag: '1', site: this.$store.state.user.site, - bu: '', - buNo: '', + bu: this.departmentDefaultBuNo, departmentId: '', departmentName: '', createBy: this.$store.state.user.name, @@ -494,12 +842,10 @@ export default { }, updateModal (row) { - const buValue = row.buNo || row.bu || ''; this.modalData = { flag: '2', site: row.site, - bu: buValue, - buNo: buValue, + bu: row.buNo != null && row.buNo !== '' ? row.buNo : this.departmentDefaultBuNo, departmentId: row.departmentId, departmentName: row.departmentName, createBy: this.$store.state.user.name, @@ -548,16 +894,14 @@ export default { this.$message.warning('请输入工厂!') return } - if (this.modalData.bu === '' || this.modalData.bu == null) { - this.$message.warning('请输入BU!') - return - } + // 本项目不使用 BU,buNo 使用 departmentDefaultBuNo(默认 *) + const buNoPart = (this.modalData.bu === '' || this.modalData.bu == null) ? this.departmentDefaultBuNo : this.modalData.bu // 构建后端期望的数据格式 let saveData = { ...this.modalData, - // 将site和buNo合并成bu字段,后端会进行分割处理 - bu: `${this.modalData.site}_${this.modalData.bu}` + // 将 site 与 buNo 合并成 bu,后端 split 解析(Java 不能用尾部空 buNo) + bu: `${this.modalData.site}_${buNoPart}` }; if (this.modalData.flag === '1') { diff --git a/src/views/modules/sys/user.vue b/src/views/modules/sys/user.vue index 64fc86f..6a66bfb 100644 --- a/src/views/modules/sys/user.vue +++ b/src/views/modules/sys/user.vue @@ -12,6 +12,7 @@ {{ buttons.add || '新增' }} {{ buttons.factoryAuthorization || '工厂授权' }} {{ buttons.buAuthorization || 'BU授权' }} + {{ buttons.viewUserDept || '查看部门' }} {{ buttons.deptAuthorization || '部门授权' }} {{ buttons.businessRoleAuthorization || '岗位' }} @@ -180,6 +181,33 @@ + + + + + + + + + + + + + + 关闭 + + import {getSiteList, addUserSite, delUserSite, getSite, getBuList, addUserBu, delUserBu, getBu, getDeptList, addUserDept, delUserDept, getDept, getBusinessRole, getBusinessRoleList, addUserBusinessRole, delUserBusinessRole} from '@/api/factory/site.js' -import {searchAccessBuList,saveAccessBU,saveBusinessRole} from '@/api/base/site.js' +import { listAccessDeptByUsername } from '@/api/factory/accessDept.js' +import {saveAccessBU, saveBusinessRole} from '@/api/base/site.js' import AddOrUpdate from './user-add-or-update' -import {getUserBusinessRoleList, saveUserBusinessRole,} from '@/api/auditManagement/auditType.js' -import {getUserSpecialSecurity, saveUserSpecialSecurity, updateUserSpecialSecurity} from '@/api/factory/userSpecialSecurity.js' -import {debounce, throttle} from "../../../utils/common"; -import {searchFunctionButtonList} from "@/api/sysLanguage.js" +import {saveUserBusinessRole} from '@/api/auditManagement/auditType.js' +import {updateUserSpecialSecurity} from '@/api/factory/userSpecialSecurity.js' +import {throttle} from '../../../utils/common' +import {searchFunctionButtonList} from '@/api/sysLanguage.js' import {userFavoriteList, saveUserFavorite, removeUserFavorite} from '@/api/userFavorite.js' export default { - data() { + data () { return { // 是否收藏 favorite: false, @@ -655,67 +684,67 @@ export default { transferData: [], checked: [], inputSearch1: '审核权限', - //设置 + // 设置 setUp: { reviewFlag: false, - saveButton: false, + saveButton: false }, dataForm: { userName: '', - userDisplay:'' + userDisplay: '' }, columnList: [ { userId: this.$store.state.user.name, serialNumber: 'security' + this.$route.meta.menuId + 'securitydesc', tableId: this.$route.meta.menuId + 'security', - tableName: "securityTable", - columnProp: "securitydesc", - headerAlign: "center", - align: "left", - columnLabel: "参数描述", + tableName: 'securityTable', + columnProp: 'securitydesc', + headerAlign: 'center', + align: 'left', + columnLabel: '参数描述', columnHidden: false, columnImage: false, columnWidth: 70, columnSortable: false, sortLv: 0, status: true, - fixed: '', + fixed: '' }, { userId: this.$store.state.user.name, serialNumber: 'security' + this.$route.meta.menuId + 'securitydesc', tableId: this.$route.meta.menuId + 'security', - tableName: "securityTable", - columnProp: "module", - headerAlign: "center", - align: "left", - columnLabel: "模块", + tableName: 'securityTable', + columnProp: 'module', + headerAlign: 'center', + align: 'left', + columnLabel: '模块', columnHidden: false, columnImage: false, columnSortable: false, columnWidth: 20, sortLv: 0, status: true, - fixed: '', + fixed: '' }, { userId: this.$store.state.user.name, serialNumber: 'security' + this.$route.meta.menuId + 'securitydesc', tableId: this.$route.meta.menuId + 'security', - tableName: "securityTable", - columnProp: "itemvalue", - headerAlign: "center", - align: "center", - columnLabel: "参数值", + tableName: 'securityTable', + columnProp: 'itemvalue', + headerAlign: 'center', + align: 'center', + columnLabel: '参数值', columnHidden: true, columnImage: false, columnSortable: false, columnWidth: 10, sortLv: 0, status: true, - fixed: '', - }, + fixed: '' + } ], buttons: { cz: '操作', @@ -727,6 +756,7 @@ export default { factoryAuthorization: '工厂授权', buAuthorization: 'BU授权', deptAuthorization: '部门授权', + viewUserDept: '查看部门', businessRoleAuthorization: '岗位', createTime: '创建时间', username: '用户账号', @@ -752,10 +782,10 @@ export default { dataListLoading: false, dataListSelections: [], addOrUpdateVisible: false, - selectBUList:[], - buList:[], - siteList1:[], - siteList2:[], + selectBUList: [], + buList: [], + siteList1: [], + siteList2: [], siteSelections1: [], siteSelections2: [], siteAddModal: false, @@ -765,8 +795,8 @@ export default { sitename: '', active: '' }, - buList1:[], - buList2:[], + buList1: [], + buList2: [], buSelections1: [], buSelections2: [], buAddModal: false, @@ -777,6 +807,9 @@ export default { active: '', username: '' }, + userDeptModalVisible: false, + userDeptList: [], + userDeptLoading: false, deptData: { site: '', buNo: '', @@ -785,15 +818,15 @@ export default { active: '', username: '' }, - deptList1:[], - deptList2:[], + deptList1: [], + deptList2: [], deptSelections1: [], deptSelections2: [], deptAddModal: false, - selectBusinessRoleList:[], - businessRoleList:[], - businessRoleList1:[], - businessRoleList2:[], + selectBusinessRoleList: [], + businessRoleList: [], + businessRoleList1: [], + businessRoleList2: [], businessRoleSelections1: [], businessRoleSelections2: [], businessRoleAddModal: false, @@ -804,24 +837,23 @@ export default { roleDesc: '', active: '', username: '' - }, + } } - }, components: { AddOrUpdate }, - activated() { + activated () { this.getDataList() }, - mounted() { + mounted () { this.favoriteIsOk() this.$nextTick(() => { - this.securityHeight = window.innerHeight - 300; - this.height = window.innerHeight - 200; + this.securityHeight = window.innerHeight - 300 + this.height = window.innerHeight - 200 }) }, - computed:{ + computed: { adminUser () { return this.$store.state.user.id === 1 } @@ -845,7 +877,7 @@ export default { favoriteFunction () { let userFavorite = { userId: this.$store.state.user.id, - functionId: this.$route.meta.menuId, + functionId: this.$route.meta.menuId } if (this.favorite) { // 取消收藏 @@ -913,7 +945,7 @@ export default { this.siteList2 = data.row2 }) this.siteAddModal = true - //this.searchSiteList() + // this.searchSiteList() }, /** @@ -952,7 +984,7 @@ export default { // 添加site addSite () { - if(this.siteSelections1 == null || this.siteSelections1.length === 0){ + if (this.siteSelections1 == null || this.siteSelections1.length === 0) { this.$message.warning('请选择可选工厂!') return } @@ -977,7 +1009,7 @@ export default { // 删除site deleteSite () { - if(this.siteSelections2 == null || this.siteSelections2.length === 0){ + if (this.siteSelections2 == null || this.siteSelections2.length === 0) { this.$message.warning('请选择已有工厂!') return } @@ -1104,6 +1136,29 @@ export default { } }) }, + viewUserDept () { + if (!this.selectUser || !this.selectUser.username) { + this.$message.warning('请先在列表中选中用户') + return + } + this.userDeptLoading = true + this.userDeptList = [] + this.userDeptModalVisible = true + listAccessDeptByUsername({ username: this.selectUser.username }).then(({ data }) => { + this.userDeptLoading = false + if (data && data.code === 0) { + this.userDeptList = data.list || [] + } else { + this.userDeptList = [] + if (data && data.msg) { + this.$message.error(data.msg) + } + } + }).catch(() => { + this.userDeptLoading = false + this.userDeptList = [] + }) + }, // 授权部门 deptAuthorize () { @@ -1230,11 +1285,11 @@ export default { } }) }, - //可选角色 + // 可选角色 businessRoleClickRow1 (row) { this.$refs.businessRoleTable1.toggleRowSelection(row) }, - //已有角色 + // 已有角色 businessRoleClickRow2 (row) { this.$refs.businessRoleTable2.toggleRowSelection(row) }, @@ -1244,7 +1299,7 @@ export default { selectionBusinessRole2 (val) { this.businessRoleSelections2 = val }, - //添加角色 + // 添加角色 addBusinessRole () { if (this.businessRoleSelections1 == null || this.businessRoleSelections1.length === 0) { this.$message.warning('请选择可选角色!') @@ -1268,7 +1323,7 @@ export default { } }) }, - //删除角色 + // 删除角色 deleteBusinessRole () { if (this.businessRoleSelections2 == null || this.businessRoleSelections2.length === 0) { this.$message.warning('请选择已有角色!') @@ -1293,26 +1348,23 @@ export default { }) }, - - - saveBuAssessSite () { - if(this.selectBUList.length == 0){ - this.$message.warning("请选择BU") - return false; + if (this.selectBUList.length == 0) { + this.$message.warning('请选择BU') + return false } - let inList=[]; + let inList = [] for (let i = 0; i < this.selectBUList.length; i++) { - let inData={ - site:this.$store.state.user.site, - username:this.selectUser.username, - buNo:this.selectBUList[i] + let inData = { + site: this.$store.state.user.site, + username: this.selectUser.username, + buNo: this.selectBUList[i] } inList.push(inData) } saveAccessBU(inList).then(({data}) => { if (data && data.code === 0) { - this.$message.success( '操作成功') + this.$message.success('操作成功') this.buVisible = false } else { this.$message.error(data.msg) @@ -1322,22 +1374,22 @@ export default { // 保存选中的授权角色 saveBusinessRoleSite () { - if(this.selectBusinessRoleList.length==0){ - this.$message.warning("请选择角色") - return false; + if (this.selectBusinessRoleList.length == 0) { + this.$message.warning('请选择角色') + return false } - let businessRole=[]; + let businessRole = [] for (let i = 0; i < this.selectBusinessRoleList.length; i++) { - let inData={ - site:this.$store.state.user.site, - username:this.selectUser.username, - roleNo:this.selectBusinessRoleList[i] + let inData = { + site: this.$store.state.user.site, + username: this.selectUser.username, + roleNo: this.selectBusinessRoleList[i] } businessRole.push(inData) } saveBusinessRole(businessRole).then(({data}) => { if (data && data.code === 0) { - this.$message.success( '操作成功') + this.$message.success('操作成功') this.roleVisible = false } else { this.$message.error(data.msg) @@ -1345,8 +1397,6 @@ export default { }) }, - - // 选中行 handleCurrentChange (val) { this.selectUser = val @@ -1358,24 +1408,24 @@ export default { let currentList = this.checked // 当前未选择记录 if (currentList.length == 0) { - this.$confirm("当前未选择记录,是否继续?", '删除提示', { + this.$confirm('当前未选择记录,是否继续?', '删除提示', { confirmButtonText: '确定', - cancelButtonText: '取消', + cancelButtonText: '取消' }).then(() => { let data = { - userId: this.currentData.userId, + userId: this.currentData.userId } saveList.push(data) this.saveUserBusinessRole(saveList) }).catch(() => { - return + }) } else { for (let i = 0; i < currentList.length; i++) { let data = { userId: this.currentData.userId, roleItemNo: currentList[i], - selectFlag: 'Y', + selectFlag: 'Y' } saveList.push(data) } @@ -1397,7 +1447,6 @@ export default { }) }, - // 获取数据列表 getDataList: throttle(function () { this.dataListLoading = true @@ -1474,14 +1523,14 @@ export default { }) }, - test() { + test () { let dto = { - qty:100, - name:'张三' + qty: 100, + name: '张三' } this.$http({ url: this.$http.adornUrl('/pms/test/getTdo1'), - method: 'get', + method: 'get' }).then(({data}) => { if (data && data.code === 0) { } else { @@ -1490,7 +1539,7 @@ export default { }) this.$http({ url: this.$http.adornUrl('/qm/test/list'), - method: 'get', + method: 'get' }).then(({data}) => { if (data && data.code === 0) { } else { @@ -1498,11 +1547,11 @@ export default { } }) }, - closeDialog() { + closeDialog () { this.$refs.addOrUpdate.closeDialog() - }, + } }, - created() { + created () { this.getFunctionButtonList() } } From f06a87168c2d494f7f450e502096e4e28ddb2ab2 Mon Sep 17 00:00:00 2001 From: qiankanghui Date: Fri, 24 Apr 2026 14:28:44 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(home):=20=E6=B7=BB=E5=8A=A0=E4=BE=9B?= =?UTF-8?q?=E5=BA=94=E5=95=86=E6=96=87=E6=A1=A3=E5=88=B0=E6=9C=9F=E6=8F=90?= =?UTF-8?q?=E9=86=92=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 home.vue 页面实现代办清单展示 - 集成供应商文档上传到期提醒功能 - 实现合同续签请求提醒功能 - 添加 API 接口支持文档和合同提醒查询 - 创建供应商合同续签请求管理页面 - 实现点击卡片跳转到相应供应商列表功能 - 添加悬停动画效果和视觉反馈机制 --- src/api/srm/srmSupplier.js | 2 + src/views/common/home.vue | 395 +++++++++++++++--- .../srmSupplier/supplierContractRequest.vue | 32 +- .../modules/srmSupplier/supplierList.vue | 50 ++- 4 files changed, 423 insertions(+), 56 deletions(-) diff --git a/src/api/srm/srmSupplier.js b/src/api/srm/srmSupplier.js index 92c4b11..c1fd3ea 100644 --- a/src/api/srm/srmSupplier.js +++ b/src/api/srm/srmSupplier.js @@ -2,6 +2,8 @@ import { createAPI } from '@/utils/httpRequest.js' export const searchSrmSupplierList = data => createAPI('/srmSupplier/searchSrmSupplierList', 'POST', data) +export const supplierDocExpireReminder = data => createAPI('/srmSupplier/supplierDocExpireReminder', 'POST', data || {}) +export const supplierContractRequestExpireReminder = data => createAPI('/srmSupplier/supplierContractRequestExpireReminder', 'POST', data || {}) export const searchSupplierGroupRequestList = data => createAPI('/srmSupplier/searchSupplierGroupRequestList', 'POST', data) export const getSupplierGroupRequestList = data => createAPI('/srmSupplier/getSupplierGroupRequestList', 'POST', data) export const createNewSupplierRequest = data => createAPI('/srmSupplier/createNewSupplierRequest', 'POST', data) diff --git a/src/views/common/home.vue b/src/views/common/home.vue index 3ae1d22..f764fb2 100644 --- a/src/views/common/home.vue +++ b/src/views/common/home.vue @@ -1,70 +1,363 @@ - + 100% { + transform: translate(-50%, -50%) scale(1.28); + opacity: 0; + border-color: rgba(56, 189, 248, 0); + } +} + +.tech-card__grid { + position: absolute; + inset: 0; + z-index: 0; + border-radius: inherit; + opacity: 0.35; + background-image: + linear-gradient(rgba(148, 163, 184, 0.12) 1px, transparent 1px), + linear-gradient(90deg, rgba(148, 163, 184, 0.08) 1px, transparent 1px); + background-size: 18px 18px; + pointer-events: none; +} + +.tech-card--active { + border-color: rgba(14, 165, 233, 0.42); + box-shadow: + 0 0 0 1px rgba(56, 189, 248, 0.12), + 0 6px 20px rgba(15, 23, 42, 0.08), + 0 0 20px rgba(14, 165, 233, 0.08); +} + +.home-reminder-card.is-clickable { + cursor: pointer; +} + +.tech-card.is-clickable:hover { + transform: translateY(-4px); + border-color: var(--tech-border-hover); + box-shadow: + 0 0 0 1px rgba(56, 189, 248, 0.2), + 0 8px 28px rgba(15, 23, 42, 0.08), + 0 0 32px rgba(56, 189, 248, 0.12); +} +.home-reminder-card__title { + position: relative; + z-index: 3; + font-size: 14px; + font-weight: 600; + color: #334155; + line-height: 1.45; +} + +.home-reminder-card__count { + position: relative; + z-index: 3; + font-size: 36px; + font-weight: 800; + font-variant-numeric: tabular-nums; + margin-top: 14px; + line-height: 1; + color: var(--home-count-color); +} + +.home-reminder-card:not(.tech-card--active) .home-reminder-card__count { + color: var(--home-count-muted); +} + +.home-reminder-card__hint { + position: relative; + z-index: 3; + font-size: 11px; + margin-top: 12px; + color: #64748b; + letter-spacing: 0.06em; + opacity: 0.95; +} + +.home-reminder-card__meta { + font-size: 12px; + color: #64748b; + margin-top: 6px; +} + diff --git a/src/views/modules/srmSupplier/supplierContractRequest.vue b/src/views/modules/srmSupplier/supplierContractRequest.vue index fd0a41b..3d66182 100644 --- a/src/views/modules/srmSupplier/supplierContractRequest.vue +++ b/src/views/modules/srmSupplier/supplierContractRequest.vue @@ -466,13 +466,35 @@ export default { this.requestModelData.supplierNo = this.requestModelData.supplierNo.toUpperCase() } }, + '$route.query.contractExpireRequestIds'(val, oldVal) { + if (val === oldVal) return + if (this._suppressContractExpireRouteWatch) { + this._suppressContractExpireRouteWatch = false + return + } + this.loadMainOrReminder() + } }, mounted() { this.$nextTick(() => { this.height = window.innerHeight - 220; + this.loadMainOrReminder() }) }, methods: { + loadMainOrReminder () { + const raw = this.$route.query.contractExpireRequestIds + if (raw !== undefined && raw !== null && String(raw).trim() !== '') { + const ids = String(raw).split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n)) + if (ids.length) { + this.$set(this.searchData, 'contractRequestIdList', ids) + this.pageIndex = 1 + this.getMainData({ clearReminderIdFilterAfter: true }) + return + } + } + this.getMainData() + }, // 获取基础数据列表S getBaseList(val, type) { this.tagNo = val @@ -505,7 +527,8 @@ export default { } } }, - getMainData(){ + getMainData (opts) { + const clearReminderIdFilterAfter = opts && opts.clearReminderIdFilterAfter === true this.searchData.limit = this.pageSize this.searchData.page = this.pageIndex getContractRequestList(this.searchData).then(({data}) => { @@ -514,6 +537,13 @@ export default { this.pageIndex = data.page.currPage this.pageSize = data.page.pageSize this.totalPage = data.page.totalCount + if (clearReminderIdFilterAfter) { + this.$delete(this.searchData, 'contractRequestIdList') + const q = Object.assign({}, this.$route.query) + delete q.contractExpireRequestIds + this._suppressContractExpireRouteWatch = true + this.$router.replace({ name: this.$route.name, query: q, params: this.$route.params }) + } } this.dataListLoading = false }) diff --git a/src/views/modules/srmSupplier/supplierList.vue b/src/views/modules/srmSupplier/supplierList.vue index ad8530c..1c2d127 100644 --- a/src/views/modules/srmSupplier/supplierList.vue +++ b/src/views/modules/srmSupplier/supplierList.vue @@ -1099,9 +1099,33 @@ export default { mounted () { this.$nextTick(() => { this.height = (window.innerHeight - 220) / 2 + this.loadMainOrReminder() }) }, + watch: { + '$route.query.docExpireSupplierIds'(val, oldVal) { + if (val === oldVal) return + if (this._suppressDocExpireRouteWatch) { + this._suppressDocExpireRouteWatch = false + return + } + this.loadMainOrReminder() + } + }, methods: { + loadMainOrReminder () { + const raw = this.$route.query.docExpireSupplierIds + if (raw !== undefined && raw !== null && String(raw).trim() !== '') { + const ids = String(raw).split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n)) + if (ids.length) { + this.$set(this.searchData, 'supplierIdList', ids) + this.pageIndex = 1 + this.getMainData({ clearReminderIdFilterAfter: true }) + return + } + } + this.getMainData() + }, getBaseList (val, type) { this.tagNo = val this.$nextTick(() => { @@ -1156,7 +1180,8 @@ export default { this.currentSupplier.deliveryTerm = val.DeliveryTermID } }, - getMainData () { + getMainData (opts) { + const clearReminderIdFilterAfter = opts && opts.clearReminderIdFilterAfter === true this.searchData.limit = this.pageSize this.searchData.page = this.pageIndex searchSrmSupplierList(this.searchData).then(({data}) => { @@ -1165,14 +1190,31 @@ export default { this.pageIndex = data.page.currPage this.pageSize = data.page.pageSize this.totalPage = data.page.totalCount - // 判断是否全部存在数据 + this.$nextTick(() => { + if (this.$refs.mainTable) { + this.$refs.mainTable.clearSelection() + } + this.mainTableSelections = [] + }) + if (clearReminderIdFilterAfter) { + this.activeName = 'documents' + } + //判断是否全部存在数据 if (this.mainDataList.length > 0) { - // 设置选中行 + //设置选中行 this.$refs.mainTable.setCurrentRow(this.mainDataList[0]) this.changeData(this.mainDataList[0]) - } else { + + }else { this.changeData(null) } + if (clearReminderIdFilterAfter) { + this.$delete(this.searchData, 'supplierIdList') + const q = Object.assign({}, this.$route.query) + delete q.docExpireSupplierIds + this._suppressDocExpireRouteWatch = true + this.$router.replace({ name: this.$route.name, query: q, params: this.$route.params }) + } } this.dataListLoading = false })