Files
UserbaseFront/src/views/dept-manage/CustomDeptCard.vue
T
chenxing c39c0f83d7
build / build (push) Successful in 2m53s
feat(dept): 部门管理改为表格,系统精简为 5 列、自定义表格化并支持拖动排序
- 系统部门:卡片网格改为表格(序号/部门名称/上级/人员/状态),层级用缩进+折叠表达;
  去掉新增、排序与操作列,只保留启停与「包含子组」
- 人员列:memberCount + memberNames 前 3 个姓名 + N,Tooltip 展示完整预览,
  点击弹窗分页查看全部(/api/sysuser/List?groupId=,不传 withSub 只看直属)
- 自定义部门:卡片改表格(序号/名称/人员/状态/操作),行拖动排序沿用 customDeptSort,
  分类列表支持拖动(customDeptCategorySort),原有新增/编辑/删除/成员/上下移保留
- DeptCard.vue、CustomDeptCard.vue 标记为已废弃(无引用,可安全删除)
2026-10-23 10:31:04 +08:00

201 lines
4.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 自定义部门卡片(已被 CustomDeptPanel.vue 的表格取代,2026-10-23)。保留文件仅作参考,无任何引用,可安全删除。 -->
<template>
<article class="cdept-card" :class="{ 'is-off': !dept.enabled }">
<div class="row-1">
<span class="status-dot" :class="{ 'is-off': !dept.enabled }"></span>
<h3 class="card-name" :title="dept.name">{{ dept.name }}</h3>
<span class="sw" :class="{ 'is-off': !dept.enabled }" :title="dept.enabled ? '点击停用' : '点击启用'"
@click="emit('toggle', dept)"></span>
</div>
<div class="row-2">
<span class="sub">{{ memberText }}</span>
<span class="ops">
<i class="op" :class="{ 'is-disabled': !canMoveUp }" title="上移" @click="emit('moveUp')">↑</i>
<i class="op" :class="{ 'is-disabled': !canMoveDown }" title="下移" @click="emit('moveDown')">↓</i>
<a class="link" @click="emit('members', dept)">成员</a>
<a class="link" @click="emit('edit', dept)">编辑</a>
<a class="link danger" @click="emit('remove', dept)">删除</a>
</span>
</div>
</article>
</template>
<script lang="ts" setup>
import { computed } from "vue";
import type { CustomDepartmentVo } from "@/api/globals";
/**
* CUSTOM 部门卡片:与 SYSTEM 的 DeptCard 同款外观,但字段来自 ub_custom_department。
* 停用在管理端照常可见(灰态),软删的部门由后端列表过滤、不会走到这里。
*/
const props = defineProps<{
dept: CustomDepartmentVo;
canMoveUp?: boolean;
canMoveDown?: boolean;
}>();
const emit = defineEmits<{
(e: "toggle", dept: CustomDepartmentVo): void;
(e: "edit", dept: CustomDepartmentVo): void;
(e: "remove", dept: CustomDepartmentVo): void;
(e: "members", dept: CustomDepartmentVo): void;
(e: "moveUp"): void;
(e: "moveDown"): void;
}>();
const memberText = computed(() => {
const count = Number(props.dept?.memberCount ?? 0);
if (!props.dept?.enabled) return count ? `已停用 · ${count} 人` : "已停用 · 无成员";
return count ? `${count} 人` : "无成员(可先建部门再配人)";
});
</script>
<style scoped lang="scss">
.cdept-card {
display: flex;
flex-direction: column;
gap: 9px;
padding: 13px 14px;
background: var(--panel, #fff);
border: 1px solid var(--line, #e9edf5);
border-radius: var(--r, 10px);
box-shadow: 0 1px 2px rgba(30, 38, 53, .03);
transition: border-color .15s, box-shadow .15s;
}
.cdept-card:hover {
border-color: #dbe2fb;
box-shadow: 0 6px 18px rgba(30, 38, 53, .07);
}
.cdept-card.is-off {
background: #fbfcfd;
border-style: dashed;
}
.row-1 {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
flex: 0 0 6px;
width: 6px;
height: 6px;
border-radius: 50%;
background: var(--green, #20a162);
}
.status-dot.is-off {
background: #cbd2df;
}
.card-name {
flex: 1;
min-width: 0;
margin: 0;
font-size: 15px;
font-weight: 600;
line-height: 1.4;
color: var(--text, #1e2635);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.cdept-card.is-off .card-name {
color: var(--text-3, #98a1b2);
}
.row-2 {
display: flex;
align-items: center;
gap: 8px;
min-height: 26px;
margin-top: auto;
padding-top: 9px;
border-top: 1px dashed var(--line-2, #f0f3f9);
font-size: 12px;
color: var(--text-3, #98a1b2);
}
.row-2 .sub {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.ops {
flex: 0 0 auto;
display: inline-flex;
align-items: center;
gap: 8px;
}
.link {
color: var(--brand, #577afb);
cursor: pointer;
}
.link.danger {
color: #e54545;
}
.op {
font-style: normal;
font-size: 12px;
line-height: 18px;
width: 18px;
text-align: center;
border-radius: 4px;
color: var(--text-2, #5a6478);
cursor: pointer;
}
.op:hover {
background: #e8ecfa;
color: var(--brand, #577afb);
}
.op.is-disabled {
color: #d3d9e6;
cursor: not-allowed;
}
/* 启停开关(与 SYSTEM 卡片同一套视觉) */
.sw {
position: relative;
flex: 0 0 auto;
width: 36px;
height: 20px;
border-radius: 10px;
background: var(--brand, #577afb);
cursor: pointer;
transition: background .15s;
}
.sw::after {
content: '';
position: absolute;
top: 2px;
left: 18px;
width: 16px;
height: 16px;
border-radius: 50%;
background: #fff;
box-shadow: 0 1px 3px rgba(30, 38, 53, .22);
transition: left .15s;
}
.sw.is-off {
background: #d3d9e6;
}
.sw.is-off::after {
left: 2px;
}
</style>