|
|
@@ -0,0 +1,308 @@
|
|
|
+<template>
|
|
|
+ <div
|
|
|
+ class="leader-team"
|
|
|
+ :class="{
|
|
|
+ 'leader-team--indent': props.teamData.level != 1,
|
|
|
+ 'hide-arrow': props.teamData.level === 3,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <el-collapse-item :name="props.teamData.teamId">
|
|
|
+ <template #title>
|
|
|
+ <div
|
|
|
+ class="leader-team__title"
|
|
|
+ :class="{
|
|
|
+ 'leader-team--selected': props.teamData.teamId === curTeam?.teamId,
|
|
|
+ }"
|
|
|
+ @click.stop
|
|
|
+ @click="clickTeam"
|
|
|
+ >
|
|
|
+ <div class="leader-team__rename" v-show="showRenameTeamInput">
|
|
|
+ <el-input
|
|
|
+ v-model="inputNewTeamName"
|
|
|
+ class="leader-team__rename-input"
|
|
|
+ placeholder="为此队伍命名"
|
|
|
+ maxlength="15"
|
|
|
+ show-word-limit
|
|
|
+ ref="teamNameInputRef"
|
|
|
+ @blur="enterNewName"
|
|
|
+ @keyup.enter="$event.target.blur()"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-show="!showRenameTeamInput" class="leader-team__team-name">
|
|
|
+ {{ props.teamData.teamName }}
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="leader-team__menu-icon" @click.stop>
|
|
|
+ <img src="@/assets/icons/nine-square-grid/more.png" @click="showTeamOperation = !showTeamOperation" />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div
|
|
|
+ v-show="showTeamOperation"
|
|
|
+ class="leader-team__operation"
|
|
|
+ :class="{ 'adjust-menu-position': props.teamData.level !== 2 }"
|
|
|
+ @click.stop
|
|
|
+ >
|
|
|
+ <div v-if="props.teamData.level !== 3" @mousedown="showAddTeamDialog()" class="leader-team__operation-item">
|
|
|
+ 新建队伍
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div v-if="props.teamData.level !== 1" @click="handleDelete()" class="leader-team__operation-item">
|
|
|
+ 删除队伍
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div v-if="props.teamData.level <= 3">
|
|
|
+ <div v-for="team in props.teamData.children" :key="team.teamId">
|
|
|
+ <leaderTeam :team-data="team" :parent-id="props.teamData.teamId" @expand="emitExpandEvent" />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-collapse-item>
|
|
|
+ </div>
|
|
|
+ <AddTeam ref="addTeamRef" @emit-team-name="handleCreate" />
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup lang="ts">
|
|
|
+ import { ref, watch, nextTick } from 'vue';
|
|
|
+ import { storeToRefs } from 'pinia';
|
|
|
+ import AddTeam from './components/AddTeam.vue';
|
|
|
+ import { LeaderTeamType } from '../type';
|
|
|
+ import useTeamStore from '../store/userTeam';
|
|
|
+ import { updateEmergencyTeamInfo } from '@/api/emergency-organization/teams';
|
|
|
+
|
|
|
+ const props = defineProps<{
|
|
|
+ teamData: LeaderTeamType;
|
|
|
+ parentId: number;
|
|
|
+ }>();
|
|
|
+
|
|
|
+ const emit = defineEmits<{ (e: 'expand', collapseId: number) }>();
|
|
|
+
|
|
|
+ const indentation = `${props.teamData.level * 10}px`;
|
|
|
+
|
|
|
+ const { leaderTeamTree, curTeam, loadingTeams } = storeToRefs(useTeamStore());
|
|
|
+ const { getLeaderTeams, createTeam, deleteTeam, getSelectTeamInfo } = useTeamStore();
|
|
|
+
|
|
|
+ const showTeamOperation = ref(false);
|
|
|
+ const showRenameTeamInput = ref(false);
|
|
|
+
|
|
|
+ const teamOriginName = ref(props.teamData.teamName);
|
|
|
+ const inputNewTeamName = ref('');
|
|
|
+ const teamNameInputRef = ref();
|
|
|
+
|
|
|
+ const addTeamRef = ref<InstanceType<typeof AddTeam>>();
|
|
|
+
|
|
|
+ function handleRenameTeam() {
|
|
|
+ showRenameTeamInput.value = true;
|
|
|
+ nextTick(() => {
|
|
|
+ teamNameInputRef.value.focus();
|
|
|
+ inputNewTeamName.value = teamOriginName.value;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ async function enterNewName() {
|
|
|
+ if (inputNewTeamName.value === '' || inputNewTeamName.value === teamOriginName.value) {
|
|
|
+ showRenameTeamInput.value = false;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ loadingTeams.value = true;
|
|
|
+
|
|
|
+ const data = { id: props.teamData.teamId, teamName: inputNewTeamName.value };
|
|
|
+ await updateEmergencyTeamInfo(data);
|
|
|
+ await getLeaderTeams();
|
|
|
+ teamOriginName.value = inputNewTeamName.value;
|
|
|
+ showRenameTeamInput.value = false;
|
|
|
+
|
|
|
+ loadingTeams.value = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ function showAddTeamDialog() {
|
|
|
+ addTeamRef.value?.dialogShow();
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleCreate(teamName: string) {
|
|
|
+ createTeam(props.teamData, teamName);
|
|
|
+
|
|
|
+ // 添加完成后展开队伍
|
|
|
+ emitExpandEvent(props.teamData.teamId);
|
|
|
+ }
|
|
|
+
|
|
|
+ function handleDelete() {
|
|
|
+ deleteTeam(props.teamData);
|
|
|
+ }
|
|
|
+
|
|
|
+ let clickTimeout: any = null;
|
|
|
+ function clickTeam(event) {
|
|
|
+ // 单击事件
|
|
|
+ if (event.detail === 1) {
|
|
|
+ clickTimeout = setTimeout(() => {
|
|
|
+ if (props.teamData.teamId === leaderTeamTree.value.teamId) return;
|
|
|
+
|
|
|
+ getSelectTeamInfo(props.teamData);
|
|
|
+ }, 200);
|
|
|
+ }
|
|
|
+ // 双击事件
|
|
|
+ else if (event.detail === 2) {
|
|
|
+ clearTimeout(clickTimeout);
|
|
|
+ handleRenameTeam();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 控制新建/删除菜单的隐藏
|
|
|
+ const closeTeamOperation = (event) => {
|
|
|
+ if (event.target.className !== 'leader-team__operation-item') showTeamOperation.value = false;
|
|
|
+ if (event.target.innerText === '新建队伍') {
|
|
|
+ showTeamOperation.value = false;
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ function emitExpandEvent(collapseId: number) {
|
|
|
+ emit('expand', collapseId);
|
|
|
+ }
|
|
|
+
|
|
|
+ watch(
|
|
|
+ () => showTeamOperation.value,
|
|
|
+ (newValue) => {
|
|
|
+ newValue
|
|
|
+ ? document.addEventListener('mousedown', closeTeamOperation)
|
|
|
+ : document.removeEventListener('mousedown', closeTeamOperation);
|
|
|
+ },
|
|
|
+ );
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+ .leader-team {
|
|
|
+ .leader-team__title {
|
|
|
+ height: 38px;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ color: #333333;
|
|
|
+ border-radius: 4px;
|
|
|
+ position: relative;
|
|
|
+ cursor: default;
|
|
|
+
|
|
|
+ .leader-team__rename {
|
|
|
+ height: 32px;
|
|
|
+ width: 100%;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ background-color: #1777ff;
|
|
|
+ border-radius: 4px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 24px;
|
|
|
+ padding-right: 6px;
|
|
|
+
|
|
|
+ .leader-team__rename-input {
|
|
|
+ height: 24px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .leader-team__team-name {
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+
|
|
|
+ .leader-team__menu-icon {
|
|
|
+ visibility: hidden;
|
|
|
+ margin-left: 10px;
|
|
|
+ margin-right: 10px;
|
|
|
+
|
|
|
+ img {
|
|
|
+ height: 20px;
|
|
|
+ width: 20px;
|
|
|
+ &:hover {
|
|
|
+ background-color: rgba(255, 255, 255, 0.2);
|
|
|
+ border-radius: 4px;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover .leader-team__menu-icon {
|
|
|
+ visibility: visible;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+
|
|
|
+ .leader-team__operation {
|
|
|
+ display: block;
|
|
|
+ width: 130px;
|
|
|
+ position: absolute;
|
|
|
+ bottom: -63px;
|
|
|
+ right: 5px;
|
|
|
+ box-shadow: 0px 0px 10px 2px rgb(0, 0, 0, 0.3);
|
|
|
+ border-radius: 4px;
|
|
|
+ background: #f4f7ff;
|
|
|
+ outline: 1px solid rgba(245, 248, 255, 0.25);
|
|
|
+ z-index: 9991;
|
|
|
+
|
|
|
+ .leader-team__operation-item {
|
|
|
+ height: 31.5px;
|
|
|
+ line-height: 31.5px;
|
|
|
+ border-radius: 4px;
|
|
|
+ &:hover {
|
|
|
+ color: #fff;
|
|
|
+ background-color: #1777ff;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .adjust-menu-position {
|
|
|
+ bottom: -33px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 隐藏最后一个层级队伍的箭头icon
|
|
|
+ .hide-arrow {
|
|
|
+ .leader-team__team-name {
|
|
|
+ padding-left: 22px;
|
|
|
+ }
|
|
|
+ :deep(.el-collapse-item button) {
|
|
|
+ padding-left: 0;
|
|
|
+ cursor: auto;
|
|
|
+ }
|
|
|
+ :deep(.el-collapse-item__arrow) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ :deep(.el-collapse-item__header) {
|
|
|
+ height: 40px;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 防止最后一个队伍的操作面板不显示
|
|
|
+ :deep(.el-collapse-item__wrap) {
|
|
|
+ overflow: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 非选中队伍的名字的hover样式
|
|
|
+ .leader-team__title:not(.leader-team--selected):hover {
|
|
|
+ background-color: #cdd8ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 非选中队伍的icon的hover样式
|
|
|
+ :deep(.el-collapse-item__header:not(.el-collapse-item__header:has(.leader-team--selected)):hover) {
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: #cdd8ff;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 选中队伍的hover样式
|
|
|
+ :deep(.el-collapse-item__header:has(.leader-team--selected)) {
|
|
|
+ background-color: #1777ff;
|
|
|
+ border-radius: 4px;
|
|
|
+
|
|
|
+ .leader-team__team-name,
|
|
|
+ svg {
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .leader-team--indent {
|
|
|
+ margin-left: v-bind(indentation);
|
|
|
+ }
|
|
|
+</style>
|