index.vue 6.27 KB
<script setup lang="ts">
  import { AnyObject } from '@/types/global';
  import useRoleApi from '@/http/role';

  import useLoading from '@/hooks/loading';
  import { createVNode, onMounted, ref } from 'vue';
  import { pick, set } from 'lodash';
  import { promiseToBoolean } from '@/utils';
  import { createModalVNode } from '@/utils/createVNode';
  import UserTableColumn from '@/components/filter/user-table-column.vue';
  import NumberTableColumn from '@/components/filter/number-table-column.vue';
  import SpaceTableColumn from '@/components/filter/space-table-column.vue';
  import EnumTableColumn from '@/components/filter/enum-table-column.vue';
  import IconButton from '@/components/icon-button/index.vue';
  import FormContent from '@/views/system/role/components/form-content.vue';
  import PermissionContent from '@/views/system/role/components/permission-content.vue';
  import { SystemPermission } from '@/types/system-permission';
  import { useAuthorizedStore } from '@/store';

  const { loading, setLoading } = useLoading(false);
  const tableRef = ref();
  const filter = ref<AnyObject>({});

  const onQuery = async (params: AnyObject) => {
    setLoading(true);
    return useRoleApi
      .get({
        guard: 'Admin',
        setWith: ['creator:id,nick_name', 'permissions:id'],
        setWithCount: ['users'],
        ...params,
        sortBy: 'id',
        sortType: 'desc',
      })
      .finally(() => setLoading(false));
  };

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

  const onReset = () => {
    filter.value = { name: '', status: '' };
    onSearch();
  };

  onMounted(async () => {
    onReset();
  });

  const onCreate = () => {
    const formRef = ref();
    const formValue = ref({ name: '', intro: '' });
    createModalVNode(
      () =>
        createVNode(FormContent, {
          ref: formRef,
          modelValue: formValue.value,
          submit: () => useRoleApi.create(formValue.value),
        }),
      {
        title: '新增角色',
        titleAlign: 'center',
        onBeforeOk: () => promiseToBoolean(formRef.value?.onSubmit()),
        onOk: () => tableRef.value?.onFetch(),
      }
    );
  };

  const onUpdate = (row: any) => {
    const formRef = ref();
    const formValue = ref(pick(row, ['name', 'intro']));

    createModalVNode(
      () =>
        createVNode(FormContent, {
          ref: formRef,
          modelValue: formValue.value,
          submit: () => useRoleApi.update(row.id, formValue.value),
        }),
      {
        title: '编辑角色',
        titleAlign: 'center',
        onBeforeOk: () => promiseToBoolean(formRef.value?.onSubmit()),
        onOk: () => tableRef.value?.onFetch(),
      }
    );
  };

  const onChangeStatus = (row: any, status: number) => {
    createModalVNode(`是否将角色《${row.name}》的状态变更为:${useRoleApi.statusOption.find((item) => item.value === status)?.label}`, {
      title: '状态变更',
      titleAlign: 'center',
      onBeforeOk: () => promiseToBoolean(useRoleApi.changeStatus(row.id, status)),
      onOk: () => tableRef.value?.onFetch(),
    });
  };

  const onChangePermission = (row: any) => {
    const formValue = ref<number[]>([]);
    row.permissions.forEach((item: SystemPermission) => formValue.value.push(item.id));

    createModalVNode(
      () =>
        createVNode(PermissionContent, {
          'modelValue': formValue.value,
          'onUpdate:modelValue': (val: number[]) => set(formValue, 'value', val),
        }),
      {
        hideTitle: true,
        bodyStyle: { padding: 0 },
        width: 720,
        onBeforeOk: () => promiseToBoolean(useRoleApi.changePermission(row.id, formValue.value)),
        onOk: () => {
          useAuthorizedStore().syncInfo();
          tableRef.value?.onFetch();
        },
      }
    );
  };

  const onDelete = (row: any) => {
    createModalVNode(`删除角色:${row.name}`, {
      title: '删除操作',
      titleAlign: 'center',
      onBeforeOk: () => promiseToBoolean(useRoleApi.destroy(row.id)),
      onOk: () => tableRef.value?.onFetch(),
    });
  };
</script>

<template>
  <page-view has-bread has-card>
    <filter-search :loading="loading" :model="filter" inline @search="onSearch" @reset="onReset">
      <filter-search-item label="名称">
        <a-input v-model="filter.name" placeholder="请输入" allow-clear />
      </filter-search-item>
      <filter-search-item label="状态">
        <a-select v-model="filter.status" :options="useRoleApi.statusOption" placeholder="请选择" allow-clear />
      </filter-search-item>
    </filter-search>
    <filter-table ref="tableRef" :loading="loading" :on-query="onQuery">
      <template #tool>
        <icon-button v-permission="['system-role-create']" type="primary" icon="plus" label="新增" @click="onCreate" />
      </template>
      <filter-table-column data-index="name" title="名称" :width="160" />
      <filter-table-column data-index="intro" title="描述" :width="180" />
      <number-table-column data-index="users_count" title="关联用户数" :width="140" />
      <user-table-column data-index="user_id" user="creator" title="创建人" show-href :width="140" />
      <filter-table-column data-index="created_at" title="创建时间" :width="180" />
      <enum-table-column data-index="status" title="状态" :option="useRoleApi.statusOption" :width="80" />
      <space-table-column data-index="operator" title="操作" :width="160">
        <template #default="{ record }">
          <a-link
            v-permission="['system-role-edit']"
            :hoverable="false"
            class="link-hover"
            @click="onChangeStatus(record, Number(!record.status))"
          >
            {{ useRoleApi.statusOption.find((item) => item.value === Number(!record.status))?.label }}
          </a-link>
          <a-link v-permission="['system-role-edit']" :hoverable="false" class="link-hover" @click="onUpdate(record)">编辑</a-link>
          <a-link v-permission="['system-role-permission']" :hoverable="false" class="link-hover" @click="onChangePermission(record)">
            权限
          </a-link>
          <a-link v-permission="['system-role-delete']" :hoverable="false" class="link-hover" @click="onDelete(record)">删除</a-link>
        </template>
      </space-table-column>
    </filter-table>
  </page-view>
</template>

<style scoped lang="less"></style>