role-select.vue 4.4 KB
<script setup lang="ts">
  import { computed, onMounted, ref } from 'vue';
  import useTagApi from '@/http/Tag';
  import { TreeNodeData, TreeSelect, Checkbox } from '@arco-design/web-vue';
  import { pull, startsWith, truncate, reject, find } from 'lodash';

  const formValue = defineModel<string[]>({ default: () => [] });
  const parentKey = { broker: 'captain', manager: 'project' };

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

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

  const handleExtCheck = (key: string, value: boolean) =>
    value ? handleExtCheckTrue(key, parentKey[key]) : handleExtCheckFalse(key, parentKey[key]);

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

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

  const treeValue = computed({
    get: () => {
      const values = formValue.value.filter((item) => !['broker', 'manager'].includes(item));

      if (formValue.value.includes('broker') && !formValue.value.includes('captain')) {
        values.push('captain');
      }

      if (formValue.value.includes('manager') && !formValue.value.includes('project')) {
        values.push('project');
      }

      return values;
    },
    set: (value) => {
      if (!value.includes('project')) {
        pull(formValue.value, 'manager');
      }

      if (!value.includes('captain')) {
        pull(formValue.value, 'broker');
      }
      const values = formValue.value?.filter((item) => ['broker', 'manager'].includes(item));

      formValue.value = [...reject(value, (item) => values?.map((item) => parentKey[item]).includes(item)), ...values];
    },
  });

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

  const options = computed((): TreeNodeData[] => {
    return [
      { key: 'public', title: '未登录' },
      { 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 }));
    });
  });

  defineExpose({
    formatRole: (role: string[]) => {
      const values = [...options.value, { key: 'broker', title: '经纪人' }, { key: 'manager', title: '厂牌主理人' }];

      return role
        .map((item) => {
          if (!startsWith(item, 'musician_tag_')) {
            return find(values, { key: item })?.title;
          }

          const tagTitle = find(userAuthTags.value, { key: item })?.title;

          if (tagTitle) {
            return `音乐人 / ${tagTitle}`;
          }

          return tagTitle;
        })
        .filter((item) => item?.length !== 0)
        .join('、');
    },
  });
</script>

<template>
  <TreeSelect
    v-model="treeValue"
    :multiple="true"
    :allow-clear="true"
    :tree-checkable="true"
    tree-checked-strategy="parent"
    :fallback-option="false"
    :data="options"
    placeholder="请选择"
  >
    <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">
      <Checkbox v-if="row.key === 'captain'" v-model="brokerValue">仅通知经纪人</Checkbox>
      <Checkbox v-if="row.key === 'project'" v-model="managerValue">仅通知主理人</Checkbox>
    </template>
  </TreeSelect>
</template>

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