basic-card.vue 13.9 KB
<script setup lang="ts">
  import useUserApi from '@/http/user';
  import { IconDown } from '@arco-design/web-vue/es/icon';
  import { createModalVNode } from '@/utils/createVNode';
  import { createVNode, onMounted, ref, toRef, computed } from 'vue';
  import PasswordForm from '@/views/user/info/components/password-form.vue';
  import UpdateForm from '@/views/user/info/components/update-form.vue';
  import useTagApi from '@/http/Tag';
  import { Option } from '@/types/global';
  import { User } from '@/utils/model';
  import UserImageDynamics from '@/views/user/info/components/user-image-dynamics.vue';
  import UserAudioDynamics from '@/views/user/info/components/user-audio-dynamics.vue';
  import UserVideoDynamics from '@/views/user/info/components/user-video-dynamics.vue';
  import { useRoute, useRouter } from 'vue-router';
  import { isArray } from '@/utils/is';
  import usePermission from '@/hooks/permission';

  const props = defineProps<{
    user: User & { image_dynamic_count?: number; audio_dynamic_count?: number; video_dynamic_count?: number };
  }>();
  const user = toRef(props, 'user');
  const { scopeOption, statusOption, sexOption, update, destroy, changeStatus, changePwd } = useUserApi;

  const coverVisible = ref(false);

  const authTagOptions = ref<Option[]>([]);

  onMounted(() => useTagApi.getOption({ type: 4 }).then((data) => (authTagOptions.value = data)));

  const onViewImage = () =>
    createModalVNode(() => createVNode(UserImageDynamics, { userKey: user.value.id }), {
      title: 'Ta的相册',
      titleAlign: 'center',
      closable: true,
      footer: false,
      escToClose: true,
      width: '780px',
    });

  const onViewAudio = () =>
    createModalVNode(() => createVNode(UserAudioDynamics, { userKey: user.value.id }), {
      title: 'Ta的音频',
      titleAlign: 'center',
      closable: true,
      footer: false,
      escToClose: true,
      bodyStyle: { padding: '0 !important' },
      width: '540px',
    });

  const onViewVideo = () =>
    createModalVNode(() => createVNode(UserVideoDynamics, { userKey: user.value.id }), {
      title: 'Ta的视频',
      titleAlign: 'center',
      closable: true,
      footer: false,
      escToClose: true,
      width: '780px',
    });
  const onOperation = (value: string) => {
    // eslint-disable-next-line default-case
    switch (value) {
      case 'STATUS_ON':
        createModalVNode('是否确认将该用户启用?', {
          title: '状态变更',
          onBeforeOk: (done: any) =>
            changeStatus(user.value?.id || 0, 1)
              .then(() => {
                user.value.status = 1;
                done(true);
              })
              .catch(() => done(false)),
        });
        break;
      case 'STATUS_OFF':
        createModalVNode('是否确认将该用户禁用?', {
          title: '状态变更',
          onBeforeOk: (done: any) =>
            changeStatus(user.value?.id || 0, 0)
              .then(() => {
                user.value.status = 0;
                done(true);
              })
              .catch(() => done(false)),
        });
        break;
      case 'CHANGE_PWD':
        // eslint-disable-next-line no-case-declarations
        const pwdRef = ref<InstanceType<typeof PasswordForm>>();
        createModalVNode(() => createVNode(PasswordForm, { ref: pwdRef, onRequest: (data: any) => changePwd(user.value?.id, data) }), {
          title: '重置密码',
          onBeforeOk: (done: any) =>
            pwdRef.value
              ?.onSubmit()
              .then(() => done(true))
              .catch(() => done(false)),
        });
        break;
      case 'UPDATE':
        // eslint-disable-next-line no-case-declarations
        const updateRef = ref<InstanceType<typeof UpdateForm>>();
        createModalVNode(
          () =>
            createVNode(UpdateForm, {
              ref: updateRef,
              row: user.value,
              authTagOptions: authTagOptions.value,
              onRequest: (data: any) => update(user.value?.id, data),
            }),
          {
            title: '编辑信息',
            modalClass: 'update-modal',
            onBeforeOk: (done: any) =>
              updateRef.value
                ?.onSubmit()
                .then((attribute: User) => {
                  Object.assign(user.value, attribute);
                  done(true);
                })
                .catch(() => done(false)),
          }
        );
        break;
      case 'DELETE':
        createModalVNode('是否确认将该用户注销?', {
          title: '状态变更',
          onBeforeOk: (done: any) =>
            destroy(user.value?.id)
              .then(() => {
                user.value.status = 2;
                done(true);
              })
              .catch(() => done(false)),
        });
        break;
    }
  };

  const routeName = useRoute().name as string;
  const router = useRouter();
  const checkPermission = (permission: string | string[]): boolean => {
    permission = isArray(permission) ? permission.map((item) => `${routeName}-${item}`) : `${routeName}-${permission}`;
    return usePermission().checkPermission(permission);
  };
  const hasPermission = computed(() => checkPermission(['update', 'status', 'password', 'delete']));

  const goUserDetailPage = (user: any) => {
    if (user.identity === 1) {
      return router.push({ name: 'user-singer-show', params: { id: user.id } });
    }
    if ([2, 3].includes(Number(user.identity))) {
      return router.push({ name: 'user-business-show', params: { id: user.id } });
    }
    return router.push({ name: 'user-register-show', params: { id: user.id } });
  };
</script>

<template>
  <a-card :bordered="false">
    <a-form style="margin-top: 16px" :model="user" size="small" auto-label-width>
      <a-row justify="start" align="start">
        <a-col flex="120px">
          <a-avatar :size="120" :image-url="user.avatar" />
        </a-col>
        <a-col flex="1">
          <a-row :gutter="16">
            <a-col :span="8">
              <a-form-item label="用户艺名" :show-colon="true">
                <a-typography-paragraph type="secondary" :ellipsis="{ rows: 1, showTooltip: true }">
                  {{ `${user.nick_name}(${user.real_name})` }}
                </a-typography-paragraph>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="关注服务号" :show-colon="true">
                <span v-if="user.official_status === 1">已关注</span>
                <span v-else style="color: rgba(44, 44, 44, 0.5)">未关注</span>
              </a-form-item>
            </a-col>
            <a-col :span="6">
              <a-form-item label="状态" :show-colon="true">
                {{ statusOption.find((item) => item.value === user.status)?.label }}
              </a-form-item>
            </a-col>
            <a-col :span="2">
              <a-dropdown v-if="hasPermission && [0, 1].includes(user.status)" :popup-max-height="false" @select="onOperation">
                <a-button>
                  操作
                  <icon-down style="margin-left: 4px" />
                </a-button>
                <template #content>
                  <a-doption v-if="checkPermission('status') && user.status === 0" value="STATUS_ON">启用账号</a-doption>
                  <a-doption v-if="checkPermission('status') && user.status === 1" value="STATUS_OFF">禁用账号</a-doption>
                  <a-doption v-if="checkPermission('update')" value="UPDATE">编辑信息</a-doption>
                  <a-doption v-if="checkPermission('password')" value="CHANGE_PWD">重置密码</a-doption>
                  <a-doption v-if="checkPermission('delete')" value="DELETE">注销账号</a-doption>
                </template>
              </a-dropdown>
            </a-col>
            <a-col :span="8">
              <a-form-item label="性别" :show-colon="true">
                <span v-if="user.sex === 0" style="color: rgba(44, 44, 44, 0.5)"></span>
                <span v-else>{{ sexOption.find((item) => item.value === user.sex)?.label }}</span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="邮箱" :show-colon="true">
                <span v-if="user.email">{{ user.email }}</span>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="手机号" :show-colon="true">
                <span v-if="user.phone"> {{ `(+${user.area_code}) ${user.phone}` }}</span>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="经纪人" :show-colon="true">
                <user-link v-if="user?.business" :user="user.business" />
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="用户认证" :show-colon="true">
                <span v-if="user.auth_tags?.length === 0">
                  <span style="color: rgba(44, 44, 44, 0.5)"></span>
                  <a-divider v-if="user.auth_tags && [2, 3].includes(user.identity)" direction="vertical" />
                  <span v-if="[2, 3].includes(user.identity)"> 经纪人</span>
                </span>
                <a-typography-paragraph v-else type="secondary" :ellipsis="{ rows: 1, showTooltip: true }">
                  <span v-if="user.auth_tags?.length !== 0">音乐人{{ user.auth_tags?.map((item) => `【${item.name}】`).join('') }} </span>
                  <a-divider v-if="user.auth_tags && [2, 3].includes(user.identity)" direction="vertical" />
                  <span v-if="[2, 3].includes(user.identity)"> 经纪人</span>
                </a-typography-paragraph>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="公司" :show-colon="true">
                <a-typography-paragraph v-if="user.company" type="secondary" :ellipsis="{ rows: 1, showTooltip: true }">
                  {{ user.company }}
                </a-typography-paragraph>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="常居地" :show-colon="true">
                <span v-if="!user.province && !user.city" style="color: rgba(44, 44, 44, 0.5)"></span>
                <span v-else>{{ [user.province, user.city].filter((item) => item).join('-') }}</span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="擅长曲风" :show-colon="true">
                <span v-if="user.style_tags?.length === 0" style="color: rgba(44, 44, 44, 0.5)"></span>
                <span v-else>{{ user.style_tags?.map((item) => item.name).join('、') }}</span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="权限" :show-colon="true">
                <span v-if="user.scope === 0" style="color: rgba(44, 44, 44, 0.5)"></span>
                <span v-else>{{ scopeOption.find((item) => item.value === user.scope)?.label }}</span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="Ta的相册" show-colon>
                <a-link v-if="user.image_dynamic_count" :hoverable="false" @click="onViewImage">查看</a-link>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="Ta的音频" show-colon>
                <a-link v-if="user.audio_dynamic_count" :hoverable="false" @click="onViewAudio">查看</a-link>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="Ta的视频" :show-colon="true">
                <a-link v-if="user.video_dynamic_count" :hoverable="false" @click="onViewVideo">查看</a-link>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="8">
              <a-form-item label="头部封面" show-colon>
                <a-link :hoverable="false" @click="coverVisible = !coverVisible">查看</a-link>
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item v-if="user.register_type == 2" label="来源渠道(用户推荐)" :show-colon="true">
                <a-link :hoverable="false" @click="goUserDetailPage(user.inviter)">{{ user.inviter?.nick_name }}</a-link>
              </a-form-item>
              <a-form-item v-else-if="user.register_type == 1" label="来源渠道(自行注册)" :show-colon="true">
                <span>{{ user.register_remark }}</span>
              </a-form-item>
              <a-form-item v-else label="来源渠道" :show-colon="true">
                <span style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
            <a-col :span="24">
              <a-form-item label="简介" :show-colon="true">
                <span v-if="user.intro">{{ user.intro }}</span>
                <span v-else style="color: rgba(44, 44, 44, 0.5)"></span>
              </a-form-item>
            </a-col>
          </a-row>
        </a-col>
      </a-row>
    </a-form>

    <a-image-preview
      v-model:visible="coverVisible"
      :closable="false"
      :src="`${user.cover}?x-oss-process=image/format,webp`"
      :actions-layout="[]"
    />
  </a-card>
</template>

<style scoped lang="less">
  :deep(.arco-typography) {
    text-align: left;
    margin-bottom: 0;
    width: 100%;
  }

  :deep(.arco-form-item) {
    margin-bottom: 8px;
  }
</style>