diff --git a/components/panel/formSlot.vue b/components/panel/formSlot.vue index 587d417..7157e3b 100644 --- a/components/panel/formSlot.vue +++ b/components/panel/formSlot.vue @@ -258,31 +258,64 @@
选择部门
-
-
-
-
-
-
- {{ dept.teamName }} -
-
- + +
+
+
+
{{ crumb.teamName }}
+
/
+
+
+
+ + +
+
+ +
+ +
+ +
+
+
+
+
{{ dept.teamName }}
+ +
+
+
+ 暂无数据 +
+
+
+ +
+
+
+
+ {{ selectedDeptNames[sIndex] }} +
@@ -377,12 +410,11 @@ export default { deptModal: { isShow: false, }, - deptColumns: [], // 级联列:[[{id,teamName,childs}], [...]] - expandedDeptIds: [], // 当前展开路径上的部门id集合,用于级联展示 + currentDeptList: [], // 当前层级的部门列表 + deptBreadcrumb: [], // 部门导航面包屑(路径上的各级节点) selectedDeptIds: [], // 选中的部门id集合 selectedDeptNames: [], // 选中的部门名称集合 currentDeptItem: null, // 当前编辑的表单项 - columnPaddingTops: {}, // 每列的内边距顶部偏移,用于子级列和父级节点垂直对齐 roleModal: { isShow: false, }, @@ -827,54 +859,13 @@ export default { this.selectedDeptIds = []; this.selectedDeptNames = []; } - // 根据已选中的部门初始化展开路径 - this.expandedDeptIds = this.buildExpandedPath(this.deptList || [], item.deptIds || []); - this.columnPaddingTops = {}; - this.deptColumns = this.buildCascadingColumns(this.deptList || []); + // 初始化为根级列表,面包屑为空 + this.currentDeptList = [].concat(this.deptList || []); + this.deptBreadcrumb = []; this.deptModal.isShow = true; }, - // 根据已选中的部门id,构建展开路径 - buildExpandedPath(list, selectedIds) { - if (!list || list.length === 0 || !selectedIds || selectedIds.length === 0) return []; - for (let i = 0; i < list.length; i++) { - let item = list[i]; - if (selectedIds.indexOf(item.id) > -1) { - // 找到了选中的节点,返回包含该节点的路径 - return [item.id]; - } - if (item.childs && item.childs.length > 0) { - let childPath = this.buildExpandedPath(item.childs, selectedIds); - if (childPath.length > 0) { - return [item.id].concat(childPath); - } - } - } - return []; - }, - // 根据展开路径构建级联列 - buildCascadingColumns(list) { - if (!list || list.length === 0) return []; - let columns = [list]; - let currentList = list; - for (let i = 0; i < this.expandedDeptIds.length; i++) { - let expandedId = this.expandedDeptIds[i]; - let found = currentList.find(item => item.id === expandedId); - if (found && found.childs && found.childs.length > 0) { - columns.push(found.childs); - currentList = found.childs; - } else { - break; - } - } - return columns; - }, - // 判断某节点是否在当前展开路径上 - isParentExpanded(dept, colIndex) { - return this.expandedDeptIds[colIndex] === dept.id; - }, - // 点击部门项:切换选中 + 展开/收起下一级 - handleDeptClick(dept, colIndex, deptIndex) { - // 切换选中状态 + // 切换部门选中状态(点击复选框/名称区域) + toggleDeptSelect(dept) { let idx = this.selectedDeptIds.indexOf(dept.id); if (idx > -1) { this.selectedDeptIds.splice(idx, 1); @@ -883,55 +874,37 @@ export default { this.selectedDeptIds.push(dept.id); this.selectedDeptNames.push(dept.teamName); } - // 处理展开/收起:点击有子级的节点时,展开或收起其子级 - if (dept.childs && dept.childs.length > 0) { - if (this.expandedDeptIds[colIndex] === dept.id) { - // 已展开,则收起该节点及其后续展开 - this.expandedDeptIds = this.expandedDeptIds.slice(0, colIndex); - // 清除后续列的 padding-top - this.clearColumnPaddingTops(colIndex); - } else { - // 未展开或展开了其他节点,则设置当前节点为展开,并截断后续 - this.expandedDeptIds = this.expandedDeptIds.slice(0, colIndex); - this.expandedDeptIds.push(dept.id); - } - this.deptColumns = this.buildCascadingColumns(this.deptList || []); - // 下一帧滚动新展开的子级列,使其顶部与当前点击项对齐 - this.$nextTick(() => { - this.alignColumnToParent(colIndex, deptIndex); - }); - } }, - // 清除指定列之后所有列的 padding-top - clearColumnPaddingTops(colIndex) { - let newPaddingTops = {}; - Object.keys(this.columnPaddingTops).forEach(key => { - if (Number(key) <= colIndex) { - newPaddingTops[key] = this.columnPaddingTops[key]; - } - }); - this.columnPaddingTops = newPaddingTops; + // 进入子级部门列表(点击右箭头) + enterDeptLevel(dept) { + if (!dept.childs || dept.childs.length === 0) return; + this.deptBreadcrumb.push(dept); + this.currentDeptList = [].concat(dept.childs); }, - // 滚动子级列,使其顶部与父级节点垂直对齐 - alignColumnToParent(colIndex, deptIndex) { - let that = this; - let parentItemId = '#dept-item-' + colIndex + '-' + deptIndex; - let childColumnId = '#dept-column-' + (colIndex + 1); - let firstColumnId = '#dept-column-0'; - uni.createSelectorQuery().in(that).select(parentItemId).boundingClientRect(function(parentRect) { - if (!parentRect) return; - uni.createSelectorQuery().in(that).select(firstColumnId).boundingClientRect(function(firstRect) { - if (!firstRect) return; - // 计算父级节点相对于第一列顶部的偏移量 - let offset = parentRect.top - firstRect.top; - if (offset > 0) { - // 给子级列设置相同的 padding-top,使子级列第一项与父级节点垂直对齐 - let newPaddingTops = Object.assign({}, that.columnPaddingTops); - newPaddingTops[colIndex + 1] = offset; - that.columnPaddingTops = newPaddingTops; - } - }).exec(); - }).exec(); + // 通过面包屑导航到指定层级 + navigateToDeptLevel(index) { + // 点击最后一项(当前层级)不做处理 + if (index === this.deptBreadcrumb.length - 1) return; + // 截断面包屑到目标层级 + this.deptBreadcrumb = this.deptBreadcrumb.slice(0, index + 1); + let targetDept = this.deptBreadcrumb[this.deptBreadcrumb.length - 1]; + this.currentDeptList = [].concat(targetDept.childs || []); + }, + // 返回上一级 + backToParentDept() { + if (this.deptBreadcrumb.length === 0) return; + this.deptBreadcrumb.pop(); + if (this.deptBreadcrumb.length === 0) { + this.currentDeptList = [].concat(this.deptList || []); + } else { + let parentDept = this.deptBreadcrumb[this.deptBreadcrumb.length - 1]; + this.currentDeptList = [].concat(parentDept.childs || []); + } + }, + // 移除已选部门标签 + removeSelectedDept(index) { + this.selectedDeptIds.splice(index, 1); + this.selectedDeptNames.splice(index, 1); }, // 提交部门选择 submitDept() { @@ -1071,6 +1044,85 @@ export default { display: flex; flex-direction: column; } +.dept-breadcrumb { + width: 100%; + box-sizing: border-box; + border-bottom: 1px solid #f5f5f5; +} +.dept-list-scroll { + flex: 1; + width: 100%; + -webkit-overflow-scrolling: touch; +} +.dept-list-item { + display: flex; + flex-direction: row; + align-items: stretch; + height: 56px; +} +.dept-checkbox-area { + width: 56px; + height: 56px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} +.dept-content-area { + flex: 1; + display: flex; + flex-direction: row; + align-items: center; + border-bottom: 1px solid #f5f5f5; + padding-right: 12px; + min-width: 0; +} +.dept-folder-icon { + margin-right: 10px; +} +.dept-folder-bg { + width: 40px; + height: 40px; + background-color: rgba(2, 122, 255, 0.1); + color: #1890ff; + border-radius: 50%; +} +.dept-folder-bg .iconfont { + font-size: 20px; +} +.dept-content-name { + color: #333; + font-size: 15px; + flex: 1; +} +.dept-content-arrow { + font-size: 16px; + color: #cccccc; + margin-left: 8px; + flex-shrink: 0; +} +.dept-selected-wrap { + width: 100%; + box-sizing: border-box; + background-color: #fafafa; + border-top: 1px solid #f0f0f0; + padding: 12rpx 24rpx; +} +.dept-selected-scroll { + max-height: 160rpx; + overflow-y: auto; + -webkit-overflow-scrolling: touch; +} +.dept-selected-tag { + background-color: #f0f2ff; + color: #6A81FF; + padding: 6rpx 16rpx; + border-radius: 8rpx; + margin-right: 12rpx; + margin-bottom: 12rpx; + max-width: 100%; + box-sizing: border-box; +} .dept-columns-scroll { white-space: nowrap; overflow-x: auto; @@ -1094,11 +1146,7 @@ export default { min-width: 100%; } .dept-column { - width: 30vw; - min-width: 180px; - max-width: 30vw; height: 100%; - border-right: 1px solid #ddd; box-sizing: border-box; flex-shrink: 0; flex-grow: 0; diff --git a/static/css/iconfont.css b/static/css/iconfont.css index 6229aa9..73cb15a 100644 --- a/static/css/iconfont.css +++ b/static/css/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: 'iconfont'; /* Project id 4374774 */ - src: url('//at.alicdn.com/t/c/font_4374774_9mzefrjg1b8.woff2?t=1782283319059') format('woff2'), - url('//at.alicdn.com/t/c/font_4374774_9mzefrjg1b8.woff?t=1782283319059') format('woff'), - url('//at.alicdn.com/t/c/font_4374774_9mzefrjg1b8.ttf?t=1782283319059') format('truetype'); + src: url('//at.alicdn.com/t/c/font_4374774_lku5sprfdq.woff2?t=1782301009487') format('woff2'), + url('//at.alicdn.com/t/c/font_4374774_lku5sprfdq.woff?t=1782301009487') format('woff'), + url('//at.alicdn.com/t/c/font_4374774_lku5sprfdq.ttf?t=1782301009487') format('truetype'); } .iconfont { @@ -13,6 +13,10 @@ -moz-osx-font-smoothing: grayscale; } +.icon-check-circle-fill:before { + content: "\e84d"; +} + .icon-folder:before { content: "\e7d2"; } @@ -1259,5 +1263,4 @@ .icon-leftArrows:before { content: "\100c6"; -} - +} \ No newline at end of file