Browse Source

商品列表-完

daxia 1 year ago
parent
commit
860cd49daf

+ 26 - 3
20_React.js_VIP22/day-9/code/react-project-demo/src/pages/GoodsList/goods.scss

@@ -1,3 +1,6 @@
+$contentWidth: 400px;
+$titleFontSize: 24px;
+
 .goods-list {
   width: 500px;
   margin: 0 auto;
@@ -15,9 +18,29 @@
 
     text-align: left;
 
-    .ant-input, .ant-checkbox-wrapper {
-      width: 400px;
-    
+    .ant-input,
+    .ant-checkbox-wrapper {
+      width: $contentWidth;
+    }
+  }
+
+  table {
+    margin: 20px auto 0 auto;
+
+    width: $contentWidth;
+    text-align: left;
+
+    th {
+      font-size: $titleFontSize;
+    }
+
+    .cate {
+      font-weight: 700;
+      font-size: $titleFontSize;
+    }
+
+    .unstocked {
+      color: #ee3b3b;
     }
   }
 }

+ 4 - 1
20_React.js_VIP22/day-9/code/react-project-demo/src/pages/GoodsList/goodsSlice.js

@@ -19,5 +19,8 @@ export const { setList } = goodsSlice.actions;
 
 export const getGoodsList = () => async (dispath) => {
   // 发起网络请求
-  let { code, data, msg } = await getAllGoods();
+  let { code, data } = await getAllGoods();
+  if (code) return; //! 请求回来的数据 不对
+
+  dispath(setList(data));
 };

+ 91 - 3
20_React.js_VIP22/day-9/code/react-project-demo/src/pages/GoodsList/index.jsx

@@ -2,15 +2,103 @@ import { Input, Checkbox } from 'antd';
 import './goods.scss';
 import store from '../../store';
 import { getGoodsList } from './goodsSlice';
+import { useSelector } from 'react-redux';
+import { useState } from 'react';
 
 function GoodsList() {
+  const list = useSelector(({ goods }) => goods.list);
+
+  // 双向绑定
+  let [searchName, setSearchName] = useState('');
+  let [showStocked, setShowStocked] = useState(false);
+
+  let cate = ''; // 记录上一次的分类名称
+
+  function renderList() {
+    let res = [];
+
+    // 检索包含searchName的所有商品
+    let renderList = list.filter((p) =>
+      p.name.toLowerCase().includes(searchName.toLowerCase())
+    );
+    // 如果复选框选中,将没有库存商品过滤掉
+    if (showStocked) {
+      renderList = renderList.filter((p) => p.amount);
+    }
+
+    renderList.forEach((l) => {
+      // // 如果当前商品的分类与上一次一直 就不需要渲染分类行
+      // if (l.category == cate) {
+      //   res.push(
+      //     <tr>
+      //       <td>{l.name}</td>
+      //       <td>{l.price}</td>
+      //     </tr>
+      //   );
+      // } else {
+      //   // 这时就需要渲染分类行
+      //   res.push(
+      //     <tr>
+      //       <td colSpan={2}>{l.category}</td>
+      //     </tr>
+      //   );
+      //   res.push(
+      //     <tr>
+      //       <td>{l.name}</td>
+      //       <td>{l.price}</td>
+      //     </tr>
+      //   );
+      // }
+      if (l.category != cate) {
+        // 如果当前商品分类 与上一次 不一样 就需要渲染分类行
+        res.push(
+          <tr className="cate">
+            <td colSpan={2}>{l.category}</td>
+          </tr>
+        );
+
+        // 记录当前分类标题
+        cate = l.category;
+      }
+      res.push(
+        <tr>
+          <td className={l.amount ? '' : 'unstocked'}>{l.name}</td>
+          <td>{`$${l.price}`}</td>
+        </tr>
+      );
+    });
+
+    return res;
+  }
+
   return (
     <div className="goods-list">
       <div className="search-bar">
-        <Input placeholder="通过商品名检索..." />
-        <Checkbox>仅显示有库存的商品</Checkbox>
+        <Input
+          placeholder="通过商品名检索..."
+          value={searchName}
+          onChange={(e) => {
+            setSearchName(e.target.value);
+          }}
+        />
+        <Checkbox
+          checked={showStocked}
+          onChange={(e) => {
+            setShowStocked(e.target.checked);
+          }}
+        >
+          仅显示有库存的商品
+        </Checkbox>
       </div>
-      <table></table>
+      <table>
+        <thead>
+          <tr>
+            <th>商品名称</th>
+            <th>商品价格</th>
+          </tr>
+        </thead>
+        <tbody>{renderList()}</tbody>
+      </table>
     </div>
   );
 }

+ 7 - 0
20_React.js_VIP22/day-9/code/react-project-demo/src/utils/http.js

@@ -1,4 +1,6 @@
 import axios from 'axios';
+import { message } from 'antd';
+import { redirect } from 'react-router-dom';
 
 const axiosInstance = axios.create({
   baseURL: '/api/v1',
@@ -32,9 +34,14 @@ axiosInstance.interceptors.response.use(
     // 超出 2xx 范围的状态码都会触发该函数。
     // 对响应错误做点什么
     // 401错误处理
+    console.log(error);
     if (error.response.status == 401) {
       //! 提示用户 未登录或者 登录超时
+      message.error('您未登录或登录已超时!请重新登录。');
       //! 页面重定向到 登录上
+      redirect('/login');
+
+      return Promise.resolve({});
     }
     return Promise.reject(error);
   }