publish-user-select.vue 4.13 KB
<script setup lang="ts">
  import { computed, onMounted, ref } from 'vue';
  import useTagApi from '@/http/Tag';
  import { TreeNodeData } from '@arco-design/web-vue';
  import { pull, startsWith, truncate } from 'lodash';
  import useUserApi from '@/http/user';

  const publishTo = defineModel<string[]>({ default: () => [] });
  const publishCount = defineModel<number>('count', { default: 1 });

  const cancelSource = new AbortController();

  const queryCount = (role: string[]) => {
    if (cancelSource.signal.aborted) {
      cancelSource?.abort?.();
    }
    if (role.length > 0) {
      useUserApi.get({ identityRole: role, status: [0, 1], page: 1, pageSize: 1 }, { signal: cancelSource.signal }).then(({ meta }) => {
        publishCount.value = meta.total;
      });
    } else {
      publishCount.value = 0;
    }
  };

  const parentKey = { broker: 'captain', manager: 'project' };

  const handleExtCheckTrue = (key: string, parentKey: string) => {
    if (!publishTo.value.includes(key)) {
      publishTo.value.push(key);
      if (!publishTo.value.includes(parentKey)) {
        publishTo.value.push(parentKey);
      }
    }
  };

  const handleExtCheckFalse = (key: string, parentKey: string) => {
    pull(publishTo.value, key);
    if (!publishTo.value.includes(parentKey)) {
      publishTo.value.push(parentKey);
    }
  };

  const handleExtCheck = (key: string, value: boolean) => {
    // eslint-disable-next-line no-unused-expressions
    value ? handleExtCheckTrue(key, parentKey[key]) : handleExtCheckFalse(key, parentKey[key]);
    queryCount(publishTo.value);
  };

  const brokerValue = computed({
    get: (): boolean => publishTo.value.includes('broker'),
    set: (value: boolean) => handleExtCheck('broker', value),
  });

  const managerValue = computed({
    get: (): boolean => publishTo.value.includes('manager'),
    set: (value: boolean) => handleExtCheck('manager', value),
  });

  const treeValue = computed({
    get: () => publishTo.value.filter((item) => !['broker', 'manager'].includes(item)),
    set: (value) => {
      if (!value.includes('project')) {
        pull(publishTo.value, 'manager');
      }
      if (!value.includes('captain')) {
        pull(publishTo.value, 'broker');
      }
      publishTo.value = [...value, ...publishTo.value?.filter((item) => ['broker', 'manager'].includes(item))];
    },
  });

  const userAuthTags = ref<TreeNodeData[]>([]);

  const options = computed((): TreeNodeData[] => {
    return [
      { key: 'visitor', title: '注册未认证' },
      { key: 'musician', title: '音乐人', children: userAuthTags.value },
      { key: 'captain', title: '队长' },
      { key: 'project', title: '厂牌管理员' },
      { key: 'system', title: '平台管理员' },
    ];
  });

  onMounted(() => {
    useTagApi.get({ type: 4, fetchType: 'all', setColumn: ['id', 'name'] }).then(({ data }) => {
      userAuthTags.value = data.map((item) => ({ key: `musician_tag_${item.id}`, title: item.name }));
    });
  });
</script>

<template>
  <a-tree-select
    v-model="treeValue"
    :multiple="true"
    :allow-clear="true"
    :tree-checkable="true"
    tree-checked-strategy="parent"
    :fallback-option="false"
    :data="options"
    placeholder="请选择"
    @change="(value:any) => queryCount([...value,...publishTo?.filter((item) => ['broker', 'manager'].includes(item))])"
  >
    <template #label="{ data }">
      <template v-if="data.value === 'captain' && brokerValue">经纪人</template>
      <template v-else-if="data.value === 'project' && managerValue">厂牌主理人</template>
      <template v-else-if="startsWith(data.value, 'musician_tag_')">音乐人 / {{ truncate(data.label, { length: 6 }) }}</template>
      <template v-else>{{ data.label }}</template>
    </template>
    <template #tree-slot-extra="row">
      <a-checkbox v-if="row.key === 'captain'" v-model="brokerValue">仅通知经纪人</a-checkbox>
      <a-checkbox v-if="row.key === 'project'" v-model="managerValue">仅通知主理人</a-checkbox>
    </template>
  </a-tree-select>
</template>

<style>
  .arco-tree-node:hover {
    color: var(--color-text-1) !important;
    background-color: var(--color-fill-2) !important;
  }
</style>