index.vue 9.38 KB
<script setup lang="ts" name="audition-activity">
import { computed, createVNode, onMounted, ref } from 'vue';
import { AnyObject, AttributeData } from '@/types/global';
import useLoading from '@/hooks/loading';
import useActivityApi, { useApply } from '@/api/activity';
import NumberTableColumn from '@/components/filter/number-table-column.vue';
import { Message, TableData } from '@arco-design/web-vue';
import EnumTableColumn from '@/components/filter/enum-table-column.vue';
import { createInputVNode, createModalVNode } from '@/utils/createVNode';

import DemoForm from '@/views/audition/demo-apply/components/form-content.vue';
import ActivityForm from '@/views/audition/activity-apply/components/form-content.vue';
import DateTableColumn from '@/components/filter/date-table-column.vue';
import ActivityTableColumn from '@/components/filter/activity-table-column.vue';
import { useSelectionStore } from '@/store';
import { Project } from '@/types/project';
import { findIndex } from 'lodash';
import { promiseToBoolean } from '@/utils';

const props = defineProps<{
  initFilter?: AttributeData;
  hideSearchItem?: string[];
  hideTool?: boolean;
  hideCreate?: boolean;
  exportName?: string;
  queryHook?: () => void;
}>();

const { statusOption, get, getExport, update, destroy, changeStatus } = useActivityApi;
const { loading, setLoading } = useLoading(false);

const filter = ref<AttributeData>({});
const tableRef = ref();

const canCreate = computed(() => {
  return findIndex(useSelectionStore().projectOptions, (item) => item.is_can_demo_apply === 1) !== -1;
});

const onQuery = async (params: object) => {
  setLoading(true);
  props.queryHook?.();
  return get({
    ...filter.value,
    ...params,
    setColumn: [
      'id',
      'song_name',
      'cover',
      'user_id',
      'project_id',
      'send_url',
      'lyric',
      'expand',
      'status',
      'created_at',
      'audit_at',
      'clip_lyric',
    ],
    setWith: ['project:id,name', 'user:id,real_name,nick_name,identity', 'tags:id,name'],
    setWithCount: ['viewUsers as view_count', 'collectionUsers as like_count'],
  }).finally(() => setLoading(false));
};

const onSort = (column: string, type: string) => {
  filter.value.setSort = type ? [(type === 'desc' ? '-' : '') + column, '-id'] : ['-id'];
  tableRef.value?.onFetch();
};

const onSearch = () => tableRef.value?.onPageChange(1);

const onReset = () => {
  filter.value = {
    songName: '',
    projectName: '',
    tagName: '',
    status: [],
    createBetween: [],
    ...props.initFilter,
    songType: 2,
    setSort: ['-id'],
  };
  tableRef.value?.resetSort();
  onSearch();
};

const handleCreate = () => {
  const dialog = createModalVNode(
    () =>
      createVNode(DemoForm, {
        initValue: { song_type: 2, cover: useSelectionStore().appleDemoCover, created_form: 0, is_push: 0, expand: { push_type: [] } },
        filterProject: (value: Project) => value.is_can_demo_apply === 1,
        onSubmit: (data: AnyObject) =>
          useApply.create(data).then(() => {
            Message.success(`申请上架Demo:${data.song_name}`);
            tableRef.value?.onFetch();
            dialog.close();
          }),
      }),
    { title: '创建Demo', footer: false, closable: true, width: 'auto' }
  );
};

const onExport = () => getExport(props.exportName || 'Demo', filter.value);

const onUpdate = (record: TableData) => {
  const dialog = createModalVNode(
    () =>
      createVNode(DemoForm, {
        initValue: record,
        filterProject: (value: Project) => value.is_can_demo_apply === 1 || value.id === record.project_id,
        onSubmit: (attribute: AnyObject) =>
          update(record.id, Object.assign(attribute, { song_type: 2 })).then(() => {
            Message.success(`编辑Demo:${record.song_name}`);
            tableRef.value?.onFetch();
            dialog.close();
          }),
      }),
    { title: '编辑Demo', footer: false, width: 'auto', closable: true }
  );
};

const onDown = (record: TableData) => {
  const msg = ref<string>('');

  createModalVNode(
    () =>
      createInputVNode(msg, {
        'placeholder': '请输入下架原因',
        'maxLength': 20,
        'show-word-limit': true,
      }),
    {
      title: '变更状态',
      titleAlign: 'start',
      okText: '下架',
      onBeforeOk: (done) =>
        changeStatus(record.id, { status: 'down', msg: msg.value })
          .then(() => {
            tableRef.value?.onFetch();
            done(true);
          })
          .catch(() => done(false)),
    }
  );
};

const handleCreateActivity = (row: TableData) => {
  console.log(row);
  let editData = JSON.parse(JSON.stringify(row));
  let { cover } = editData;
  if (cover && cover == useSelectionStore().appleDemoCover) {
    editData.cover = '';
  }
  editData.song_type = 1;
  const dialog = createModalVNode(
    () =>
      createVNode(ActivityForm, {
        initValue: editData,
        filterProject: (value: Project) => value.is_can_apply === 1 || value.id === editData.project_id,
        onSubmit: (data: AnyObject) =>
          useApply.create(data).then(() => {
            Message.success(`申请上架活动:${data.song_name}`);
            tableRef.value?.onFetch();
            dialog.close();
          }),
      }),
    { title: '创建歌曲', footer: false, closable: true, width: 'auto' }
  );
};

const onUp = (record: TableData, status: 'up' | 'reUp') => {
  createModalVNode(`请确认是否上架歌曲:${record.song_name}`, {
    title: '变更状态',
    titleAlign: 'start',
    okText: '上架',
    onBeforeOk: (done) =>
      changeStatus(record.id, { status })
        .then(() => {
          tableRef.value?.onFetch();
          done(true);
        })
        .catch(() => done(false)),
  });
};

const onDelete = (row: TableData) =>
  createModalVNode(`确认要将Demo:${row.song_name} 删除吗?`, {
    title: '删除操作',
    onBeforeOk: () => promiseToBoolean(destroy(row.id)),
    onOk: () => tableRef.value?.onFetch(),
  });

onMounted(() => onReset());
</script>

<template>
  <page-view has-bread has-card>
    <filter-search :model="filter" :loading="loading" @search="onSearch" @reset="onReset">
      <filter-search-item label="歌曲名称" field="song_name">
        <a-input v-model="filter.songName" allow-clear placeholder="请输入搜索歌曲名称" />
      </filter-search-item>
      <filter-search-item v-if="!hideSearchItem?.includes('projectName')" label="厂牌名称" field="projectName">
        <a-input v-model="filter.projectName" allow-clear placeholder="请输入搜索厂牌名称" />
      </filter-search-item>
      <filter-search-item label="标签名称" field="tagName">
        <a-input v-model="filter.tagName" allow-clear placeholder="请输入搜索标签名称" />
      </filter-search-item>
      <filter-search-item label="状态" field="status">
        <a-select v-model="filter.status" :options="statusOption" allow-clear multiple placeholder="请选择搜索状态" />
      </filter-search-item>
      <filter-search-item label="创建时间" field="createBetween">
        <a-range-picker v-model="filter.createBetween" show-time :time-picker-props="{ defaultValue: ['00:00:00', '23:59:59'] }" />
      </filter-search-item>
    </filter-search>
    <filter-table ref="tableRef" :loading="loading" :on-query="onQuery" @row-sort="onSort">
      <template #tool="{ size }">
        <a-button v-if="!hideCreate && canCreate" :size="size" type="primary" @click="handleCreate">Demo上架</a-button>
      </template>
      <template v-if="!hideTool" #tool-right>
        <export-button :on-download="onExport" />
      </template>
      <activity-table-column data-index="id" title="试唱歌曲" :width="560" hide-sub-title />
      <number-table-column data-index="view_count" title="试听人数" :dark-value="0" :width="110" has-sort />
      <number-table-column data-index="like_count" title="收藏人数" :dark-value="0" :width="110" has-sort />
      <date-table-column data-index="created_at" title="创建时间" :width="110" split has-sort />
      <!-- <date-table-column data-index="audit_at" title="通过时间" :width="110" split has-sort /> -->
      <enum-table-column data-index="status" title="状态" :option="statusOption" :width="110" has-sort />
      <a-table-column :width="90" align="center" data-index="operations" fixed="right" title="操作">
        <template #cell="{ record }">
          <a-space direction="vertical" fill>
            <a-link :hoverable="false" class="link-hover" @click="$router.push({ name: 'audition-demo-show', params: { id: record.id } })">
              查看
            </a-link>
            <a-link v-if="record.status === 1" :hoverable="false" class="link-hover" @click="onDown(record)">下架</a-link>
            <a-link v-if="record.status === 1" :hoverable="false" class="link-hover" @click="handleCreateActivity(record)">上架试唱</a-link>
            <a-link v-if="record.status === 2" :hoverable="false" class="link-hover" @click="onUp(record, 'up')">上架</a-link>
            <a-link v-if="record.status !== 0 && record.status !== 5" :hoverable="false" class="link-hover" @click="onUpdate(record)">
              编辑
            </a-link>
            <a-link v-if="record.status === 2" :hoverable="false" class="link-hover" @click="onDelete(record)">删除</a-link>
          </a-space>
        </template>
      </a-table-column>
    </filter-table>
  </page-view>
</template>

<style scoped lang="less">
:deep(.arco-table-cell) {
  padding: 5px 16px !important;
}
</style>