提交 5239364a 作者: 曹云

Merge branch 'master' of ssh://git.mmcuav.cn:8222/root/sharefly-web-nextjs into caoyun

......@@ -13,7 +13,7 @@
/out/
# production
/build
/.dist/
# misc
.DS_Store
......
const dev = {
baseUrl: ''
baseUrl: 'local'
}
const prod = {
baseUrl: 'http://120.77.247.178'
baseUrl: 'https://iuav.mmcuav.cn'
}
export default process.env.NODE_ENV === 'development' ? dev : prod;
\ No newline at end of file
......@@ -5,10 +5,10 @@ import config from './config';
* @param url 请求url
* @param method 请求方法类型
* @param data 请求的参数
* @param options 额外参数
* @returns Promise<Response>
*/
export default function request(url: string, method: String = 'get', data?: any): Promise<Response<any>> {
let options = {};
export default function request(url: string, method: String = 'get', data?: any, options = {}): Promise<Response<any>> {
switch (method.toLowerCase()) {
case 'get':
......@@ -24,6 +24,7 @@ export default function request(url: string, method: String = 'get', data?: any)
case 'post':
options = {
...options,
method: 'POST',
headers: {
'Content-Type': 'application/json'
......@@ -48,6 +49,19 @@ export default function request(url: string, method: String = 'get', data?: any)
})
.then((data) => {
return data;
})
.catch(error => {
if (error.name === 'AbortError') {
console.log('请求已中断');
console.log(error);
} else {
console.error('请求出错', error);
}
return {
code: '-1',
message: '请求失败',
result: null
}
});
}
......@@ -55,5 +69,5 @@ export default function request(url: string, method: String = 'get', data?: any)
export interface Response<T> {
code: string,
message: string,
result: T
result?: T | null
}
\ No newline at end of file
import { Space, Button, Select } from 'antd';
import styles from '../../index.module.scss';
import { Space, Button, Select, Collapse } from "antd";
import styles from "../../index.module.scss";
import api, { FilterOptionResp } from "../../api";
import { useEffect, useState } from "react";
......@@ -8,13 +8,13 @@ type Props = {
};
export default function BrandItem(props: Props) {
const [data, setData] = useState<FilterOptionResp[]>([])
const [data, setData] = useState<FilterOptionResp[]>([]);
useEffect(() => {
api.brand().then(res => {
api.brand().then((res) => {
setData(res?.result || []);
});
}, [])
}, []);
const onClick = (item: FilterOptionResp) => {
props.onChange({
......@@ -26,15 +26,47 @@ export default function BrandItem(props: Props) {
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>品牌:</div>
<div className={styles.filterItemMain}>
<Space size={40}>
{
data.map(item => {
return <Button type="link" key={item.id} onClick={(e) => onClick(item)}>{item.name}</Button>;
})
}
</Space>
<div className={`${styles.filterItemMain} ${data.length <= 10 && styles.disabled}`}>
<Collapse
ghost
collapsible="icon"
expandIconPosition="end"
>
<Collapse.Panel
header={
<Space size={40}>
{data.slice(0, 10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
);
}
\ No newline at end of file
}
import { Space, Button, Select } from 'antd';
import { Space, Button, Select, Collapse } from 'antd';
import styles from '../../index.module.scss';
import api, { FilterOptionResp } from "../../api";
import { useState, useEffect } from 'react';
......@@ -26,14 +26,45 @@ export default function CategoryItem(props: Props) {
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>类目:</div>
<div className={styles.filterItemMain}>
<Space size={40}>
{
data.map(item => {
return <Button type="link" key={item.id} onClick={(e) => onClick(item)}>{item.name}</Button>;
})
}
</Space>
<div
className={`${styles.filterItemMain} ${
data.length <= 10 && styles.disabled
}`}
>
<Collapse ghost collapsible="icon" expandIconPosition="end">
<Collapse.Panel
header={
<Space size={40}>
{data.slice(0, 10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
);
......
import { Space, Button, Select } from 'antd';
import { Space, Button, Select, Collapse } from 'antd';
import styles from '../../index.module.scss';
import api, { FilterOptionResp } from "../../api";
import { useEffect, useState } from 'react';
......@@ -26,14 +26,45 @@ export default function ModelItem(props: Props) {
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>型号:</div>
<div className={styles.filterItemMain}>
<Space size={40}>
{
data?.map(item => {
return <Button type="link" key={item.id} onClick={(e) => onClick(item)}>{item.name}</Button>;
})
}
</Space>
<div
className={`${styles.filterItemMain} ${
data.length <= 10 && styles.disabled
}`}
>
<Collapse ghost collapsible="icon" expandIconPosition="end">
<Collapse.Panel
header={
<Space size={40}>
{data.slice(0, 10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
);
......
import { Space, Button, Select } from 'antd';
import { Space, Button, Select, Collapse } from 'antd';
import styles from '../../index.module.scss';
import api, { FilterOptionResp } from "../../api";
import { useState, useEffect } from 'react';
......@@ -26,16 +26,45 @@ export default function PartItem(props: Props) {
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>部件:</div>
<div className={styles.filterItemMain}>
<Space size={40}>
{data?.map((item) => {
return (
<Button type="link" key={item.id} onClick={(e) => onClick(item)}>
{item.name}
</Button>
);
})}
</Space>
<div
className={`${styles.filterItemMain} ${
data.length <= 10 && styles.disabled
}`}
>
<Collapse ghost collapsible="icon" expandIconPosition="end">
<Collapse.Panel
header={
<Space size={40}>
{data.slice(0, 10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
);
......
import { Space, Button, Select } from 'antd';
import { Space, Button, Select, Collapse } from 'antd';
import styles from '../../index.module.scss';
import api, { FilterOptionResp } from "../../api";
import { useState, useEffect } from 'react';
......@@ -26,16 +26,45 @@ export default function QualityItem(props: Props) {
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>成色:</div>
<div className={styles.filterItemMain}>
<Space size={40}>
{data?.map((item) => {
return (
<Button type="link" key={item.id} onClick={(e) => onClick(item)}>
{item.name}
</Button>
);
})}
</Space>
<div
className={`${styles.filterItemMain} ${
data.length <= 10 && styles.disabled
}`}
>
<Collapse ghost collapsible="icon" expandIconPosition="end">
<Collapse.Panel
header={
<Space size={40}>
{data.slice(0, 10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(10).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
);
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
);
......
......@@ -9,27 +9,47 @@
}
.filterItem {
height: 42px;
min-height: 42px;
border-bottom: 1px dashed RGBA(222, 222, 222, 1);
display: flex;
align-items: center;
&:nth-last-child(1) {
border-bottom: none;
}
.filterItemTitle {
flex-shrink: 0;
width: 80px;
margin-right: 8px;
font-family: MicrosoftYaHei;
color: rgba(153, 153, 153, 1);
line-height: 20px;
height: auto;
margin-top: 10px;
}
.filterItemMain {
flex: 1;
display: flex;
justify-content: space-between;
&.disabled {
:global .ant-collapse-expand-icon {
display: none;
}
}
:global .ant-collapse-item {
.ant-collapse-expand-icon {
margin-top: 10px;
}
.ant-collapse-header {
padding: 0;
height: 42px;
line-height: 42px;
}
}
}
:global .ant-select-selector {
......
/** @type {import('next').NextConfig} */
let distDir = ".next"; //默认输出目录
if (process.env.NODE_ENV === "production") {
//生产环境用另一个目录构建,防止与dev冲突
distDir = ".dist";
}
const nextConfig = {
distDir,
reactStrictMode: true,
transpilePackages: ["antd"],
redirects() {
......@@ -14,8 +22,8 @@ const nextConfig = {
async rewrites() {
return [
{
source: "/:path*",
destination: "http://120.77.247.178/:path*",
source: "/local/:path*",
destination: "https://iuav.mmcuav.cn/:path*",
},
];
},
......
......@@ -46,7 +46,7 @@ export default function FlyingHandService() {
pageSize: 10,
})
.then((res) => {
setProductList(res.result?.list.map(item=>{return { element:leftDom(item) }}))
setProductList(res.result?.list.map(item=>{return { element:leftDom(item) }}) || [])
});
}, []);
......
import request, { Response } from "~/api/request";
export interface DynamicListParams {
pageNo: number,
pageSize: number,
userId: number
}
export interface Dynamic {
userId: number;
id: number;
title: string;
description: string;
location: string;
lat: number;
lon: number;
mediaVO: {
picture: string[];
videoUrl: string;
};
likesCount: number;
commentCount: number;
likes: boolean;
}
export interface DynamicListResp {
pageNo: 1;
pageSize: 10;
list: Array<Dynamic>;
totalCount: 0;
totalPage: 0;
}
export default {
/**
* 论坛动态列表
* @param params
* @returns
*/
dynamicList(params: DynamicListParams): Promise<Response<DynamicListResp>> {
return request("/release/dynamic/dynamicList", "get", params);
},
};
......@@ -30,6 +30,7 @@
.item {
padding: 18px 0 0;
background: #ffffff;
width: 100%;
.headImg {
margin-left: 16px;
......
......@@ -35,7 +35,7 @@ export interface ListPageGoodsInfoResp {
export default {
//web-商品信息-分页
listPageGoodsInfo: (params: ListPageGoodsInfoParams): Promise<Response<ListPageGoodsInfoResp>> => {
return request('/pms/webProductMall/listPageGoodsInfo', 'post', params)
listPageGoodsInfo: (params: ListPageGoodsInfoParams, options = {}): Promise<Response<ListPageGoodsInfoResp>> => {
return request('/pms/webProductMall/listPageGoodsInfo', 'post', params, options)
}
}
\ No newline at end of file
......@@ -24,11 +24,15 @@
}
}
.listContent{
width: 100%;
}
.listWrap {
display: flex;
flex-wrap: wrap;
gap: 12px;
height: fit-content;
height: 856px;
.item {
cursor: pointer;
......
import React, { useEffect, useState } from "react";
import { Button, Pagination, Select, Space, Tag } from "antd";
import { Button, Empty, Pagination, Select, Space, Tag } from "antd";
import Layout from "~/components/layout";
import styles from "./index.module.scss";
import { useRouter } from "next/router";
......@@ -25,23 +25,35 @@ export default function Mall(props: Props) {
pageSize: 16,
});
const [count, setCount] = useState(0);
const [abort, setAbort] = useState<AbortController | null>(null);
useEffect(() => {
//中断前一次请求
abort?.abort();
setAbort(new AbortController());
}, [filterResult, pageParams]);
useEffect(() => {
api
.listPageGoodsInfo({
brandId: filterResult.brand?.id,
districtId: filterResult.region?.id,
modelId: filterResult.model?.id,
partsId: filterResult.part?.id,
productCategoryId: filterResult.category?.id,
qualityId: filterResult.quality?.id,
...pageParams,
})
.listPageGoodsInfo(
{
brandId: filterResult.brand?.id,
districtId: filterResult.region?.id,
modelId: filterResult.model?.id,
partsId: filterResult.part?.id,
productCategoryId: filterResult.category?.id,
qualityId: filterResult.quality?.id,
...pageParams,
},
{
signal: abort?.signal,
}
)
.then((res) => {
setProductList(res.result?.list || []);
setCount(res.result?.totalCount);
setCount(res.result?.totalCount || 0);
});
}, [filterResult, pageParams]);
}, [abort]);
const onFilterChange = (filterResult: FilterResult) => {
console.log("filterResult", filterResult);
......@@ -52,8 +64,8 @@ export default function Mall(props: Props) {
setPageParams({
...pageParams,
pageNo: page,
})
}
});
};
return (
<Layout>
<div className="page" style={{ paddingTop: "18px" }}>
......@@ -65,36 +77,47 @@ export default function Mall(props: Props) {
<div className={styles.productList}>
<div className={styles.title}>四旋翼无人机</div>
<div className={styles.main}>
<ul className={styles.listWrap}>
{productList.map((item, i) => {
return (
<li
key={i}
className={styles.item}
onClick={() => router.push("/mall/detail/1")}
>
<div className={styles.imgBox}>
<Image
alt=""
src={item.imgUrl}
className={styles.img}
width={116}
height={116}
></Image>
</div>
<div className={styles.title}>{item.goodsName}</div>
<div className={styles.sellCount}>半年售{(Math.floor(Math.random() * 901) + 100).toFixed(0)}</div>
</li>
);
})}
<div className={styles.listContent}>
<ul className={styles.listWrap}>
{productList.map((item, i) => {
return (
<li
key={i}
className={styles.item}
onClick={() => router.push("/mall/detail/1")}
>
<div className={styles.imgBox}>
<Image
alt=""
src={item.imgUrl}
className={styles.img}
width={116}
height={116}
></Image>
</div>
<div className={styles.title}>{item.goodsName}</div>
<div className={styles.sellCount}>
半年售
{(Math.floor(Math.random() * 901) + 100).toFixed(0)}
</div>
</li>
);
})}
{productList.length === 0 && (
<Empty style={{ paddingTop: 20, width: '100%', textAlign: "center" }}></Empty>
)}
</ul>
<Pagination
current={pageParams.pageNo}
showSizeChanger={false}
showQuickJumper
total={count}
onChange={onPageChange}
hideOnSinglePage={true}
style={{marginTop: 20}}
/>
</ul>
</div>
<div className={styles.adList}>
<div className={styles.ad}></div>
<div className={styles.ad}></div>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论