wangwei 4 éve
szülő
commit
7499b6d1d0

+ 40 - 0
src/api/sys/model/newsModel.ts

@@ -0,0 +1,40 @@
+/**
+ * @description: Get News list
+ */
+export interface GetNewsListModel {
+  count: number;
+  list: object[];
+}
+
+/**
+ * @description: Get event information return value
+ */
+export interface DeleteBatchesParams {
+  ids: string | string[] | number[];
+}
+
+/**
+ * @description: id
+ */
+export interface NewsIdParams {
+  id: string | number;
+}
+/**
+ * @description: id
+ */
+export interface GetNewsModel {
+  row: object[];
+}
+
+/**
+ * @description: add News
+ */
+export interface AddNewsParams {
+  id: number;
+}
+/**
+ * @description: edit News
+ */
+export interface EditNewsParams {
+  id: number;
+}

+ 74 - 0
src/api/sys/news.ts

@@ -0,0 +1,74 @@
+import { defHttp } from '/@/utils/http/axios';
+import {
+  GetNewsListModel,
+  DeleteBatchesParams,
+  NewsIdParams,
+  AddNewsParams,
+  EditNewsParams,
+  GetNewsModel,
+} from './model/newsModel';
+
+enum Api {
+  NewsUrl = '/news/',
+}
+
+/**
+ * @description: GetNewsList
+ */
+export function getNewsList(params) {
+  return defHttp.request<GetNewsListModel>({
+    url: Api.NewsUrl,
+    method: 'GET',
+    params,
+  });
+}
+
+/**
+ * @description: addNews
+ */
+export function addNews(params: AddNewsParams) {
+  return defHttp.request<GetNewsListModel>({
+    url: Api.NewsUrl,
+    method: 'POST',
+    params,
+  });
+}
+/**
+ * @description: 批量删除新闻
+ */
+export function deleteBatchesNews(params: DeleteBatchesParams) {
+  return defHttp.request<GetNewsListModel>({
+    url: Api.NewsUrl,
+    method: 'DELETE',
+    params,
+  });
+}
+
+/**
+ * @description: 获取单个新闻
+ */
+export function getNews(params: NewsIdParams) {
+  return defHttp.request<GetNewsModel>({
+    url: Api.NewsUrl + params.id,
+    method: 'GET',
+  });
+}
+/**
+ * @description: 修改单个新闻
+ */
+export function editNews(params: EditNewsParams) {
+  return defHttp.request<GetNewsListModel>({
+    url: Api.NewsUrl + params.id,
+    method: 'PUT',
+    params,
+  });
+}
+/**
+ * @description: 删除单个新闻
+ */
+export function deleteNews(params: NewsIdParams) {
+  return defHttp.request<GetNewsListModel>({
+    url: Api.NewsUrl + params.id,
+    method: 'DELETE',
+  });
+}

+ 144 - 0
src/views/news/news/data.ts

@@ -0,0 +1,144 @@
+import { FormProps, BasicColumn } from '/@/components/Table';
+import { h } from 'vue';
+import { Tag } from 'ant-design-vue';
+import { formatToDate } from '/@/utils/dateUtil';
+import { FormSchema } from '/@/components/Form/index';
+import { adapt } from '/@/utils/adapt';
+import { Tinymce } from '/@/components/Tinymce/index';
+
+const adaptWidth = adapt();
+
+// const isDir = (type: string) => type === '0';
+// const isMenu = (type: string) => type === '1';
+// const isButton = (type: string) => type === '2';
+export const columns: BasicColumn[] = [
+  {
+    title: 'ID',
+    dataIndex: 'id',
+    editComponentProps: {
+      prefix: '$',
+    },
+    width: 100,
+    sorter: true,
+  },
+  {
+    title: '标题',
+    dataIndex: 'title',
+    width: 130,
+    sorter: true,
+  },
+  {
+    title: '分类',
+    dataIndex: 'type',
+    width: 150,
+    sorter: true,
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'createtime',
+    width: 200,
+    customRender: ({ record }) => {
+      const createtime = record.createtime;
+      return formatToDate(createtime * 1000);
+    },
+  },
+  {
+    title: '更新时间',
+    dataIndex: 'updatetime',
+    width: 200,
+    customRender: ({ record }) => {
+      const updatetime = record.updatetime;
+      return formatToDate(updatetime * 1000);
+    },
+  },
+  {
+    title: '状态',
+    dataIndex: 'status',
+    width: 80,
+    customRender: ({ record }) => {
+      const status = record.status;
+      const enable = status === 'normal';
+      const color = enable ? 'green' : 'red';
+      const text = enable ? '启用' : '停用';
+      return h(Tag, { color: color }, () => text);
+    },
+    sorter: true,
+  },
+];
+
+export function getFormConfig(): Partial<FormProps> {
+  return {
+    labelWidth: 100,
+    schemas: [
+      {
+        field: `id`,
+        label: `ID`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+      {
+        field: `title`,
+        label: `标题`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+      {
+        field: `type`,
+        label: `分类`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+    ],
+  };
+}
+
+// =================popup================================
+export const schemas: FormSchema[] = [
+  {
+    field: 'title',
+    component: 'Input',
+    label: '标题',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    required: true,
+  },
+  {
+    field: 'type',
+    component: 'Input',
+    label: '分类',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    required: true,
+  },
+  {
+    field: 'content',
+    component: 'Input',
+    label: '内容',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    render: ({ model, field }) => {
+      return h(Tinymce, {
+        value: model[field],
+        onChange: (value: string) => {
+          model[field] = value;
+        },
+      });
+    },
+    required: true,
+  },
+];

+ 295 - 0
src/views/news/news/index.vue

@@ -0,0 +1,295 @@
+<template>
+  <CollapseContainer
+    class="sys-container"
+    title="新闻管理"
+    :canExpan="false"
+    helpMessage="新闻管理"
+  >
+    <BasicTable
+      ref="tableRef"
+      @register="registerTable"
+      rowKey="id"
+      @selectionChange="selectionChange"
+      @rowClick="rowClick"
+      @rowDbClick="handleEdit"
+      showTableSetting
+      :canResize="true"
+      :pagination="{
+        pageSize: 10,
+        defaultPageSize: 10,
+        showSizeChanger: false,
+      }"
+    >
+      <template #toolbar>
+        <div class="tool-btn-wrap">
+          <a-button type="primary" @click="addRole">添加</a-button>
+          <a-button color="error" :disabled="disable_btn" @click="deleteBatches">删除</a-button>
+        </div>
+      </template>
+      <template #form-custom>custom-slot</template>
+      <template #action="{ record }">
+        <TableAction :actions="createActions(record)" stopButtonPropagation />
+      </template>
+    </BasicTable>
+    <Popup @register="addRegister" :popupData="popupData" @saveData="saveData" />
+  </CollapseContainer>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, ref, toRefs, unref, createVNode } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import Popup from './popup.vue';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useModal } from '/@/components/Modal';
+  import { Modal } from 'ant-design-vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
+  import { getFormConfig, columns } from './data';
+  import moment from 'moment';
+  import { getNewsList, addNews, editNews, deleteNews, deleteBatchesNews } from '/@/api/sys/news';
+  import {
+    BasicTable,
+    useTable,
+    TableAction,
+    ActionItem,
+    EditRecordRow,
+    TableActionType,
+  } from '/@/components/Table';
+
+  interface PopupData {
+    title: string;
+  }
+  interface Btn {
+    disable_btn: boolean;
+  }
+
+  export default defineComponent({
+    name: 'News',
+    components: { CollapseContainer, BasicTable, TableAction, Popup },
+    setup() {
+      const { createMessage } = useMessage();
+      const { success, error } = createMessage;
+      const tableRef = ref<Nullable<TableActionType>>(null);
+      const currentEditKeyRef = ref('');
+      const popupData = reactive<PopupData>({
+        title: '添加',
+      });
+      const btn = reactive<Btn>({
+        disable_btn: true,
+      });
+      const [registerTable] = useTable({
+        rowSelection: {
+          type: 'checkbox',
+        },
+        columns: columns,
+        // clickToRowSelect: false, // 点击行不勾选
+        api: getNewsList,
+        useSearchForm: true,
+        beforeFetch: beforeFetch,
+        afterFetch: afterFetch,
+        formConfig: getFormConfig(),
+        actionColumn: {
+          width: 160,
+          title: '操作',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+          fixed: undefined,
+        },
+        tableSetting: {
+          // redo: false,
+          size: false,
+        },
+        showIndexColumn: false,
+        bordered: true,
+      });
+      const [register, { openModal }] = useModal();
+      const [addRegister, { openModal: openPopup }] = useModal();
+      function getTableAction() {
+        // 获取组件
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+
+      // 请求之前处理
+      function beforeFetch(params) {
+        for (let k in params) {
+          if (k !== 'page' && k !== 'pageSize' && k !== 'field' && k !== 'order') {
+            if (params[k] === '') {
+              delete params[k];
+            } else {
+              if (!params.filter) {
+                params.filter = {};
+              }
+              params.filter[k] = params[k];
+              delete params[k];
+            }
+          }
+        }
+        params.filter = JSON.stringify(params.filter);
+        params.offset = params.page;
+        params.limit = params.pageSize;
+        delete params.page;
+        delete params.pageSize;
+      }
+
+      function afterFetch(result) {
+        console.log(`result`, result);
+      }
+
+      function addRole() {
+        popupData.title = '添加';
+        openPopup(true, {});
+      }
+
+      function handleEdit(record: EditRecordRow) {
+        currentEditKeyRef.value = record.id; // record.key
+        popupData.title = '编辑';
+        const data = getTableAction().getDataSource();
+        data.map((item) => {
+          if (item.id === record.id) {
+            record = item;
+          }
+        });
+        openPopup(true, record);
+      }
+
+      async function handleDelete(record: Recordable) {
+        console.log(record);
+        await deleteNews({ id: record.id }).then((res) => {
+          console.log(res);
+          getTableAction().reload();
+          success('删除成功!');
+        });
+      }
+
+      function selectionChange() {
+        const keys = getTableAction().getSelectRowKeys();
+        if (keys.length) {
+          btn.disable_btn = false;
+        } else {
+          btn.disable_btn = true;
+        }
+      }
+      function rowClick() {
+        const keys = getTableAction().getSelectRowKeys();
+        if (keys.length) {
+          btn.disable_btn = false;
+        } else {
+          btn.disable_btn = true;
+        }
+      }
+
+      async function deleteBatches() {
+        const keys = await getTableAction().getSelectRowKeys();
+        const count = keys.length;
+        const ids = keys.toString();
+        if (!ids) {
+          return;
+        }
+        Modal.confirm({
+          title: '删除提示',
+          icon: createVNode(ExclamationCircleOutlined),
+          content: '确定删除选中的' + count + '项?',
+          okText: '确定',
+          okType: 'danger',
+          cancelText: '取消',
+          maskClosable: true,
+          async onOk() {
+            await deleteBatchesNews({ ids }).then((res) => {
+              console.log(res);
+              getTableAction().reload();
+              success('删除成功!');
+              getTableAction().setSelectedRowKeys([]);
+            });
+          },
+          onCancel() {
+            console.log('Cancel');
+          },
+        });
+      }
+
+      async function saveData(params: any) {
+        const data = params.data;
+        const closeModel = params.closeModal;
+        if (!data.id) {
+          await addNews(data).then((res) => {
+            console.log(res);
+            getTableAction().reload();
+            closeModel();
+            success('创建成功!');
+          });
+          console.log('----------add---');
+        } else {
+          await editNews(data).then((res) => {
+            console.log(res);
+            getTableAction().reload();
+            closeModel();
+            success('修改成功!');
+          });
+          console.log('----------edit---');
+        }
+      }
+
+      function createActions(record: EditRecordRow): ActionItem[] {
+        return [
+          {
+            label: '编辑',
+            icon: 'ant-design:edit-outlined',
+            color: 'warning',
+            onClick: handleEdit.bind(null, record),
+          },
+          {
+            label: '删除',
+            color: 'error',
+            icon: 'ic:outline-delete-outline',
+            popConfirm: {
+              title: '是否确认删除',
+              confirm: handleDelete.bind(null, record),
+            },
+          },
+        ];
+      }
+      return {
+        popupData,
+        tableRef,
+        registerTable,
+        addRole,
+        handleEdit,
+        deleteBatches,
+        createActions,
+        getTableAction,
+        rowClick,
+        selectionChange,
+        addRegister,
+        saveData,
+        openModal,
+        register,
+        ...toRefs(btn),
+      };
+    },
+  });
+</script>
+<style scoped>
+  .ant-calendar-picker {
+    width: 100%;
+  }
+  @media (max-width: 639px) {
+    .sys-container .vben-basic-table-header__toolbar > * {
+      margin-right: 3px;
+    }
+
+    .sys-container .vben-basic-table .ant-table-wrapper {
+      padding: 3px;
+    }
+  }
+  .vben-basic-table-header__toolbar {
+    justify-content: space-between;
+  }
+  .tool-btn-wrap {
+    flex: 1;
+  }
+  .tool-btn-wrap button {
+    margin-right: 5px;
+  }
+</style>

+ 119 - 0
src/views/news/news/popup.vue

@@ -0,0 +1,119 @@
+<template>
+  <BasicModal width="800px" v-bind="$attrs" @register="register" @ok="confirm" :title="title">
+    <BasicForm @register="registerForm" :model="model" />
+    <!-- <MenuTree /> -->
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { Tree } from 'ant-design-vue';
+  import { defineComponent, PropType, reactive, ref, toRefs } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { schemas } from './data';
+  interface PopupData {
+    title: string;
+  }
+  interface Role {
+    id: string | number;
+  }
+
+  export default defineComponent({
+    components: { BasicModal, BasicForm, [Tree.name]: Tree },
+    props: {
+      popupData: {
+        type: Object as PropType<PopupData>,
+        default: () => {},
+      },
+    },
+    emits: ['saveData'],
+    setup(props, { emit }) {
+      const { createMessage } = useMessage();
+      const { error } = createMessage;
+      const role = reactive<Role>({
+        id: 0,
+      });
+      const popupData = props.popupData as PopupData;
+      console.log(`popupData`, popupData);
+      const modelRef = ref({});
+
+      const [registerForm, { updateSchema, setFieldsValue, resetFields, validate }] = useForm({
+        labelWidth: 120,
+        schemas,
+        showActionButtonGroup: false,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      //   const [register, { closeModal }] = useModalInner((data) => {
+      //     modelRef.value = data;
+
+      //
+      //   });
+      const [register, { closeModal }] = useModalInner((data) => {
+        resetFields();
+        if (data) {
+          role.id = data.id;
+          updateSchema({
+            field: 'password',
+            required: false,
+          });
+        } else {
+          role.id = 0;
+          updateSchema({
+            field: 'password',
+            required: true,
+          });
+        }
+        setFieldsValue(data);
+      });
+
+      async function confirm() {
+        try {
+          const data = await validate();
+          if (role.id) {
+            data.id = role.id;
+          }
+          const popupData = { closeModal, data };
+          emit('saveData', popupData);
+        } catch (err: any) {
+          error(err.errorFields[0].errors[0]);
+        }
+      }
+      return {
+        register,
+        schemas,
+        registerForm,
+        model: modelRef,
+        confirm,
+        ...toRefs(popupData),
+      };
+    },
+  });
+</script>
+<style lang="less">
+  .ant-form-item-label {
+    text-align: center !important;
+  }
+
+  .tree-label {
+    width: 20.6%;
+    margin-top: 8px;
+    margin-bottom: 1em;
+    text-align: center;
+  }
+
+  @media (max-width: 639px) {
+    .ant-form-item-label {
+      line-height: 2.5715 !important;
+      text-align: center !important;
+    }
+
+    .tree-label {
+      width: 33%;
+      margin-top: 8px;
+      margin-bottom: 1em;
+      text-align: center;
+    }
+  }
+</style>

+ 144 - 0
src/views/news/type/data.ts

@@ -0,0 +1,144 @@
+import { FormProps, BasicColumn } from '/@/components/Table';
+import { h } from 'vue';
+import { Tag } from 'ant-design-vue';
+import { formatToDate } from '/@/utils/dateUtil';
+import { FormSchema } from '/@/components/Form/index';
+import { adapt } from '/@/utils/adapt';
+import { Tinymce } from '/@/components/Tinymce/index';
+
+const adaptWidth = adapt();
+
+// const isDir = (type: string) => type === '0';
+// const isMenu = (type: string) => type === '1';
+// const isButton = (type: string) => type === '2';
+export const columns: BasicColumn[] = [
+  {
+    title: 'ID',
+    dataIndex: 'id',
+    editComponentProps: {
+      prefix: '$',
+    },
+    width: 100,
+    sorter: true,
+  },
+  {
+    title: '标题',
+    dataIndex: 'title',
+    width: 130,
+    sorter: true,
+  },
+  {
+    title: '分类',
+    dataIndex: 'type',
+    width: 150,
+    sorter: true,
+  },
+  {
+    title: '创建时间',
+    dataIndex: 'createtime',
+    width: 200,
+    customRender: ({ record }) => {
+      const createtime = record.createtime;
+      return formatToDate(createtime * 1000);
+    },
+  },
+  {
+    title: '更新时间',
+    dataIndex: 'updatetime',
+    width: 200,
+    customRender: ({ record }) => {
+      const updatetime = record.updatetime;
+      return formatToDate(updatetime * 1000);
+    },
+  },
+  {
+    title: '状态',
+    dataIndex: 'status',
+    width: 80,
+    customRender: ({ record }) => {
+      const status = record.status;
+      const enable = status === 'normal';
+      const color = enable ? 'green' : 'red';
+      const text = enable ? '启用' : '停用';
+      return h(Tag, { color: color }, () => text);
+    },
+    sorter: true,
+  },
+];
+
+export function getFormConfig(): Partial<FormProps> {
+  return {
+    labelWidth: 100,
+    schemas: [
+      {
+        field: `id`,
+        label: `ID`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+      {
+        field: `title`,
+        label: `标题`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+      {
+        field: `type`,
+        label: `分类`,
+        component: 'Input',
+        colProps: {
+          xl: 12,
+          xxl: 8,
+        },
+      },
+    ],
+  };
+}
+
+// =================popup================================
+export const schemas: FormSchema[] = [
+  {
+    field: 'title',
+    component: 'Input',
+    label: '标题',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    required: true,
+  },
+  {
+    field: 'type',
+    component: 'Input',
+    label: '分类',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    required: true,
+  },
+  {
+    field: 'content',
+    component: 'Input',
+    label: '内容',
+    labelWidth: adaptWidth.adminLabelWidth,
+    colProps: {
+      span: adaptWidth.elContainer,
+    },
+    render: ({ model, field }) => {
+      return h(Tinymce, {
+        value: model[field],
+        onChange: (value: string) => {
+          model[field] = value;
+        },
+      });
+    },
+    required: true,
+  },
+];

+ 295 - 0
src/views/news/type/index.vue

@@ -0,0 +1,295 @@
+<template>
+  <CollapseContainer
+    class="sys-container"
+    title="新闻类型"
+    :canExpan="false"
+    helpMessage="新闻类型"
+  >
+    <BasicTable
+      ref="tableRef"
+      @register="registerTable"
+      rowKey="id"
+      @selectionChange="selectionChange"
+      @rowClick="rowClick"
+      @rowDbClick="handleEdit"
+      showTableSetting
+      :canResize="true"
+      :pagination="{
+        pageSize: 10,
+        defaultPageSize: 10,
+        showSizeChanger: false,
+      }"
+    >
+      <template #toolbar>
+        <div class="tool-btn-wrap">
+          <a-button type="primary" @click="addRole">添加</a-button>
+          <a-button color="error" :disabled="disable_btn" @click="deleteBatches">删除</a-button>
+        </div>
+      </template>
+      <template #form-custom>custom-slot</template>
+      <template #action="{ record }">
+        <TableAction :actions="createActions(record)" stopButtonPropagation />
+      </template>
+    </BasicTable>
+    <Popup @register="addRegister" :popupData="popupData" @saveData="saveData" />
+  </CollapseContainer>
+</template>
+<script lang="ts">
+  import { defineComponent, reactive, ref, toRefs, unref, createVNode } from 'vue';
+  import { CollapseContainer } from '/@/components/Container/index';
+  import Popup from './popup.vue';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { useModal } from '/@/components/Modal';
+  import { Modal } from 'ant-design-vue';
+  import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
+  import { getFormConfig, columns } from './data';
+  import moment from 'moment';
+  import { getNewsList, addNews, editNews, deleteNews, deleteBatchesNews } from '/@/api/sys/news';
+  import {
+    BasicTable,
+    useTable,
+    TableAction,
+    ActionItem,
+    EditRecordRow,
+    TableActionType,
+  } from '/@/components/Table';
+
+  interface PopupData {
+    title: string;
+  }
+  interface Btn {
+    disable_btn: boolean;
+  }
+
+  export default defineComponent({
+    name: 'NewsType',
+    components: { CollapseContainer, BasicTable, TableAction, Popup },
+    setup() {
+      const { createMessage } = useMessage();
+      const { success, error } = createMessage;
+      const tableRef = ref<Nullable<TableActionType>>(null);
+      const currentEditKeyRef = ref('');
+      const popupData = reactive<PopupData>({
+        title: '添加',
+      });
+      const btn = reactive<Btn>({
+        disable_btn: true,
+      });
+      const [registerTable] = useTable({
+        rowSelection: {
+          type: 'checkbox',
+        },
+        columns: columns,
+        // clickToRowSelect: false, // 点击行不勾选
+        api: getNewsList,
+        useSearchForm: true,
+        beforeFetch: beforeFetch,
+        afterFetch: afterFetch,
+        formConfig: getFormConfig(),
+        actionColumn: {
+          width: 160,
+          title: '操作',
+          dataIndex: 'action',
+          slots: { customRender: 'action' },
+          fixed: undefined,
+        },
+        tableSetting: {
+          // redo: false,
+          size: false,
+        },
+        showIndexColumn: false,
+        bordered: true,
+      });
+      const [register, { openModal }] = useModal();
+      const [addRegister, { openModal: openPopup }] = useModal();
+      function getTableAction() {
+        // 获取组件
+        const tableAction = unref(tableRef);
+        if (!tableAction) {
+          throw new Error('tableAction is null');
+        }
+        return tableAction;
+      }
+
+      // 请求之前处理
+      function beforeFetch(params) {
+        for (let k in params) {
+          if (k !== 'page' && k !== 'pageSize' && k !== 'field' && k !== 'order') {
+            if (params[k] === '') {
+              delete params[k];
+            } else {
+              if (!params.filter) {
+                params.filter = {};
+              }
+              params.filter[k] = params[k];
+              delete params[k];
+            }
+          }
+        }
+        params.filter = JSON.stringify(params.filter);
+        params.offset = params.page;
+        params.limit = params.pageSize;
+        delete params.page;
+        delete params.pageSize;
+      }
+
+      function afterFetch(result) {
+        console.log(`result`, result);
+      }
+
+      function addRole() {
+        popupData.title = '添加';
+        openPopup(true, {});
+      }
+
+      function handleEdit(record: EditRecordRow) {
+        currentEditKeyRef.value = record.id; // record.key
+        popupData.title = '编辑';
+        const data = getTableAction().getDataSource();
+        data.map((item) => {
+          if (item.id === record.id) {
+            record = item;
+          }
+        });
+        openPopup(true, record);
+      }
+
+      async function handleDelete(record: Recordable) {
+        console.log(record);
+        await deleteNews({ id: record.id }).then((res) => {
+          console.log(res);
+          getTableAction().reload();
+          success('删除成功!');
+        });
+      }
+
+      function selectionChange() {
+        const keys = getTableAction().getSelectRowKeys();
+        if (keys.length) {
+          btn.disable_btn = false;
+        } else {
+          btn.disable_btn = true;
+        }
+      }
+      function rowClick() {
+        const keys = getTableAction().getSelectRowKeys();
+        if (keys.length) {
+          btn.disable_btn = false;
+        } else {
+          btn.disable_btn = true;
+        }
+      }
+
+      async function deleteBatches() {
+        const keys = await getTableAction().getSelectRowKeys();
+        const count = keys.length;
+        const ids = keys.toString();
+        if (!ids) {
+          return;
+        }
+        Modal.confirm({
+          title: '删除提示',
+          icon: createVNode(ExclamationCircleOutlined),
+          content: '确定删除选中的' + count + '项?',
+          okText: '确定',
+          okType: 'danger',
+          cancelText: '取消',
+          maskClosable: true,
+          async onOk() {
+            await deleteBatchesNews({ ids }).then((res) => {
+              console.log(res);
+              getTableAction().reload();
+              success('删除成功!');
+              getTableAction().setSelectedRowKeys([]);
+            });
+          },
+          onCancel() {
+            console.log('Cancel');
+          },
+        });
+      }
+
+      async function saveData(params: any) {
+        const data = params.data;
+        const closeModel = params.closeModal;
+        if (!data.id) {
+          await addNews(data).then((res) => {
+            console.log(res);
+            getTableAction().reload();
+            closeModel();
+            success('创建成功!');
+          });
+          console.log('----------add---');
+        } else {
+          await editNews(data).then((res) => {
+            console.log(res);
+            getTableAction().reload();
+            closeModel();
+            success('修改成功!');
+          });
+          console.log('----------edit---');
+        }
+      }
+
+      function createActions(record: EditRecordRow): ActionItem[] {
+        return [
+          {
+            label: '编辑',
+            icon: 'ant-design:edit-outlined',
+            color: 'warning',
+            onClick: handleEdit.bind(null, record),
+          },
+          {
+            label: '删除',
+            color: 'error',
+            icon: 'ic:outline-delete-outline',
+            popConfirm: {
+              title: '是否确认删除',
+              confirm: handleDelete.bind(null, record),
+            },
+          },
+        ];
+      }
+      return {
+        popupData,
+        tableRef,
+        registerTable,
+        addRole,
+        handleEdit,
+        deleteBatches,
+        createActions,
+        getTableAction,
+        rowClick,
+        selectionChange,
+        addRegister,
+        saveData,
+        openModal,
+        register,
+        ...toRefs(btn),
+      };
+    },
+  });
+</script>
+<style scoped>
+  .ant-calendar-picker {
+    width: 100%;
+  }
+  @media (max-width: 639px) {
+    .sys-container .vben-basic-table-header__toolbar > * {
+      margin-right: 3px;
+    }
+
+    .sys-container .vben-basic-table .ant-table-wrapper {
+      padding: 3px;
+    }
+  }
+  .vben-basic-table-header__toolbar {
+    justify-content: space-between;
+  }
+  .tool-btn-wrap {
+    flex: 1;
+  }
+  .tool-btn-wrap button {
+    margin-right: 5px;
+  }
+</style>

+ 119 - 0
src/views/news/type/popup.vue

@@ -0,0 +1,119 @@
+<template>
+  <BasicModal width="800px" v-bind="$attrs" @register="register" @ok="confirm" :title="title">
+    <BasicForm @register="registerForm" :model="model" />
+    <!-- <MenuTree /> -->
+  </BasicModal>
+</template>
+<script lang="ts">
+  import { Tree } from 'ant-design-vue';
+  import { defineComponent, PropType, reactive, ref, toRefs } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
+  import { useMessage } from '/@/hooks/web/useMessage';
+  import { BasicForm, useForm } from '/@/components/Form/index';
+  import { schemas } from './data';
+  interface PopupData {
+    title: string;
+  }
+  interface Role {
+    id: string | number;
+  }
+
+  export default defineComponent({
+    components: { BasicModal, BasicForm, [Tree.name]: Tree },
+    props: {
+      popupData: {
+        type: Object as PropType<PopupData>,
+        default: () => {},
+      },
+    },
+    emits: ['saveData'],
+    setup(props, { emit }) {
+      const { createMessage } = useMessage();
+      const { error } = createMessage;
+      const role = reactive<Role>({
+        id: 0,
+      });
+      const popupData = props.popupData as PopupData;
+      console.log(`popupData`, popupData);
+      const modelRef = ref({});
+
+      const [registerForm, { updateSchema, setFieldsValue, resetFields, validate }] = useForm({
+        labelWidth: 120,
+        schemas,
+        showActionButtonGroup: false,
+        actionColOptions: {
+          span: 24,
+        },
+      });
+      //   const [register, { closeModal }] = useModalInner((data) => {
+      //     modelRef.value = data;
+
+      //
+      //   });
+      const [register, { closeModal }] = useModalInner((data) => {
+        resetFields();
+        if (data) {
+          role.id = data.id;
+          updateSchema({
+            field: 'password',
+            required: false,
+          });
+        } else {
+          role.id = 0;
+          updateSchema({
+            field: 'password',
+            required: true,
+          });
+        }
+        setFieldsValue(data);
+      });
+
+      async function confirm() {
+        try {
+          const data = await validate();
+          if (role.id) {
+            data.id = role.id;
+          }
+          const popupData = { closeModal, data };
+          emit('saveData', popupData);
+        } catch (err: any) {
+          error(err.errorFields[0].errors[0]);
+        }
+      }
+      return {
+        register,
+        schemas,
+        registerForm,
+        model: modelRef,
+        confirm,
+        ...toRefs(popupData),
+      };
+    },
+  });
+</script>
+<style lang="less">
+  .ant-form-item-label {
+    text-align: center !important;
+  }
+
+  .tree-label {
+    width: 20.6%;
+    margin-top: 8px;
+    margin-bottom: 1em;
+    text-align: center;
+  }
+
+  @media (max-width: 639px) {
+    .ant-form-item-label {
+      line-height: 2.5715 !important;
+      text-align: center !important;
+    }
+
+    .tree-label {
+      width: 33%;
+      margin-top: 8px;
+      margin-bottom: 1em;
+      text-align: center;
+    }
+  }
+</style>