IT评测·应用市场-qidao123.com

标题: Koa商城项目-轮播图模块(前端) [打印本页]

作者: 农民    时间: 2024-8-15 05:04
标题: Koa商城项目-轮播图模块(前端)
 媒介

   通过这次独自做前后端发现有很多需要提升的地方,很多细节处理处罚不到位。下面简朴看一下本人本身做的结果吧~~
  Git地址

  1. https://gitee.com/ah-ah-bao/koa_system
复制代码
结果图


 前端代码

api/banner.ts

  1. import request from "../utils/request";
  2. export const getBannerList = (params: any = {}) => {
  3.   return request.post("/banner/list", { ...params });
  4. };
  5. export const getBannerAdd = (params = {}) => {
  6.   return request.post("/banner/add", params);
  7. };
  8. export const getBannerUpdate = (params = {}) => {
  9.   return request.post("/banner/update", params);
  10. };
  11. export const getBannerDetail = (params = {}) => {
  12.   return request.post("/banner/detail", params);
  13. };
  14. export const getBannerDelete = (params = {}) => {
  15.   return request.post("/banner/delete", params);
  16. };
  17. export const getBannerUpload = (params = {}) => {
  18.   return request.post("/banner/upload", params);
  19. };
复制代码
pages/BannerList/index.tsx

  1. import { useEffect, useState } from 'react';
  2. import { message, Table, Popconfirm } from 'antd';
  3. import { getBannerList, getBannerDelete } from '../../api/banner'
  4. import type { BannerData, pageGationBannerData } from '../../types/banner';
  5. import { BannerColumnsList } from './columns'
  6. import SearchForm from './SearchForm'
  7. import BannerAddOrEdit from './BannerAddOrEdit';
  8. const BannerList = () => {
  9.   const [bannerList, setBannerList] = useState<BannerData[]>([]);
  10.   const [columns, setColumns] = useState<any[]>([]);
  11.   const [visible, setVisible] = useState<boolean>(false);
  12.   const [selectedId, setSelectedId] = useState<number | null>(null);
  13.   const [pagination, setPagination] = useState({
  14.     page: 1,
  15.     pageSize: 10,
  16.     total: 0,
  17.     showSizeChanger: true,
  18.     hideOnSinglePage: false,
  19.     pageSizeOptions: ['10', '50', '100', '200'],
  20.     showTotal: (total: number) => `共 ${total} 条数据`,
  21.   })
  22.   const [queryParams, setQueryParams] = useState<pageGationBannerData>({
  23.     page: 1,
  24.     pageSize: 10,
  25.     bannername: '',
  26.     url: ''
  27.   })
  28.   const getTableColmuns = async () => {
  29.     var columns = [];
  30.     const bannerColumns: any = await BannerColumnsList();
  31.     columns = [
  32.       ...bannerColumns,
  33.       {
  34.         title: '操作',
  35.         key: 'operation',
  36.         align: 'center',
  37.         width: 120,
  38.         render: (_text: any, record: any) =>
  39.           [
  40.             <div className='banner_opertion'>
  41.               <div key={`${record.id}-update`} onClick={() => handleUpdateClick(record.id)}>修改</div>
  42.               <Popconfirm
  43.                 title="确定要删除这条记录吗?"
  44.                 onConfirm={() => {
  45.                   try {
  46.                     getBannerDelete({
  47.                       id: record.id
  48.                     }).then((res: any) => {
  49.                       if (res.data.code === 200) {
  50.                         message.success('删除成功');
  51.                         fetchData();
  52.                       } else {
  53.                         message.error(res.data.message);
  54.                       }
  55.                     })
  56.                   } catch (error) {
  57.                     message.error('删除失败!');
  58.                   }
  59.                 }
  60.                 }
  61.                 okText="确定"
  62.                 cancelText="取消"
  63.               >
  64.                 <div key={`${record.id}-delete`}>删除</div>
  65.               </Popconfirm>
  66.             </div>
  67.           ]
  68.       }
  69.     ];
  70.     return columns; // 确保返回值
  71.   }
  72.   const handleUpdateClick = (id: number) => {
  73.     setSelectedId(id);
  74.     setVisible(true);
  75.   };
  76.   
  77.   const getBannerListData = async () => {
  78.     try {
  79.       const res = await getBannerList(queryParams);
  80.       if (res.data.code === 200) {
  81.         setBannerList(res.data.data);
  82.         setPagination({
  83.           ...pagination,
  84.         })
  85.       } else {
  86.         message.error(res.data.message);
  87.       }
  88.     } catch (error) {
  89.       message.error('获取数据失败!');
  90.     }
  91.   }
  92.   const fetchData = async () => {
  93.     try {
  94.       await getBannerListData();
  95.       const column = await getTableColmuns();
  96.       setColumns(column);
  97.     } catch (error) {
  98.       message.error('获取数据失败!');
  99.     }
  100.   };
  101.   useEffect(() => {
  102.     fetchData();
  103.   }, [])
  104.   const handleMessageSearch = (msg: any) => {
  105.     setQueryParams({ ...queryParams, bannername: msg })
  106.   };
  107.   const getBannerAdd = (msg: any) => {
  108.     setVisible(msg)
  109.   }
  110.   const handleModalClose = () => {
  111.     setVisible(false);
  112.     setSelectedId(null);
  113.   };
  114.   useEffect(() => {
  115.     getBannerListData();
  116.   }, [queryParams]);
  117.   return (
  118.     <>
  119.       <SearchForm SumbitSearch={handleMessageSearch} SumbitAdd={getBannerAdd} />
  120.       <BannerAddOrEdit visible={visible} onClose={handleModalClose} id={selectedId} onRefresh={fetchData} />
  121.       <Table
  122.         columns={columns}
  123.         dataSource={bannerList}
  124.         pagination={pagination}
  125.         rowKey={(record: any) => `table_${record.id}`}
  126.         scroll={{ x: 1200 }}
  127.       />
  128.     </>
  129.   )
  130. }
  131. export default BannerList;
复制代码
pages/BannerList/columns.tsx

  1. import type { TableProps } from 'antd';
  2. import type { BannerData } from '../../types/banner';
  3. import { Image } from 'antd';
  4. export const BannerColumnsList: () => Promise<TableProps<BannerData>['columns']> = async () => {
  5.     return [
  6.         {
  7.             title: 'id',
  8.             dataIndex: 'id',
  9.             key: 'id',
  10.             align: 'center',
  11.         },
  12.         {
  13.             title: '轮播图名称',
  14.             dataIndex: 'bannername',
  15.             key: 'bannername',
  16.             align: 'center',
  17.         },
  18.         {
  19.             title: '图片',
  20.             dataIndex: 'url',
  21.             key: 'url',
  22.             align: 'center',
  23.             render: (url: string) => (
  24.                 <Image
  25.                     width={80}
  26.                     height={80}
  27.                     src={url}
  28.                 />
  29.             ),
  30.         },
  31.     ]
  32. }
复制代码
pages/BannerList/SearchForm.tsx

  1. import type { FormProps } from 'antd';
  2. import { Button, Form, Input, Row, Col } from 'antd';
  3. import { SearchOutlined, PlusOutlined, RedoOutlined } from '@ant-design/icons';
  4. import { useEffect } from 'react';
  5. import './banner.sass'
  6. type FieldType = {
  7.     bannername?: string;
  8. };
  9. const SearchForm = (props: any) => {
  10.     const [form] = Form.useForm();
  11.     const onFinish: FormProps<FieldType>['onFinish'] = (values) => {
  12.         props.SumbitSearch(values.bannername);
  13.     };
  14.     const onReset = () => {
  15.         form.resetFields();
  16.         onFinish(form.getFieldsValue())
  17.     };
  18.     //新增轮播图弹窗
  19.     const addBannerModal = () => {
  20.         // 弹窗显示
  21.         props.SumbitAdd(true)
  22.     }
  23.     useEffect(() => {
  24.         form.setFieldsValue({
  25.             bannername: ''
  26.         })
  27.     }, [])
  28.     return (
  29.         <>
  30.             <Form
  31.                 name="basic"
  32.                 labelCol={{ span: 4 }}
  33.                 wrapperCol={{ span: 20 }}
  34.                 onFinish={onFinish}
  35.                 autoComplete="off"
  36.                 form={form}
  37.             >
  38.                 <Row gutter={24}>
  39.                     <Col span={12}>
  40.                         <Form.Item<FieldType>
  41.                             label="轮播图名称"
  42.                             name="bannername"
  43.                         >
  44.                             <Input />
  45.                         </Form.Item></Col>
  46.                     <Col span={12}>
  47.                         <Form.Item wrapperCol={{ offset: 8, span: 16 }}>
  48.                             <Button type="primary" htmlType="submit">
  49.                                 <SearchOutlined />  搜索
  50.                             </Button>
  51.                             <Button className='banner_button' onClick={onReset}>
  52.                                 <RedoOutlined />重置
  53.                             </Button>
  54.                             <Button className='banner_button' type="primary" onClick={addBannerModal}>
  55.                                 <PlusOutlined />  新增轮播图
  56.                             </Button>
  57.                         </Form.Item></Col>
  58.                 </Row>
  59.             </Form>
  60.         </>
  61.     )
  62. }
  63. export default SearchForm;
复制代码
pages/BannerList/BannerAddOrEdit.tsx

  1. import React, { useState, useEffect } from 'react';
  2. import { Modal, Button, message, Upload, Input, Form, Image } from 'antd';
  3. import { UploadOutlined } from '@ant-design/icons';
  4. import type { UploadProps } from 'antd';
  5. import { getBannerAdd, getBannerUpdate, getBannerDetail } from '../../api/banner'
  6. import { API_URL, getToken } from '../../../common'
  7. import type { BannerAddOrEditProps, } from '../../types/banner'
  8. const BannerAdd: React.FC<BannerAddOrEditProps> = ({ visible, onClose, onRefresh, id }) => {
  9.   const [localVisible, setLocalVisible] = useState(visible);
  10.   const [title, setTitle] = useState<string>('');
  11.   const [url, setUrl] = useState<string>('');
  12.   const [bannername, setBannername] = useState<string>('')
  13.   const [confirmLoading, setConfirmLoading] = useState<boolean>(false);
  14.   const [form] = Form.useForm();
  15.   useEffect(() => {
  16.     setLocalVisible(visible);
  17.     if (!id) {
  18.       setBannername('')
  19.       setUrl('')
  20.     } else {
  21.       getBannerDetail({
  22.         id: id
  23.       }).then((res: any) => {
  24.         if (res.data.code === 200) {
  25.           setTitle('修改轮播图')
  26.           setBannername(res.data.data.bannername)
  27.           setUrl(res.data.data.url)
  28.           form.setFieldsValue({
  29.             bannername: res.data.data.bannername,
  30.             url: res.data.data.url,
  31.           });
  32.         }
  33.       })
  34.     }
  35.   }, [visible]);
  36.   useEffect(() => {
  37.     if (id) {
  38.       setTitle('修改轮播图')
  39.     } else {
  40.       setTitle('新增轮播图')
  41.     }
  42.   }, [id])
  43.   const handleOk = () => {
  44.     try {
  45.       setConfirmLoading(true);
  46.       if (id) {
  47.         getBannerUpdate({
  48.           id: id,
  49.           bannername,
  50.           url
  51.         }).then((res: any) => {
  52.           if (res.data.code === 200) {
  53.             message.success(res.data.message);
  54.             setConfirmLoading(false);
  55.             setLocalVisible(false);
  56.             onClose();
  57.             onRefresh(); // 调用父组件传递的回调函数
  58.           } else {
  59.             message.error(res.data.message);
  60.             setConfirmLoading(false);
  61.           }
  62.         })
  63.       } else {
  64.         getBannerAdd({
  65.           bannername,
  66.           url
  67.         }).then((res: any) => {
  68.           if (res.data.code === 200) {
  69.             message.success(res.data.message);
  70.             setConfirmLoading(false);
  71.             setLocalVisible(false);
  72.             onClose();
  73.             onRefresh(); // 调用父组件传递的回调函数
  74.           } else {
  75.             message.error(res.data.message);
  76.             setConfirmLoading(false);
  77.           }
  78.         })
  79.       }
  80.     } catch (err: any) {
  81.       message.error(err);
  82.     }
  83.   };
  84.   const handleCancel = () => {
  85.     setLocalVisible(false);
  86.     onClose();
  87.   };
  88.   const props: UploadProps = {
  89.     name: 'file',
  90.     action: API_URL + '/banner/upload',
  91.     headers: {
  92.       Authorization: getToken() || 'defaultTokenValue',
  93.     },
  94.     onChange(info) {
  95.       if (info.file.status !== 'uploading') {
  96.         // console.log(info.file, info.fileList);
  97.       }
  98.       if (info.file.status === 'done') {
  99.         message.success(`${info.file.name} file uploaded successfully`);
  100.         setUrl(info.file.response.data.url);
  101.       } else if (info.file.status === 'error') {
  102.         message.error(`${info.file.name} file upload failed.`);
  103.       }
  104.     },
  105.   };
  106.   return (
  107.     <div>
  108.       <Modal title={title} open={localVisible} onOk={handleOk} onCancel={handleCancel} confirmLoading={confirmLoading} footer={
  109.         [
  110.           <Button key="cancel" onClick={handleCancel}>取消</Button>,
  111.           <Button key="confirm" type="primary" onClick={handleOk} loading={confirmLoading}>确认</Button>
  112.         ]
  113.       }>
  114.         <Form layout="vertical" form={form}>
  115.           <Form.Item label="轮播图名称" name="bannername" rules={[{ required: true, message: '请输入轮播图名称' }]}>
  116.             <Input placeholder="请输入轮播图名称" value={bannername} onChange={(e) => setBannername(e.target.value)}></Input>
  117.           </Form.Item>
  118.           <Form.Item label="轮播图" name="url" rules={[{ required: true, message: '请上传轮播图' }]}>
  119.             <Upload {...props} maxCount={1} showUploadList={false}>
  120.               <Button icon={<UploadOutlined />}>上传</Button>
  121.             </Upload>
  122.           </Form.Item>
  123.           {
  124.             url ? <Form.Item label="轮播图预览" name="url">
  125.               <Image width={200} src={url} />
  126.             </Form.Item> : ''
  127.           }
  128.         </Form>
  129.       </Modal>
  130.     </div>
  131.   )
  132. }
  133. export default BannerAdd;
复制代码
 pages/BannerList/index.sass

  1. .banner_button
  2.     margin-left: 10px
  3. .banner_opertion
  4.     display: flex
  5.     justify-content: space-evenly
  6.     align-items: center
  7.     cursor: pointer
  8.     color: #26a0f1
复制代码
完备代码

   看本人git地址啦

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/) Powered by Discuz! X3.4