提交 39368c2a 作者: 曹云

Merge branch 'master' of ssh://git.mmcuav.cn:8222/iuav/csf-web into feature/chuck

import request, { Response } from "~/api/request"; import request, { Response } from '~/api/request'
import config from "./config"; import config from './config'
export interface RegionResp { export interface RegionResp {
childInfo?: RegionResp[] | null; childInfo?: RegionResp[] | null
id: number; id: number
level: number; level: number
name: string; name: string
pid: number; pid: number
} }
export interface UserInfoResp { export interface UserInfoResp {
id: number; id: number
accountType: number; accountType: number
uid: string; uid: string
phoneNum: string; phoneNum: string
userName: string; userName: string
nickName: string; nickName: string
userImg: string; userImg: string
userSex: number; userSex: number
email: string; email: string
source: number; source: number
accountStatus: number; accountStatus: number
remark: string; remark: string
portType: number; portType: number
createTime: string; createTime: string
companyAuthStatus: number; companyAuthStatus: number
token: string; token: string
cooperationTagId: number | null
} }
export interface TestAppletLoginResp { export interface TestAppletLoginResp {
userAccountId: number; userAccountId: number
token: string; token: string
uid: string; uid: string
phoneNum?: string; phoneNum?: string
nickName: string; nickName: string
sessionKey?: any; sessionKey?: any
} }
export default { export default {
//获取区域数据 //获取区域数据
region: (): Promise<Response<Array<RegionResp>>> => { region: (): Promise<Response<Array<RegionResp>>> => {
return request("/pms/webDevice/getSecondDistrictInfo"); return request('/pms/webDevice/getSecondDistrictInfo')
}, },
//测试-小程序unionId登录-注册 //测试-小程序unionId登录-注册
testAppletLogin: (): Promise<Response<TestAppletLoginResp>> => { testAppletLogin: (): Promise<Response<TestAppletLoginResp>> => {
let params = new URLSearchParams(); let params = new URLSearchParams()
params.append("unionId", "oQZEd5hy0Qrwaj10BGtP8xq8vH--s88888"); params.append('unionId', 'oQZEd5hy0Qrwaj10BGtP8xq8vH--s88888')
return request( return request(
"/userapp/auth/testAppletLogin", '/userapp/auth/testAppletLogin',
"post", 'post',
{}, {},
{ {
headers: { headers: {
"Content-Type": "application/x-www-form-urlencoded", 'Content-Type': 'application/x-www-form-urlencoded',
}, },
body: params, body: params,
} }
); )
}, },
//生成小程序码 //生成小程序码
getAppletQRCode: (params: { randomLoginCode: string }) => { getAppletQRCode: (params: { randomLoginCode: string }) => {
return request("/userapp/wx/getAppletQRCode", "get", { return request('/userapp/wx/getAppletQRCode', 'get', {
page: "page-identity/identity-empower/index", page: 'page-identity/identity-empower/index',
scene: "randomLoginCode=" + params.randomLoginCode, scene: 'randomLoginCode=' + params.randomLoginCode,
}); })
}, },
//查询登录信息 //查询登录信息
getLoginInfo: (params: { randomLoginCode: string }) => { getLoginInfo: (params: { randomLoginCode: string }) => {
return request("/userapp/temp-auth/getLoginInfo", "get", params, { return request('/userapp/temp-auth/getLoginInfo', 'get', params, {
hideError: true //隐藏错误提示 hideError: true, //隐藏错误提示
}); })
}, },
//获取用户基本信息 //获取用户基本信息
userInfo: (): Promise<Response<UserInfoResp>> => { userInfo: (): Promise<Response<UserInfoResp>> => {
return request("/userapp/user-account/info", "get"); return request('/userapp/user-account/info', 'get')
}, },
//图片上传地址 //图片上传地址
imgOss: () => { imgOss: () => {
return config.baseUrl + "/pms/upload/imgOss"; return config.baseUrl + '/pms/upload/imgOss'
}, },
}; }
import config from './config'; import config from './config';
let loginTimeout: NodeJS.Timeout | undefined;
/** /**
* 请求封装 * 请求封装
* @param url 请求url * @param url 请求url
...@@ -43,12 +45,31 @@ export default function request(url: string, method: String = 'get', data?: any, ...@@ -43,12 +45,31 @@ export default function request(url: string, method: String = 'get', data?: any,
} }
} }
/**
* 错误消息
* @param msg
*/
function errMsg(msg: string) { function errMsg(msg: string) {
if (!options.hideError) { if (!options.hideError) {
window.messageApi.error(msg); window.messageApi.error(msg);
} }
} }
/**
* 未登录消息展示,1.5秒内限制只展示一次
* @returns
*/
function loginErrorMsg(){
console.log('loginTimeout', loginTimeout)
if(loginTimeout){
return;
}
loginTimeout = setTimeout(() => {
errMsg('请先登录');
loginTimeout = undefined;
}, 1500)
}
return fetch(config.baseUrl + url, options) return fetch(config.baseUrl + url, options)
.then((r) => { .then((r) => {
try { try {
...@@ -84,8 +105,9 @@ export default function request(url: string, method: String = 'get', data?: any, ...@@ -84,8 +105,9 @@ export default function request(url: string, method: String = 'get', data?: any,
if (data.code !== '200') { if (data.code !== '200') {
//未登录判断 //未登录判断
if(data.code === '5008'){ if(data.code === '5008' || data.code === '2014'){
errMsg('请先登录'); loginErrorMsg();
window.logout();
}else{ }else{
errMsg(data.message || '请求出错'); errMsg(data.message || '请求出错');
} }
......
...@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from "react"; ...@@ -2,7 +2,7 @@ import React, { useContext, useEffect, useState } from "react";
import { Avatar, Button, Dropdown, Space, Tabs } from "antd"; import { Avatar, Button, Dropdown, Space, Tabs } from "antd";
import type { TabsProps } from "antd"; import type { TabsProps } from "antd";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { useRouter } from "next/router"; import { Router, useRouter } from "next/router";
import LoginModal from "~/components/loginModal"; import LoginModal from "~/components/loginModal";
import PublishModal from "./publishModal"; import PublishModal from "./publishModal";
import JoinModal from "./joinModal"; import JoinModal from "./joinModal";
...@@ -39,17 +39,21 @@ const items: TabsProps["items"] = [ ...@@ -39,17 +39,21 @@ const items: TabsProps["items"] = [
}, },
]; ];
export default function NavHeader() { type Props = {
style?: React.CSSProperties;
};
export default function NavHeader(props: Props) {
const router = useRouter(); const router = useRouter();
const [currentPath, setCurrentPath] = useState(""); const [currentPath, setCurrentPath] = useState("");
const { userInfo, testLogin, logout, setNeedLogin, needLogin } = const { userInfo, testLogin, logout, setNeedLogin, needLogin } =
useContext(UserContext); useContext(UserContext);
useEffect(() => { useEffect(() => {
const routerTo = items?.filter(item=>router.route.includes(item.key))[0] const routerTo = items?.filter((item) => router.route == item.key)[0];
if (routerTo) { if (routerTo) {
setCurrentPath(routerTo?.key!); setCurrentPath(routerTo?.key!);
}else{ } else {
setCurrentPath(router.route); setCurrentPath(router.route);
} }
console.log("currentHash", currentPath); console.log("currentHash", currentPath);
...@@ -75,7 +79,7 @@ export default function NavHeader() { ...@@ -75,7 +79,7 @@ export default function NavHeader() {
if (!userInfo) { if (!userInfo) {
setOpenLoginModal(true); setOpenLoginModal(true);
} else { } else {
setOpenPublishModal(true); setOpenPublishModal(true);
} }
} }
...@@ -97,7 +101,7 @@ export default function NavHeader() { ...@@ -97,7 +101,7 @@ export default function NavHeader() {
}, [needLogin]); }, [needLogin]);
return ( return (
<div className={styles.navHeader}> <div className={styles.navHeader} style={props.style}>
<div className={styles.nav}> <div className={styles.nav}>
<div className={styles.logo}></div> <div className={styles.logo}></div>
<Tabs <Tabs
...@@ -120,6 +124,18 @@ export default function NavHeader() { ...@@ -120,6 +124,18 @@ export default function NavHeader() {
<Dropdown <Dropdown
menu={{ menu={{
items: [ items: [
{
key: "2",
label: (
<div
onClick={() =>
router.push("/personalCenter/servicesOrders")
}
>
我的订单
</div>
),
},
{ key: "1", label: <div onClick={onLogout}>退出登录</div> }, { key: "1", label: <div onClick={onLogout}>退出登录</div> },
], ],
}} }}
......
...@@ -23,7 +23,6 @@ export default function PublishModal(props: Props) { ...@@ -23,7 +23,6 @@ export default function PublishModal(props: Props) {
const position = useGeolocation(); const position = useGeolocation();
const { reloadRequirements, setReloadRequirements } = const { reloadRequirements, setReloadRequirements } =
useContext(CommonContext); useContext(CommonContext);
console.log("position", position);
useEffect(() => { useEffect(() => {
api.listType().then((res) => { api.listType().then((res) => {
......
import request, { Response } from "~/api/request"; import request, { Response } from '~/api/request'
export interface FilterOptionResp { export interface FilterOptionResp {
id: number; id: number
name?: string; name?: string
appName?: string; appName?: string
} }
export interface RegionResp { export interface RegionResp {
childInfo: RegionResp[] | null; childInfo: RegionResp[] | null
id: number; id: number
level: number; level: number
name: string; name: string
pid: number; pid: number
}
export interface InfoList {
id: number
directoryId: number
name: string
icon: string
}
export interface TypesResp {
directoryId: number
name: string
categoriesInfoListDTO: InfoList[]
} }
export default { export default {
category: (): Promise<Response<Array<FilterOptionResp>>> => { category: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/category"); return request('/pms/webProductMall/category')
}, },
categoryId: (): Promise<Response<Array<FilterOptionResp>>> => { categoryId: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/category"); return request('/pms/webDevice/category')
}, },
brand: (): Promise<Response<Array<FilterOptionResp>>> => { brand: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/brand"); return request('/pms/webDevice/brand')
}, },
model: (): Promise<Response<Array<FilterOptionResp>>> => { model: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/model"); return request('/pms/webDevice/model')
}, },
part: (): Promise<Response<Array<FilterOptionResp>>> => { part: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/parts"); return request('/pms/webProductMall/parts')
}, },
quality: (): Promise<Response<Array<FilterOptionResp>>> => { quality: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/quality"); return request('/pms/webProductMall/quality')
}, },
region: (): Promise<Response<Array<RegionResp>>> => { region: (): Promise<Response<Array<RegionResp>>> => {
return request("/pms/webDevice/getSecondDistrictInfo"); return request('/pms/webDevice/getSecondDistrictInfo')
}, },
industry: (): Promise<Response<Array<RegionResp>>> => { industry: (): Promise<Response<Array<RegionResp>>> => {
return request("/release/work/listAllIndustry"); return request('/release/work/listAllIndustry')
}, },
appType: (): Promise<Response<Array<RegionResp>>> => { appType: (): Promise<Response<Array<RegionResp>>> => {
return request("/release/work/listAllAppType"); return request('/release/work/listAllAppType')
}, },
deviceBrand: (): Promise<Response<Array<RegionResp>>> => { deviceBrand: (): Promise<Response<Array<RegionResp>>> => {
return request("/pms/webDevice/deviceBrand"); return request('/pms/webDevice/deviceBrand')
}, },
deviceModel: (): Promise<Response<Array<RegionResp>>> => { deviceModel: (): Promise<Response<Array<RegionResp>>> => {
return request("/pms/webDevice/deviceModel"); return request('/pms/webDevice/deviceModel')
}, },
}; infoByType: (params: {
type: number
}): Promise<Response<Array<TypesResp>>> => {
return request('/pms/classify/queryCategoryInfoByType', 'get', params)
},
}
import { Space, Select } from "antd"; import { Space, Select } from 'antd'
import { useEffect, useState } from "react"; import { useEffect, useState } from 'react'
import styles from "../../index.module.scss"; import styles from '../../index.module.scss'
import api, { RegionResp } from "../../api"; import api, { RegionResp } from '../../api'
type Props = { type Props = {
onChange: (item: RegionResp) => void; onChange: (item: RegionResp) => void
}; }
export default function RegionItem(props: Props) { export default function RegionItem(props: Props) {
const [provinceList, setProvinceList] = useState<RegionResp[]>([]); const [provinceList, setProvinceList] = useState<RegionResp[]>([])
const [cityList, setCityList] = useState<RegionResp[]>([]); const [cityList, setCityList] = useState<RegionResp[]>([])
const [selectCity, setSelectCity] = useState<number>() const [selectCity, setSelectCity] = useState<number>()
useEffect(() => { useEffect(() => {
api.region().then((res) => { api.region().then((res) => {
setProvinceList(res?.result || []); setProvinceList(res?.result || [])
}); })
}, []); }, [])
const onProvinceChange = (value: number, item: any) => { const onProvinceChange = (value: number, item: any) => {
console.log("省", value, item); console.log('省', value, item)
setCityList(item.childInfo || []); setCityList(item.childInfo || [])
setSelectCity(undefined); setSelectCity(undefined)
props.onChange(item); props.onChange(item)
}; }
const onCityChange = (value: number, item: any) => { const onCityChange = (value: number, item: any) => {
console.log("市", value); console.log('市', value)
setSelectCity(value); setSelectCity(value)
props.onChange(item); props.onChange(item)
}; }
return ( return (
<div className={styles.filterItem}> <div className={styles.filterItem}>
<div className={styles.filterItemTitle}>地域:</div> <div className={styles.filterItemTitle}>地域:</div>
...@@ -44,10 +44,10 @@ export default function RegionItem(props: Props) { ...@@ -44,10 +44,10 @@ export default function RegionItem(props: Props) {
...item, ...item,
value: item.id, value: item.id,
label: item.name, label: item.name,
}; }
})} })}
/> />
<Select {/* <Select
value={selectCity} value={selectCity}
bordered={false} bordered={false}
popupMatchSelectWidth={false} popupMatchSelectWidth={false}
...@@ -60,9 +60,9 @@ export default function RegionItem(props: Props) { ...@@ -60,9 +60,9 @@ export default function RegionItem(props: Props) {
label: item.name, label: item.name,
}; };
})} })}
/> /> */}
</Space> </Space>
</div> </div>
</div> </div>
); )
} }
import { Space, Tag } from "antd"; import { Space, Tag } from 'antd'
import { FilterResult } from "../.."; import { FilterResult } from '../..'
import styles from "../../index.module.scss"; import styles from '../../index.module.scss'
import { InfoList } from '../../api'
type Props = { type Props = {
data: FilterResult; data: FilterResult
onDel: (key: string) => void; onDel: (key: string | number) => void
}; }
export default function ResultItem({data, onDel}: Props) { export default function ResultItem({ data, onDel }: Props) {
return ( return (
<div className={styles.filterItem}> <div className={styles.filterItem}>
<div className={styles.filterItemTitle}>已选:</div> <div className={styles.filterItemTitle}>已选:</div>
<div className={styles.filterItemMain}> <div className={styles.filterItemMain}>
<Space size={10}> <Space size={10}>
{data && {data.provinceId && (
Object.keys(data).map((key) => { // Object.keys(data).map((key) => {
//@ts-ignore // //@ts-ignore
let item = data[key]; // let item = data[key]
// return (
// <Tag
// closable
// onClose={(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
// onDel(key)
// }}
// key={key}
// >
// {item?.name}
// </Tag>
// )
// })
<Tag
closable
onClose={(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
onDel('provinceId')
}}
key={data.provinceId.id}
>
{data.provinceId.name}
</Tag>
)}
{data.categoryId &&
data.categoryId.map((item: InfoList, index) => {
return ( return (
<Tag <Tag
closable closable
onClose={(e: React.MouseEvent<HTMLElement, MouseEvent>) => { onClose={(e: React.MouseEvent<HTMLElement, MouseEvent>) => {
onDel(key); onDel(item.id)
}} }}
key={key} key={item.name}
> >
{item?.name} {item?.name}
</Tag> </Tag>
); )
})} })}
</Space> </Space>
</div> </div>
</div> </div>
); )
} }
import { Space, Button, Select, Collapse } from 'antd'
import styles from '../../index.module.scss'
import api, { FilterOptionResp, InfoList } from '../../api'
import { useState, useEffect } from 'react'
type Props = {
onChange: (id: FilterOptionResp) => void
typeName: string
dataValue: InfoList[]
}
export default function CategoryItem(props: Props) {
const [data, setData] = useState<FilterOptionResp[]>([])
useEffect(() => {
setData(props.dataValue || [])
}, [])
const onClick = (item: FilterOptionResp) => {
props.onChange({
id: item.id,
name: `${props.typeName}:` + item.name,
})
}
const showCount = 12 //展示数量
return (
<div className={styles.filterItem}>
<div className={styles.filterItemTitle}>{props.typeName}</div>
<div
className={`${styles.filterItemMain} ${
data.length <= showCount && styles.disabled
}`}
>
<Collapse
ghost
collapsible="icon"
expandIconPosition="end"
style={{ width: '100%' }}
>
<Collapse.Panel
header={
<Space size={[40, 0]}>
{data.slice(0, showCount).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
)
})}
</Space>
}
key="1"
>
<Space size={40}>
{data.slice(showCount).map((item) => {
return (
<Button
type="link"
key={item.id}
onClick={(e) => onClick(item)}
>
{item.name}
</Button>
)
})}
</Space>
</Collapse.Panel>
</Collapse>
</div>
</div>
)
}
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
flex: 1; flex: 1;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
overflow: hidden;
&.disabled { &.disabled {
:global .ant-collapse-expand-icon { :global .ant-collapse-expand-icon {
......
import CategoryItem from "./compoents/categoryItem"; import CategoryItem from './compoents/categoryItem'
import Category from "./compoents/category"; import Category from './compoents/category'
import { FilterOptionResp, RegionResp } from "./api"; import { FilterOptionResp, RegionResp } from './api'
import ResultItem from "./compoents/resultItem"; import ResultItem from './compoents/resultItem'
import RegionItem from "./compoents/regionItem"; import RegionItem from './compoents/regionItem'
import styles from "./index.module.scss"; import styles from './index.module.scss'
import React, { useEffect, useState, forwardRef, useImperativeHandle, Ref } from "react"; import React, {
import { useRouter } from "next/router"; useEffect,
import BrandItem from "./compoents/brandItem"; useState,
import ModelItem from "./compoents/modelItem"; forwardRef,
import PartItem from "./compoents/partItem"; useImperativeHandle,
import QualityItem from "./compoents/qualityItem"; Ref,
import Industry from "./compoents/industry"; } from 'react'
import AppType from "./compoents/appType"; import { useRouter } from 'next/router'
import DeviceBrand from "./compoents/deviceBrand"; import BrandItem from './compoents/brandItem'
import DeviceModel from "./compoents/deviceModel"; import ModelItem from './compoents/modelItem'
import PartItem from './compoents/partItem'
import QualityItem from './compoents/qualityItem'
import Industry from './compoents/industry'
import AppType from './compoents/appType'
import DeviceBrand from './compoents/deviceBrand'
import DeviceModel from './compoents/deviceModel'
import TypeInfo from './compoents/typeInfo'
import api, { TypesResp, InfoList } from './api'
export type AdapterResult = { export type AdapterResult = {
brandId?: number; // brandId?: number
districtId?: number; // districtId?: number
modelId?: number; // modelId?: number
partsId?: number; // partsId?: number
productCategoryId?: number; // productCategoryId?: number
qualityId?: number; // qualityId?: number
industryId?: number; // industryId?: number
appTypeId?: number; // appTypeId?: number
categoryId?: number; categoryId?: any[]
}; provinceId?: number
}
export type FilterResult = { export type FilterResult = {
region?: RegionResp; // region?: RegionResp
brand?: FilterOptionResp; // brand?: FilterOptionResp
category?: FilterOptionResp; // category?: FilterOptionResp
part?: FilterOptionResp; // part?: FilterOptionResp
model?: FilterOptionResp; // model?: FilterOptionResp
quality?: FilterOptionResp; // quality?: FilterOptionResp
industryId?: FilterOptionResp; // industryId?: FilterOptionResp
appTypeId?: FilterOptionResp; // appTypeId?: FilterOptionResp
categoryId?: FilterOptionResp; categoryId?: InfoList[]
}; provinceId?: FilterOptionResp
}
type itemType = type itemType =
| "类目" | '类目'
| "地域" | '地域'
| "品牌" | '品牌'
| "部件" | '部件'
| "型号" | '型号'
| "成色" | '成色'
| "行业" | '行业'
| "应用" | '应用'
| "设备品牌" | '设备品牌'
| "设备型号" | '设备型号'
| "设备类目"; | '设备类目'
type Props = { type Props = {
types: itemType[]; //需要包含的筛选条件项 types: itemType[] //需要包含的筛选条件项
showResultItem: Boolean; //显示结果栏 showResultItem: Boolean //显示结果栏
onChange: ( onChange: (
filterResult: FilterResult, filterResult: FilterResult,
adapterFilterResult: AdapterResult //适配器,直接用于接口请求 adapterFilterResult: AdapterResult //适配器,直接用于接口请求
) => void; //筛选条件更改事件 ) => void //筛选条件更改事件
}; }
const idArr = [ // const idArr = [
"brandId", // 'brandId',
"categoryId", // 'categoryId',
"modelId", // 'modelId',
"partsId", // 'partsId',
"productCategoryId", // 'productCategoryId',
"qualityId", // 'qualityId',
"industryId", // 'industryId',
"appTypeId", // 'appTypeId',
]; // ]
const nameArr: any = { // const nameArr: any = {
brandId: { // brandId: {
type: "brandId", // type: 'brandId',
typeObj: "brand", // typeObj: 'brand',
typeName: "品牌:", // typeName: '品牌:',
}, // },
// districtId: { // // districtId: {
// type:"districtId", // // type:"districtId",
// typeObj:"region", // // typeObj:"region",
// typeName:"地域:", // // typeName:"地域:",
// }, // // },
modelId: { // modelId: {
type: "modelId", // type: 'modelId',
typeObj: "model", // typeObj: 'model',
typeName: "型号:", // typeName: '型号:',
}, // },
partsId: { // partsId: {
type: "partsId", // type: 'partsId',
typeObj: "part", // typeObj: 'part',
typeName: "部件:", // typeName: '部件:',
}, // },
productCategoryId: { // productCategoryId: {
type: "productCategoryId", // type: 'productCategoryId',
typeObj: "category", // typeObj: 'category',
typeName: "类目:", // typeName: '类目:',
}, // },
qualityId: { // qualityId: {
type: "qualityId", // type: 'qualityId',
typeObj: "quality", // typeObj: 'quality',
typeName: "成色:", // typeName: '成色:',
}, // },
industryId: { // industryId: {
type: "industryId", // type: 'industryId',
typeObj: "industryId", // typeObj: 'industryId',
typeName: "行业:", // typeName: '行业:',
}, // },
appTypeId: { // appTypeId: {
type: "appTypeId", // type: 'appTypeId',
typeObj: "appTypeId", // typeObj: 'appTypeId',
typeName: "应用:", // typeName: '应用:',
}, // },
categoryId: { // categoryId: {
type: "categoryId", // type: 'categoryId',
typeObj: "categoryId", // typeObj: 'categoryId',
typeName: "类目:", // typeName: '类目:',
}, // },
}; // }
const Filter = (props: Props, ref: Ref<any>) => { const Filter = (props: Props, ref: Ref<any>) => {
const router = useRouter(); const router = useRouter()
useImperativeHandle(ref, () => ({ useImperativeHandle(ref, () => ({
idArr: idArr,
clearRouter: clearRouter, clearRouter: clearRouter,
})); }))
const [result, setResult] = useState<FilterResult>({}); const [result, setResult] = useState<FilterResult>({})
const onChange = (item: FilterOptionResp, type: string) => { const onChange = (item: FilterOptionResp, type: string) => {
clearRouter(); clearRouter()
let data: { [key: string]: FilterOptionResp } = {}; let data: { [key: string]: FilterOptionResp[] | FilterOptionResp } = {}
data[type] = item; if (type === 'categoryId') {
if (result.categoryId) {
setResult({ ...result, ...data }); data[type] = [...result.categoryId, item]
}; const map = new Map()
//去重
data[type] = (data[type] as InfoList[]).filter(
(v) => !map.has(v.id) && map.set(v.id, 1)
)
} else {
data[type] = [item]
}
} else {
data[type] = item
}
setResult({ ...result, ...data })
}
useEffect(() => { useEffect(() => {
props.onChange(result, { props.onChange(result, {
brandId: result.brand?.id, // brandId: result.brand?.id,
districtId: result.region?.id, // districtId: result.region?.id,
modelId: result.model?.id, // modelId: result.model?.id,
partsId: result.part?.id, // partsId: result.part?.id,
productCategoryId: result.category?.id, // productCategoryId: result.category?.id,
qualityId: result.quality?.id, // qualityId: result.quality?.id,
industryId: result.industryId?.id, // industryId: result.industryId?.id,
appTypeId: result.appTypeId?.id, // appTypeId: result.appTypeId?.id,
categoryId: result.categoryId?.id, categoryId: result.categoryId,
}); provinceId: result.provinceId?.id,
}, [result]); })
}, [result])
useEffect(() => { const clearRouter = () => {
let queryVal = JSON.parse(JSON.stringify(router.query));
if (Object.keys(router.query).length) { if (Object.keys(router.query).length) {
for (const key in queryVal) { router.query = {}
if (idArr.includes(key)) { router.replace(router.pathname)
onChange(
{ id: queryVal[key], name: nameArr[key].typeName + queryVal.name },
nameArr[key].typeObj
);
}
}
} }
}, [router]); }
const onDel = (key: string | number) => {
clearRouter()
console.log(key)
const clearRouter = () => { if (Object.prototype.toString.call(key) === '[object String]') {
if (Object.keys(router.query).length) { //@ts-ignore
router.query = {}; delete result[key]
router.replace(router.pathname); } else {
if (result.categoryId?.length! === 1) {
result.categoryId = undefined
} else if (result.categoryId?.length! >= 2) {
result.categoryId?.map((item, index) => {
if (item.id === key) {
result.categoryId?.splice(index, 1)
}
})
}
} }
};
const onDel = (key: string) => {
clearRouter();
//@ts-ignore
delete result[key];
setResult({ setResult({
...result, ...result,
}); })
}; }
const routerList = [
'/jobServices',
'/equipmentLeasing',
'/flyingHandService',
'/mall',
]
const [typeInfo, setTypeInfo] = useState<Array<TypesResp> | null>()
useEffect(() => {
if (routerList.indexOf(router.pathname) > -1) {
;(async () => {
const res = await api.infoByType({
type: routerList.indexOf(router.pathname) + 1,
})
setTypeInfo(res.result)
//首页跳转自定筛选选中
let queryVal = JSON.parse(JSON.stringify(router.query))
if (Object.keys(router.query).length) {
//获取类型的id
const idOfType = res.result
?.map((item) => item.categoriesInfoListDTO)
.flat()
.filter(
(item) => item && item.id === Number(queryVal['categoryId'])
)[0]?.directoryId
//获取类型的名称然后拼接
const TypeName = res.result?.filter(
(item) => item.directoryId === idOfType
)[0]?.name
onChange(
{
id: Number(queryVal['categoryId']),
name: `${
TypeName ? TypeName + ':' + queryVal.name : queryVal.name
}`,
},
'categoryId'
)
}
})()
}
}, [router])
return ( return (
<> <>
{props.types.includes("地域") && ( {props.types.includes('地域') && (
<div <div
className={styles.filterWrap} className={styles.filterWrap}
style={{ style={{
...@@ -187,68 +252,79 @@ const Filter = (props: Props, ref: Ref<any>) => { ...@@ -187,68 +252,79 @@ const Filter = (props: Props, ref: Ref<any>) => {
}} }}
> >
<RegionItem <RegionItem
onChange={(item: FilterOptionResp) => onChange(item, "region")} onChange={(item: FilterOptionResp) => onChange(item, 'provinceId')}
></RegionItem> ></RegionItem>
</div> </div>
)} )}
<div className={styles.filterWrap}> <div className={styles.filterWrap}>
{props.types.includes("品牌") && ( {/* {props.types.includes('品牌') && (
<BrandItem <BrandItem
onChange={(item: FilterOptionResp) => onChange(item, "brand")} onChange={(item: FilterOptionResp) => onChange(item, 'brand')}
></BrandItem> ></BrandItem>
)} )}
{props.types.includes("设备品牌") && ( {props.types.includes('设备品牌') && (
<DeviceBrand <DeviceBrand
onChange={(item: FilterOptionResp) => onChange(item, "brand")} onChange={(item: FilterOptionResp) => onChange(item, 'brand')}
></DeviceBrand> ></DeviceBrand>
)} )}
{props.types.includes("类目") && ( {props.types.includes('类目') && (
<CategoryItem <CategoryItem
onChange={(item: FilterOptionResp) => onChange(item, "category")} onChange={(item: FilterOptionResp) => onChange(item, 'category')}
></CategoryItem> ></CategoryItem>
)} )}
{props.types.includes("设备类目") && ( {props.types.includes('设备类目') && (
<Category <Category
onChange={(item: FilterOptionResp) => onChange(item, "categoryId")} onChange={(item: FilterOptionResp) => onChange(item, 'categoryId')}
></Category> ></Category>
)} )}
{props.types.includes("部件") && ( {props.types.includes('部件') && (
<PartItem <PartItem
onChange={(item: FilterOptionResp) => onChange(item, "part")} onChange={(item: FilterOptionResp) => onChange(item, 'part')}
></PartItem> ></PartItem>
)} )}
{props.types.includes("型号") && ( {props.types.includes('型号') && (
<ModelItem <ModelItem
onChange={(item: FilterOptionResp) => onChange(item, "model")} onChange={(item: FilterOptionResp) => onChange(item, 'model')}
></ModelItem> ></ModelItem>
)} )}
{props.types.includes("设备型号") && ( {props.types.includes('设备型号') && (
<DeviceModel <DeviceModel
onChange={(item: FilterOptionResp) => onChange(item, "model")} onChange={(item: FilterOptionResp) => onChange(item, 'model')}
></DeviceModel> ></DeviceModel>
)} )}
{props.types.includes("成色") && ( {props.types.includes('成色') && (
<QualityItem <QualityItem
onChange={(item: FilterOptionResp) => onChange(item, "quality")} onChange={(item: FilterOptionResp) => onChange(item, 'quality')}
></QualityItem> ></QualityItem>
)} )}
{props.types.includes("行业") && ( {props.types.includes('行业') && (
<Industry <Industry
onChange={(item: FilterOptionResp) => onChange(item, "industryId")} onChange={(item: FilterOptionResp) => onChange(item, 'industryId')}
></Industry> ></Industry>
)} )}
{props.types.includes("应用") && ( {props.types.includes('应用') && (
<AppType <AppType
onChange={(item: FilterOptionResp) => onChange(item, "appTypeId")} onChange={(item: FilterOptionResp) => onChange(item, 'appTypeId')}
></AppType> ></AppType>
)} )} */}
{typeInfo?.length &&
typeInfo?.map((item) => (
<TypeInfo
key={item.directoryId}
typeName={item.name}
dataValue={item.categoriesInfoListDTO}
onChange={(item: FilterOptionResp) =>
onChange(item, 'categoryId')
}
></TypeInfo>
))}
{props.showResultItem && ( {props.showResultItem && (
<ResultItem data={result} onDel={onDel}></ResultItem> <ResultItem data={result} onDel={onDel}></ResultItem>
)} )}
</div> </div>
</> </>
); )
}; }
export default forwardRef(Filter); export default forwardRef(Filter)
...@@ -41,7 +41,9 @@ const footerStyle: React.CSSProperties = { ...@@ -41,7 +41,9 @@ const footerStyle: React.CSSProperties = {
type Props = { type Props = {
children?: React.ReactNode; children?: React.ReactNode;
layoutStyle?: React.CSSProperties; layoutStyle?: React.CSSProperties;
contentStyle?: React.CSSProperties;
hideFooter?: boolean; hideFooter?: boolean;
headerStyle?: React.CSSProperties
}; };
export default function LayoutView(props: Props) { export default function LayoutView(props: Props) {
...@@ -55,11 +57,19 @@ export default function LayoutView(props: Props) { ...@@ -55,11 +57,19 @@ export default function LayoutView(props: Props) {
)} )}
> >
<Header style={headerStyle}> <Header style={headerStyle}>
<NavHeader /> <NavHeader style={props.headerStyle} />
</Header> </Header>
<Content className={styles.content}>{props.children}</Content> <Content className={styles.content} style={props.contentStyle}>
{props.children}
</Content>
{!props.hideFooter && ( {!props.hideFooter && (
<Footer style={ includesPage.includes(router.pathname) ? {...footerStyle,...homeStyle} : footerStyle}> <Footer
style={
includesPage.includes(router.pathname)
? { ...footerStyle, ...homeStyle }
: footerStyle
}
>
<FooterView></FooterView> <FooterView></FooterView>
</Footer> </Footer>
)} )}
......
...@@ -35,6 +35,10 @@ const UserProvider = ({ children }: Props) => { ...@@ -35,6 +35,10 @@ const UserProvider = ({ children }: Props) => {
setUserInfo( setUserInfo(
JSON.parse(window.localStorage.getItem("userInfo") || "") || undefined JSON.parse(window.localStorage.getItem("userInfo") || "") || undefined
); );
window.setUserInfo = setUserInfo;
window.setNeedLogin = setNeedLogin;
window.logout = logout;
} catch (e) {} } catch (e) {}
}, []); }, []);
......
/** @type {import('next').NextConfig} */ /** @type {import('next').NextConfig} */
let distDir = ".dev"; //默认输出目录 let distDir = '.dev' //默认输出目录
if (process.env.NODE_ENV === "production") { if (process.env.NODE_ENV === 'production') {
//生产环境用另一个目录构建,防止与dev冲突 //生产环境用另一个目录构建,防止与dev冲突
distDir = ".next"; distDir = '.next'
} }
const nextConfig = { const nextConfig = {
distDir, distDir,
reactStrictMode: true, reactStrictMode: true,
transpilePackages: ["antd"], transpilePackages: ['antd'],
output: "standalone", output: 'standalone',
compiler: { compiler: {
styledComponents: true, styledComponents: true,
}, },
redirects() { redirects() {
return [ return [
{ {
source: "/", source: '/',
destination: "/home", destination: '/home',
permanent: true, permanent: true,
}, },
]; ]
}, },
async rewrites() { async rewrites() {
return [ return [
{ {
source: "/local/:path*", source: '/local/:path*',
//destination: "https://iuav.mmcuav.cn/:path*", //destination: "https://iuav.mmcuav.cn/:path*",
destination: "https://test.iuav.mmcuav.cn/:path*", destination: 'https://test.iuav.shop/:path*',
}, },
]; ]
}, },
images: { images: {
remotePatterns: [ remotePatterns: [
{ {
protocol: "http", protocol: 'http',
hostname: "**", hostname: '**',
}, },
{ {
protocol: "https", protocol: 'https',
hostname: "**", hostname: '**',
}, },
], ],
}, },
pageExtensions: ["page.tsx", "page.ts", "page.jsx", "page.js"], pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
}; }
module.exports = nextConfig; module.exports = nextConfig
...@@ -23,6 +23,7 @@ export default function App({ Component, pageProps }: AppProps) { ...@@ -23,6 +23,7 @@ export default function App({ Component, pageProps }: AppProps) {
return withTheme( return withTheme(
<> <>
<Head> <Head>
<title>云享飞</title>
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no"
......
...@@ -12,18 +12,22 @@ import { ...@@ -12,18 +12,22 @@ import {
} from "antd"; } from "antd";
import type { UploadChangeParam } from "antd/es/upload"; import type { UploadChangeParam } from "antd/es/upload";
import type { RcFile, UploadFile, UploadProps } from "antd/es/upload/interface"; import type { RcFile, UploadFile, UploadProps } from "antd/es/upload/interface";
import { useContext, useState } from "react"; import { useContext, useEffect, useState } from "react";
import Layout from "~/components/layout"; import Layout from "~/components/layout";
import api, { } from "./api"; import api from "./api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import gApi from "~/api"; import gApi from "~/api";
import Router from "next/router"; import Router from "next/router";
import { UserContext } from "~/lib/userProvider"; import { UserContext } from "~/lib/userProvider";
const beforeUpload = (file: RcFile) => { const beforeUpload = (file: RcFile) => {
const isJpgOrPng = file.type === "image/jpeg" || file.type === "image/png"; const isJpgOrPng =
file.type === "image/jpeg" ||
file.type === "image/png" ||
file.type === "image/bmp" ||
file.type === "image/gif"
if (!isJpgOrPng) { if (!isJpgOrPng) {
message.error("You can only upload JPG/PNG file!"); message.error("请上传10M以内的JPG、JPEG、BMP、GIF、PNG格式图片");
} }
//限制上传10M //限制上传10M
const isLt2M = file.size / 1024 / 1024 < 10; const isLt2M = file.size / 1024 / 1024 < 10;
...@@ -55,6 +59,11 @@ export default function Certification() { ...@@ -55,6 +59,11 @@ export default function Certification() {
Array<EnterpriseOption> Array<EnterpriseOption>
>([]); >([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
const [token, setToken] = useState("");
useEffect(() => {
setToken(window.localStorage.getItem("token") || "");
}, []);
//上传change事件 //上传change事件
const handleChange: UploadProps["onChange"] = ( const handleChange: UploadProps["onChange"] = (
...@@ -91,7 +100,11 @@ export default function Certification() { ...@@ -91,7 +100,11 @@ export default function Certification() {
}); });
} }
setTimeout(() => { setTimeout(() => {
Router.push("/"); if (Router.query.type == "back") {
Router.back();
} else {
Router.push("/");
}
}, 1000); }, 1000);
} }
}); });
...@@ -209,6 +222,7 @@ export default function Certification() { ...@@ -209,6 +222,7 @@ export default function Certification() {
beforeUpload={beforeUpload} beforeUpload={beforeUpload}
onChange={handleChange} onChange={handleChange}
maxCount={1} maxCount={1}
headers={{ token: token }}
> >
{imageUrl ? ( {imageUrl ? (
<Image <Image
......
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
export interface ListPageDeviceInfoParams { export interface ListPageDeviceInfoParams {
"brandId"?: number, brandId?: number
"districtId"?: number, districtId?: number
"modelId"?: number, modelId?: number
"pageNo": number, pageNo: number
"pageSize": number, pageSize: number
"partsId"?: number, partsId?: number
"productCategoryId"?: number, productCategoryId?: number
"qualityId"?: number qualityId?: number
} }
export interface Device { export interface Device {
id: number, id: number
wareNo: string, goodsName: string
wareTitle: string, images: string
wareTypeId: number, price: number | null
wareStatus: number,
minDeposit: number,
minRent: number,
totalStock: number,
totalSale: number,
propInfoId: null,
createTime: string,
wareImgs: [
{
id: number,
wareInfoId: number,
imgUrl: string,
imgType: number
}
],
tags: string[]
} }
export interface Advertisement { export interface Advertisement {
id:number, id: number
imageUrl:string imageUrl: string
} }
export interface ListPageDeviceInfoResp { export interface ListPageDeviceInfoResp {
"pageNo": 1, pageNo: 1
"pageSize": 10, pageSize: 10
"list": Array<Device>, list: Array<Device>
"totalCount": 0, totalCount: 0
"totalPage": 0 totalPage: 0
} }
export default { export default {
//web-设备租赁-分页 //web-设备租赁-分页
listPageDeviceInfo: (params: ListPageDeviceInfoParams,options = {}): Promise<Response<ListPageDeviceInfoResp>> => { listPageDeviceInfo: (
return request('/pms/webDevice/deviceList', 'post', params, options) params: ListPageDeviceInfoParams,
options = {}
): Promise<Response<ListPageDeviceInfoResp>> => {
return request('/pms/product/mall/deviceList', 'post', params, options)
}, },
//web-设备租赁-广告 //web-设备租赁-广告
listAdvertisementInfo: (): Promise<Response<Array<Advertisement>>> => { listAdvertisementInfo: (): Promise<Response<Array<Advertisement>>> => {
return request('/pms/webDevice/ad', 'get') return request('/pms/webDevice/ad', 'get')
} },
} }
\ No newline at end of file
import React, { useEffect , useState , useContext } from 'react' import React, { useEffect, useState, useContext } from 'react'
import {useRouter} from 'next/router'; import { useRouter } from 'next/router'
import Layout from "~/components/layout"; import Layout from '~/components/layout'
import {Box} from './styled'; import { Box } from './styled'
import ImagePreview from './components/picture-preview'; import ImagePreview from './components/picture-preview'
import { Button , Image as AImage , Divider , Select,Modal ,Tag,Space,Form,message} from 'antd'; import OrderForGoods from './components/orderForGoods'
import Image from 'next/image'; import moment from 'moment'
import errImg from "~/assets/errImg"; import {
import api,{GetWebDeviceDetailResult,GetWebDeviceWareSkuById} from './api'; Button,
import { UserContext } from "~/lib/userProvider"; Image as AImage,
Divider,
Select,
Modal,
Tag,
Space,
Form,
message,
InputNumber,
DatePicker,
} from 'antd'
import Image from 'next/image'
import errImg from '~/assets/errImg'
import api, {
GetWebDeviceDetailResult,
GetWebDeviceWareSkuById,
GetLeaseGoodsResult,
} from './api'
import { UserContext } from '~/lib/userProvider'
import flowPat from './assets/flow-path.png' import flowPat from './assets/flow-path.png'
import { RangePickerProps } from 'antd/es/date-picker'
const { RangePicker } = DatePicker
const { CheckableTag } = Tag const { CheckableTag } = Tag
export interface ShopDetail {
dateDetail: Array<Date>
num: number
id: number
}
export default function EquipmentLeasingDetail() { export default function EquipmentLeasingDetail() {
const router = useRouter(); const router = useRouter()
const { userInfo, setNeedLogin } = useContext(UserContext); const { userInfo, setNeedLogin } = useContext(UserContext)
const [id, setId] = useState<number | null>(null); const [id, setId] = useState<number | null>(null)
const [detail,setDetail] = useState<GetWebDeviceDetailResult | null>()
const [wareSkuList,setWareSkuList] = useState<GetWebDeviceWareSkuById[] | undefined>()
useEffect(()=>{ const [detail, setDetail] = useState<GetWebDeviceDetailResult | null>()
const [wareSkuList, setWareSkuList] = useState<
GetWebDeviceWareSkuById[] | undefined
>()
useEffect(() => {
setId(Number(router.query.id)) setId(Number(router.query.id))
},[router]) }, [router])
useEffect(()=>{ useEffect(() => {
if (id) { if (id) {
api api
.listDetailDeviceInfo({ .listDetailDeviceInfo({
id:id goodsId: id,
type: 1,
}) })
.then((res) => { .then((res) => {
setDetail(res.result || null); setDetail(res.result || null)
}); const wareList = res.result?.goodsSpec.map(
api (item) => item.productSpecList
.listWareSkuById({ )
id:id if (wareList) {
const List: GetWebDeviceWareSkuById[] = wareList.flat()
setWareSkuList(List)
}
}) })
.then((res) => {
res.result?.map(item=>{
return item
})
setWareSkuList(res.result || undefined);
});
} }
},[id]) }, [id])
//租赁弹框 //租赁弹框
const [isModalOpen, setIsModalOpen] = useState(false); const [visible, setVisible] = useState(false)
const [loading, setLoading] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false)
const [form] = Form.useForm(); const [isModalDateOpen, setIsModalDateOpen] = useState(false)
const tagsData = ['3-7天', '8-15天', '16-30天', '30天以上']; const [loading, setLoading] = useState(false)
const [selectedTags, setSelectedTags] = useState<number>(); const [isorderForGoods, setIsorderForGoods] = useState(false)
const [selectedTagsData, setSelectedTagsData] = useState<string>(); const [form] = Form.useForm()
const [formDate] = Form.useForm()
const tagsData = [
{ id: 0, label: '1-7天', disable: false },
{ id: 1, label: '8-15天', disable: false },
{ id: 2, label: '16-30天', disable: false },
{ id: 3, label: '30天以上', disable: false },
]
const [discount, setDiscount] = useState<GetLeaseGoodsResult | null>()
const [selectedTags, setSelectedTags] = useState<number>()
const [selectedTagsData, setSelectedTagsData] = useState<number>()
const [shopDetail, setShopDetail] = useState<ShopDetail>()
const showModal = () => { const showModal = () => {
if (userInfo) { if (userInfo) {
setIsModalOpen(true); setIsModalOpen(true)
if (wareSkuList?.length) { if (wareSkuList?.length) {
setSelectedTags(wareSkuList[0].id); setSelectedTags(wareSkuList[0].id)
form.setFieldValue("id",wareSkuList[0].id) form.setFieldValue('id', wareSkuList[0].id)
setSelectedTagsData("3-7天") setSelectedTagsData(0)
form.setFieldValue("date","3-7天") form.setFieldValue('date', 0)
getPrice(0)
} }
}else{ } else {
setNeedLogin(true) setNeedLogin(true)
} }
}; }
const handleOk = () => { const handleOk = () => {
setLoading(true); setLoading(true)
form form
.validateFields() .validateFields()
.then(async (values) => { .then(async (values) => {
form.resetFields() setLoading(false)
message.success("租赁成功") setIsModalOpen(false)
setLoading(false); setIsModalDateOpen(true)
setIsModalOpen(false); })
// try{ .catch((err) => {
// const res = await api.listWareSkuUpdate(values) message
// if (res.code === "200") { .warning({
// setLoading(false); content: err.errorFields[0].errors[0],
// setIsModalOpen(false); })
// form.resetFields() .then()
// message.success('租赁成功') setLoading(false)
// }else{ })
// setLoading(false); }
// message.error(res.message)
// } const [days, setDays] = useState<number>()
// }catch(e:any){ const handleOkDate = async () => {
// message.error(e.message) setLoading(true)
// } try {
}).catch((err) => { const result = await Promise.all([
message form.validateFields(),
.warning({ formDate.validateFields(),
content: err.errorFields[0].errors[0], ])
}) if (result) {
.then(); setLoading(false)
setLoading(false); setIsModalOpen(false)
}); setIsModalDateOpen(false)
setIsorderForGoods(true)
}; setShopDetail({ ...result[0], ...result[1] })
}
} catch (error) {
setLoading(false)
}
}
const handleCancel = () => { const handleCancel = () => {
setIsModalOpen(false); setIsModalOpen(false)
}; setIsModalDateOpen(false)
form.resetFields()
const handleChange = (tag: number, checked: boolean) => { formDate.resetFields()
if (checked) { }
const nextWareSkuList = checked
? tag
: wareSkuList?.filter((t) => t.id !== tag)[0].id;
console.log('You are interested in: ', nextWareSkuList);
setSelectedTags(nextWareSkuList);
form.setFieldValue("id",tag)
}
};
const handleChangeDate = (tag: string, checked: boolean) => { const handleChange = (tag: number, checked: boolean) => {
if (checked) { if (checked) {
const nextWareSkuList = checked
? tag
: wareSkuList?.filter((t) => t.id !== tag)[0].id
setSelectedTags(nextWareSkuList)
form.setFieldValue('id', tag)
}
}
const handleChangeDate = (
tag: number,
checked: boolean,
disable: boolean
) => {
if (checked && !disable) {
const nextSelectedTags = checked const nextSelectedTags = checked
? tag ? tag
: tagsData.filter((t) => t !== tag)[0]; : tagsData.filter((t) => t.id !== tag)[0].id
console.log('You are interested in: ', nextSelectedTags); setSelectedTagsData(nextSelectedTags)
setSelectedTagsData(nextSelectedTags); form.setFieldValue('date', tag)
form.setFieldValue("date",tag) getPrice(tag)
}
}
const getPrice = (tag: number) => {
const Id = wareSkuList?.filter(
(item) => item.id === form.getFieldValue('id')
)[0].productSpec
if (Id) {
api
.GoodsPriceDetail({ leaseTerm: tag, productSpecId: Id })
.then((res) => {
setDiscount(res.result)
})
}
}
const onChangeNum = (value: number | string | null) => {
console.log('changed', value)
}
const goBack = () => {
setIsModalDateOpen(false)
setIsModalOpen(true)
}
const onchanges = (values: any) => {
if (values) {
const day = new Date(values[1]).getTime() - new Date(values[0]).getTime()
const totalDays = Math.floor(day / (1000 * 3600 * 24))
setDays(totalDays)
} else {
setDays(undefined)
} }
}; }
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
return current && current < moment().endOf('day')
}
return ( return (
<Layout> <Layout>
<Box> {!isorderForGoods ? (
<div className='item'> <Box>
<ImagePreview imgList={detail?.wareImgs!}/> <div className="item">
<div className='item-right'> <ImagePreview imgList={detail?.images!} />
<div className='title'>{detail?.wareTitle}</div> <div className="item-right">
{ <div className="title">{detail?.goodsName}</div>
detail?.tags?.length ? {detail?.otherService?.length ? (
(<div className='function'> <div className="function">
{detail?.tags?.map(item=>(<div key={item} className='function-item'>{item}</div>))} {detail?.otherService?.map((item) => (
</div>) : (<div className='function not'></div>) <div key={item.id} className="function-item">
} {item.serviceName}
<div className='menoy'> </div>
<span className='menoy-left'>{`¥${detail?.minRent}`}</span> ))}
<span className='menoy-right'>/天起</span> </div>
</div> ) : (
<div className='classification'> <div className="function not"></div>
<div className='top'> )}
<div className='left'> {userInfo?.cooperationTagId ? (
<span className='label'>选择</span> <div className="menoy">
<span className='value'>商品分类</span> <span className="menoy-left">{`¥${detail?.price! | 0}`}</span>
<span className="menoy-right">/天起</span>
</div>
) : (
<div className="menoy">暂无报价</div>
)}
<div className="classification">
<div className="top">
<div className="left">
<span className="label">选择</span>
<span className="value">商品分类</span>
</div>
<div className="right">
<Select
className="selectItem"
defaultActiveFirstOption
defaultValue={wareSkuList}
style={{ width: 120 }}
bordered={false}
options={wareSkuList}
fieldNames={{ label: 'specName', value: 'id' }}
placeholder="选择商品"
/>
</div>
</div> </div>
<div className='right'> <div className="bottom">
<Select <span className="label">发货</span>
className="selectItem" <span className="value">顺丰到付</span>
defaultActiveFirstOption
defaultValue={wareSkuList}
style={{ width: 120 }}
bordered={false}
options={wareSkuList}
fieldNames={{label:"skuTitle",value:"id"}}
placeholder="选择商品"
/>
</div> </div>
</div> </div>
<div className='bottom'> <div className="botton-btn">
<span className='label'>发货</span> {/* <Button className='btn-left' size='small' type="primary">成为渠道商</Button> */}
<span className='value'>顺丰到付</span> <Button
className="btn-right"
size="small"
type="primary"
onClick={showModal}
>
立即租赁
</Button>
</div> </div>
</div> </div>
<div className='botton-btn'>
{/* <Button className='btn-left' size='small' type="primary">成为渠道商</Button> */}
<Button className='btn-right' size='small' type="primary" onClick={showModal}>立即租赁</Button>
</div>
</div> </div>
</div> <div className="flow-path">
<div className='flow-path'> <Image className="image" fill src={flowPat.src} alt="" />
<Image className='image' fill src={flowPat.src} alt="" />
</div>
<div className='prompt'>
更多租金规则请前往【云享飞】微信小程序查
</div>
<Divider className='divider'>商品详情</Divider>
{
detail?.wareDetailContent ? <div style={{ textAlign: "center" }} dangerouslySetInnerHTML={{ __html: detail?.wareDetailContent}}>
</div> : <div style={{ textAlign: "center" }} ></div>
}
{/* 立即租赁 */}
<Modal
wrapClassName='application'
open={isModalOpen}
onOk={handleOk}
onCancel={handleCancel}
getContainer={false}
footer={[
<Button
style={{ width: "100%" ,height: 44 }}
key="submit"
type="primary"
loading={loading}
onClick={handleOk}
>
立即租赁
</Button>,
]}
>
<div className='title'>
<div className="left"></div>
<div className="right">
<div className="top">
<span className='tag'>¥</span>
<span className='money'>{detail?.minRent}</span>
<span className='unit'>/天</span>
</div>
<div className="bottom">渠道免押金</div>
</div> </div>
</div> <div className="prompt">更多租金规则请前往【云享飞】微信小程序查</div>
<Form <Divider className="divider">商品详情</Divider>
form={form} {detail?.goodsDetail.content ? (
layout="vertical" <div
name="application" style={{ textAlign: 'center' }}
initialValues={{ modifier: 'public' }} dangerouslySetInnerHTML={{ __html: detail?.goodsDetail.content }}
> ></div>
<Form.Item style={{flex:1,marginRight:16}} name="id" label="选择商品"> ) : null}
<Space size={[0, 8]} wrap> {/* 立即租赁 */}
{wareSkuList?.map((tag) => ( <Modal
<CheckableTag wrapClassName="application"
style={{height:28,lineHeight:"28px"}} open={isModalOpen}
key={tag.id} onOk={handleOk}
checked={wareSkuList?.some(item=>tag.id === selectedTags)} onCancel={handleCancel}
onChange={(checked) => handleChange(tag.id, checked)} getContainer={false}
> maskClosable={false}
{tag.skuTitle} footer={[
</CheckableTag> <Button
))} style={{ width: '100%', height: 44 }}
</Space> key="submit"
</Form.Item> type="primary"
<Form.Item style={{flex:1,marginRight:16}} name="date" label="租期天数(拿到和归还当天不算入租期)"> loading={loading}
<Space size={[0, 8]} wrap> onClick={handleOk}
{tagsData.map((tag) => ( >
<CheckableTag 立即租赁
key={tag} </Button>,
checked={tag === selectedTagsData} ]}
onChange={(checked) => handleChangeDate(tag, checked)}
> >
{tag} <div className="title">
</CheckableTag> <div className="left">
))} <AImage
</Space> preview={{ visible: false }}
</Form.Item> src={detail?.images[0].imgUrl}
</Form> onClick={() => setVisible(true)}
</Modal> />
</Box> <div style={{ display: 'none' }}>
<AImage.PreviewGroup
preview={{
visible,
onVisibleChange: (vis) => setVisible(vis),
}}
>
{detail?.images.map((item) => (
<AImage key={item.id} src={item.imgUrl} />
))}
</AImage.PreviewGroup>
</div>
</div>
<div className="right">
<div className="top">
<span className="tag">¥</span>
<span className="money">
{discount?.specPrice[0]?.price || 0}
</span>
<span className="unit">/天</span>
</div>
<div className="bottom">渠道免押金</div>
</div>
</div>
<Form
form={form}
layout="vertical"
name="application"
initialValues={{ num: 1 }}
className="form-data"
>
<Form.Item
style={{ flex: 1, marginRight: 16 }}
name="id"
label="选择商品"
>
<Space size={[0, 8]} wrap>
{wareSkuList?.map((tag) => (
<CheckableTag
style={{ height: 28, lineHeight: '28px' }}
key={tag.id}
checked={wareSkuList?.some(
(item) => tag.id === selectedTags
)}
onChange={(checked) => handleChange(tag.id, checked)}
>
{tag.specName}
</CheckableTag>
))}
</Space>
</Form.Item>
<Form.Item
style={{ flex: 1, marginRight: 16 }}
name="date"
label="租期天数(拿到和归还当天不算入租期)"
>
<Space size={[0, 8]} wrap>
{tagsData.map((tag) => (
<CheckableTag
key={tag.id}
checked={tag.id === selectedTagsData}
onChange={(checked) =>
handleChangeDate(tag.id, checked, tag.disable)
}
className={`tagsData ${
tag.disable ? 'disable tagsDisable' : ''
}`}
>
{tag.label}
</CheckableTag>
))}
</Space>
</Form.Item>
<div className="num-box">
<div className="num-left">
<div className="label">租赁数量</div>
</div>
<div className="num-right">
<Form.Item style={{ flex: 1, marginRight: 16 }} name="num">
<InputNumber min={1} max={100} onChange={onChangeNum} />
</Form.Item>
</div>
</div>
</Form>
</Modal>
<Modal
wrapClassName="applicationDate"
open={isModalDateOpen}
onOk={handleOkDate}
onCancel={handleCancel}
getContainer={false}
maskClosable={false}
width={420}
footer={[
<Button
style={{ width: '100%', height: 44 }}
key="submit"
type="primary"
loading={loading}
onClick={handleOkDate}
>
确认租期{days ? `${days}天` : null}
</Button>,
]}
>
<div className="title">
<div className="left" onClick={goBack}>
{'<'}
</div>
<div className="right">选择租期</div>
</div>
<Form
form={formDate}
layout="vertical"
name="applicationDate"
initialValues={{ modifier: 'public' }}
className="form-data"
>
<Form.Item
style={{ flex: 1, marginRight: 16 }}
name="dateDetail"
rules={[{ required: true, message: '请选择日期' }]}
>
<RangePicker
style={{ width: 376, marginTop: 10 }}
disabledDate={disabledDate}
onChange={onchanges}
/>
</Form.Item>
</Form>
<div className="bottom-item">
<div className="label">租金合计</div>
<div className="price">
<div className="left">
¥
{discount?.specPrice[0]?.price! *
days! *
form.getFieldValue('num') || 0}
</div>
{/* <div className="right">(日均175)</div> */}
</div>
</div>
</Modal>
</Box>
) : (
<OrderForGoods
setIsorderForGoods={setIsorderForGoods}
shopDetail={shopDetail}
days={days}
detailData={detail}
discount={discount}
wareSkuList={wareSkuList?.filter(
(item) => item.id === form.getFieldValue('id')
)}
/>
)}
</Layout> </Layout>
) )
} }
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
export interface GetWebDeviceDetailParams { export interface GetWebDeviceDetailParams {
id:number goodsId: number
type: 1
}
export interface GetLeaseGoodsParams {
leaseTerm: number //租赁时限:(输入0:1-7天、输入1:8-15天、输入2:16-30天、输入3:30天以上)
productSpecId: number
} }
export interface WareImgsType { export interface WareImgsType {
id: number, id: number
wareInfoId: number | null, imgUrl: string
imgUrl: string,
imgType: number imgType: number
} }
export interface PriceType {
id: number
cooperationTag: number
price: number
productSpecId: number
leaseTerm: number
}
export interface GetLeaseGoodsResult {
productSpecId: number
type: number | null
leaseTerm: number
specPrice: PriceType[]
}
export interface GetWebDeviceDetailResult { export interface GetWebDeviceDetailResult {
id: number, id: number
wareNo: string, images: {
wareTitle: string, id: number
wareTypeId: number, imgUrl: string
wareStatus: number, imgType: number
payStatus: number, }[]
minDeposit: number, goodsVideo: string
maxDeposit: number, goodsVideoId: number
minRent: number, goodsName: string
maxRent: number, goodsDetail: {
totalStock: number, id: number
totalSale: number, goodsDesc: string
skuNum: number, content: string | null
tags: [ remark: string | null
string, }
string directoryId: number
], categoryByOne: number
wareImgs: Array<WareImgsType>, categoryByTwo: null
warePropDTO: number | null, tag: null
wareDetailContent: string | TrustedHTML shelfStatus: number
goodsSpec: {
productSpecList: GetWebDeviceWareSkuById[]
}[]
otherService?: {
id: number
saleServiceId: string
serviceName: string
}[]
price: number | null
goodsNo: string
} }
export interface PriceList { export interface PriceList {
id: number, id: number
wareInfoId: number, wareInfoId: number
skuInfoId: number, skuInfoId: number
rentPrice: number, rentPrice: number
minDay: number, minDay: number
maxDay: number, maxDay: number
createTime: null createTime: null
} }
export interface GetWebDeviceWareSkuById { export interface GetWebDeviceWareSkuById {
id: number, id: number
wareInfoId: number, productSpec: number
skuTitle: string, productSkuId: number
rentPrice: number | null, specName: string
rentDeposit: number, specImage: string
stockNum: number, partNo: string
saleNum: number, versionDesc: string
createTime: string, createTime: string | null
updateTime: null, productSpecCPQVO: string | null
skuPriceDTOList: Array<PriceList>,
} }
export interface WebDeviceUpdateParams { export interface WebDeviceUpdateParams {
id?:number, id?: number
inventoryId?:number, inventoryId?: number
inventoryUsage?:string, inventoryUsage?: string
startDay?:string startDay?: string
endDay?:string, endDay?: string
} }
export default { export default {
//web-设备租赁-详情 //web-设备租赁-详情
listDetailDeviceInfo: (params: GetWebDeviceDetailParams): Promise<Response<GetWebDeviceDetailResult>> => { listDetailDeviceInfo: (
return request('/pms/webDevice/detail', 'get', params) params: GetWebDeviceDetailParams
}, ): Promise<Response<GetWebDeviceDetailResult>> => {
//web-设备租赁-商品 return request('/pms/product/mall/getLeaseGoodsDetail', 'get', params)
listWareSkuById: (params: GetWebDeviceDetailParams): Promise<Response<GetWebDeviceWareSkuById[]>> => {
return request('/pms/appDevice/listWareSkuById', 'get', params)
}, },
//web-设备租赁-立即租赁 //web-设备租赁-立即租赁
listWareSkuUpdate: (params: WebDeviceUpdateParams): Promise<Response<number>> => { listWareSkuUpdate: (
params: WebDeviceUpdateParams
): Promise<Response<number>> => {
return request('/pms/appDevice/update', 'post', params) return request('/pms/appDevice/update', 'post', params)
} },
} //web-设备租赁-详情-获取设备商品规格价格详情
\ No newline at end of file GoodsPriceDetail: (
params: GetLeaseGoodsParams
): Promise<Response<GetLeaseGoodsResult>> => {
return request('/pms/product/mall/getLeaseGoodsPriceDetail', 'get', params)
},
}
import request, { Response } from '~/api/request'
export interface GetWebDeviceDetailParams {
actualPay: number
deposit: number
endDate: string
orderReceipt: {
detailAddress: string
receiptMethod: number
region: string
takeName: string
takePhone: number
}
rentPrice: number
returnDate: string
shouldPay: number
specsId: number
startDate: string
wareDescription: string
wareImg: string
wareInfoId: number
wareNo: string
wareNum: number
wareTitle: string
remark?: string
}
export interface WareImgsType {
id: number
imgUrl: string
imgType: number
}
export interface UserAddress {
id: number
takeName: string
takePhone: string
takeRegion: string
takeAddress: string
type: number
}
export interface GetOrderForGoods {
balance: number
nickName: string
orderNo: string
}
export default {
//web-地址管理-查询用户地址列表-条件查询
listUserAddress: (params: {}): Promise<Response<UserAddress[]>> => {
return request('/oms/user-address/selectList', 'POST', params)
},
//web-设备租赁-下单
FeignAddLease: (
params: GetWebDeviceDetailParams
): Promise<Response<GetOrderForGoods>> => {
return request('/oms/RentalOrders/feignAddLease', 'post', params)
},
//web-设备租赁-订单支付
OrderPayment: (params: {
orderNo: string
}): Promise<Response<GetOrderForGoods>> => {
return request(`/payment/repocash/orderPayment`, 'get', params)
},
}
import React, { useContext, useEffect, useState } from 'react'
import { OrderForGoodsBox } from './styled'
import type { FormInstance, RadioChangeEvent } from 'antd'
import { Button, Radio, Space, Input, message, Modal, Image } from 'antd'
import api, { UserAddress, GetOrderForGoods } from './api'
import moment from 'moment'
import { ShopDetail } from '../../[id].page'
import {
GetWebDeviceDetailResult,
GetWebDeviceWareSkuById,
GetLeaseGoodsResult,
} from '../../api'
import { UserContext } from '~/lib/userProvider'
const { TextArea } = Input
interface PropsBox {
setIsorderForGoods: (boolean: boolean) => void
detailData?: GetWebDeviceDetailResult | null
days?: number
shopDetail?: ShopDetail
wareSkuList?: GetWebDeviceWareSkuById[]
discount?: GetLeaseGoodsResult | null
}
export default function OrderForGoods(props: PropsBox) {
const {
setIsorderForGoods,
shopDetail,
days,
detailData,
wareSkuList,
discount,
} = props
const [value, setValue] = useState(1)
const [areaValue, setAreaValue] = useState<string>()
const [list, setList] = useState<Array<UserAddress> | null>()
const [detail, setDetail] = useState<ShopDetail>()
const onChange = (e: RadioChangeEvent) => {
console.log('radio checked', e.target.value)
setValue(e.target.value)
}
const onChangeValue = (index: number) => {
setValue(index)
}
const detailSumbit = () => {
if (detailData && shopDetail && list && wareSkuList) {
const pushList = {
actualPay:
discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0,
deposit: 0,
endDate: moment(new Date(shopDetail.dateDetail[1])).format(
'YYYY-MM-DD'
),
orderReceipt: {
detailAddress: list[value]?.takeAddress,
receiptMethod: 0,
region: list[value].takeRegion,
takeName: list[value].takeName,
takePhone: Number(list[value].takePhone),
},
rentPrice:
discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0,
returnDate: moment(
new Date(shopDetail.dateDetail[1]).getTime() + 864e5
).format('YYYY-MM-DD'),
shouldPay:
discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0,
specsId: wareSkuList[0].productSpec,
startDate: moment(new Date(shopDetail.dateDetail[0]!)).format(
'YYYY-MM-DD'
),
wareDescription: detailData.goodsName,
wareImg: detailData.images[0].imgUrl,
wareInfoId: shopDetail.id,
wareNo: detailData.goodsNo,
wareNum: shopDetail.num,
wareTitle: detailData.goodsName,
remark: areaValue,
}
api.FeignAddLease(pushList).then((res) => {
if (res.code === '200') {
message.success('提交成功')
setPaymentDetail(res.result)
setIsPaymentOpen(true)
} else {
message.error(res.message)
}
})
}
}
useEffect(() => {
api
.listUserAddress({})
.then((res) => {
console.log(res)
setList(res.result)
res.result?.map((item, index) => {
if (item.type === 0) {
setValue(index)
}
})
})
.catch((err) => {
console.log(err)
})
if (shopDetail) {
setDetail(shopDetail)
}
}, [])
//图片预览
const [visible, setVisible] = useState(false)
//付款
const { userInfo } = useContext(UserContext)
const [loading, setLoading] = useState(false)
const [isPaymentOpen, setIsPaymentOpen] = useState(false)
const [paymentDetail, setPaymentDetail] = useState<GetOrderForGoods | null>()
const handleCancel = () => {
setIsPaymentOpen(false)
}
const handleOkPayment = () => {
setLoading(true)
if (paymentDetail?.orderNo) {
api.OrderPayment({ orderNo: paymentDetail?.orderNo }).then((res) => {
if (res.code === '200') {
message.success('付款成功')
setLoading(false)
setIsorderForGoods(false)
handleCancel()
} else {
message.error(res.message)
setLoading(false)
}
})
} else {
message.error('出错了')
setLoading(false)
}
}
//扫码管理地址
const [isAddAddressOpen, setIsAddAddressOpen] = useState(false)
const [addressVisible, setAddressVisible] = useState(false)
return (
<OrderForGoodsBox>
<div className="address">
<div className="top">
<div className="left">确认收货地址</div>
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
管理收货地址
</Button>
</div>
</div>
<div className="bottom">
{list?.length ? (
list?.map((item, index) => (
<div
key={item.id}
className={`item ${value === index ? 'active' : ''}`}
onClick={() => onChangeValue(index)}
>
<div className="left">
<div className="active">
<div className="icon"></div>
<div className="label">寄送至</div>
</div>
<Radio.Group onChange={onChange} value={value}>
<Space direction="vertical">
<Radio value={index}>{item.takeAddress}</Radio>
</Space>
</Radio.Group>
</div>
{value === index ? (
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
修改地址
</Button>
</div>
) : null}
</div>
))
) : (
<div className="item active">
<div className="left">
<div className="active">
<div className="icon"></div>
<div className="label">
暂无地址,请打开手机端【云享飞】微信小程序,【我的】-【个人设置】-【地址管理】添加
</div>
</div>
</div>
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
添加地址
</Button>
</div>
</div>
)}
</div>
</div>
<div className="info">
<div className="title">确认订单信息</div>
<div className="table">
<div className="table-title">
<div className="table-item" style={{ width: 290 }}>
宝贝
</div>
<div className="table-item" style={{ width: 130 }}>
单价
</div>
<div className="table-item" style={{ width: 130 }}>
数量
</div>
<div className="table-item" style={{ width: 300 }}>
租期
</div>
<div className="table-item" style={{ width: 135 }}>
合计
</div>
</div>
<div className="table-body">
<div className="body-item article" style={{ width: 290 }}>
<div className="image">
<Image
className="image-box"
preview={{ visible: false }}
src={(wareSkuList && wareSkuList![0].specImage) || ''}
onClick={() => setVisible(true)}
/>
<div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible,
onVisibleChange: (vis) => setVisible(vis),
}}
>
<Image
src={(wareSkuList && wareSkuList![0].specImage) || ''}
/>
</Image.PreviewGroup>
</div>
</div>
<div className="right">
<div className="top">
{(wareSkuList && wareSkuList![0].specName) || ''}
</div>
<div className="bottom">
{(wareSkuList && wareSkuList![0].versionDesc) || ''}
</div>
</div>
</div>
<div className="body-item" style={{ width: 130 }}>
{discount?.specPrice[0]?.price || 0}
</div>
<div className="body-item" style={{ width: 130 }}>
{shopDetail?.num || 1}
</div>
<div className="body-item lease-term" style={{ width: 300 }}>
{moment(new Date(shopDetail?.dateDetail[0]!)).format(
'YYYY/MM/DD'
)}
<div className="num">{days}</div>
{moment(new Date(shopDetail?.dateDetail[1]!)).format(
'YYYY/MM/DD'
)}
</div>
<div className="body-item total-price" style={{ width: 135 }}>
{discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0}
</div>
</div>
</div>
</div>
<div className="notes">
<div className="left">
<div className="label">备注:</div>
<TextArea
value={areaValue}
onChange={(e) => setAreaValue(e.target.value)}
placeholder="请输入备注"
autoSize={{ minRows: 3, maxRows: 5 }}
style={{ width: 385, height: 72 }}
/>
</div>
<div className="right">
<div className="top">
<div className="font">
<div className="label">运费:</div>
<div className="value">邮寄到付,由客户自己承担</div>
</div>
<div className="price">0.00</div>
</div>
<div className="bottom">
<div className="font">
<div className="label">押金:</div>
<div className="value">渠道商可免押金</div>
</div>
<div className="price">0.00</div>
</div>
</div>
</div>
<div className="detail-box">
<div className="right-box">
<div className="detail">
<div className="top">
<div className="label">实付款</div>
<div className="price">
¥
{discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0}
</div>
</div>
<div className="bottom">
<div className="value">寄送至</div>
{list ? (
<div className="value-content">{list![value]?.takeAddress}</div>
) : null}
</div>
</div>
<div className="detail-sumbit">
<Button className="btn" onClick={detailSumbit}>
提交订单
</Button>
</div>
</div>
</div>
<Modal
wrapClassName="Payment"
open={isPaymentOpen}
onOk={handleOkPayment}
onCancel={handleCancel}
getContainer={false}
maskClosable={false}
width={420}
footer={[
<Button
style={{ width: '100%', height: 44 }}
key="submit"
type="primary"
loading={loading}
onClick={handleOkPayment}
>
立即付款
</Button>,
]}
>
<div className="title">
{discount?.specPrice[0]?.price! * shopDetail?.num! * days! || 0}
</div>
<div>云享飞账号: {userInfo?.uid}</div>
<div>付款方式: 可用(¥{paymentDetail?.balance})</div>
</Modal>
<Modal
wrapClassName="addAddress"
open={isAddAddressOpen}
onCancel={() => setIsAddAddressOpen(false)}
getContainer={false}
maskClosable={false}
width={420}
footer={false}
>
<div className="title">扫码管理地址</div>
<div className="image">
<Image
className="addressImg"
preview={{ visible: false }}
src={
window.location.href.includes('https://test.iuav.shop/')
? 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-trial.jpg'
: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-formal.jpg' ||
''
}
onClick={() => setAddressVisible(true)}
/>
<div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible: addressVisible,
onVisibleChange: (vis) => setAddressVisible(vis),
}}
>
<Image
src={
window.location.href.includes('https://test.iuav.shop/')
? 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-trial.jpg'
: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-formal.jpg' ||
''
}
/>
</Image.PreviewGroup>
</div>
</div>
<div className="content">
【打开微信扫一扫】-进入云享飞【我的】- 【个人设置】-【地址管理】
</div>
</Modal>
</OrderForGoodsBox>
)
}
import styled from 'styled-components'
export const OrderForGoodsBox = styled.div`
box-sizing: border-box;
width: 1000px;
.address {
.top {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e6e6e6;
height: 30px;
line-height: 30px;
margin-top: 30px;
.left {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #333333;
line-height: 18px;
}
.right {
.btn {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #007aff;
line-height: 19px;
}
}
}
.bottom {
.item {
display: flex;
justify-content: space-between;
align-items: center;
width: 1000px;
height: 48px;
border: 1px solid transparent;
margin-top: 8px;
&.active {
background: #fff1e8;
border-radius: 6px;
border: 1px solid #ff552d;
}
.left {
display: flex;
align-items: center;
justify-content: space-around;
.active {
margin-right: 18px;
display: flex;
.icon {
width: 15px;
height: 22px;
background: #ff552d;
margin-left: 17px;
}
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
margin-left: 18px;
}
}
}
.right {
margin-right: 22px;
}
}
}
}
.info {
margin-top: 30px;
.title {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #333333;
line-height: 18px;
}
.table {
.table-title {
display: flex;
align-items: center;
width: 1000px;
border-bottom: 1px solid #e6e6e6;
padding: 10px 0;
margin-top: 20px;
.table-item {
text-align: center;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
}
}
.table-body {
display: flex;
align-items: center;
height: 100px;
margin-top: 10px;
.body-item {
text-align: center;
&.article {
display: flex;
justify-content: space-between;
.image {
margin-right: 10px;
.image-box {
width: 80px;
height: 80px;
}
}
.right {
.top {
width: 171px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #141414;
line-height: 20px;
}
.bottom {
width: 171px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
}
}
&.lease-term {
display: flex;
align-items: center;
justify-content: center;
.num {
width: 62px;
height: 24px;
background: #ff552d;
border-radius: 2px;
position: relative;
margin: 0 15px;
line-height: 24px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #ffffff;
&::before {
content: '';
width: 10px;
height: 1px;
background-color: #ff552d;
position: absolute;
left: -10px;
top: 50%;
transform: translateY(-50%);
}
&::after {
content: '';
width: 10px;
height: 1px;
background-color: #ff552d;
position: absolute;
right: -10px;
top: 50%;
transform: translateY(-50%);
}
}
}
&.total-price {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff3100;
line-height: 18px;
}
}
}
}
}
.notes {
display: flex;
align-items: center;
justify-content: space-between;
width: 1000px;
height: 110px;
background: #e1efff;
border: 1px solid #d0eaf5;
padding: 0 22px 0 16px;
.left {
display: flex;
align-items: top;
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
margin-top: 4px;
}
}
.right {
width: 430px;
.top {
display: flex;
align-items: center;
justify-content: space-between;
}
.font {
display: flex;
}
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 18px;
}
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
margin-right: 12px;
}
.value {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #2b2b2b;
line-height: 20px;
}
.price {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff3100;
line-height: 18px;
}
}
}
.detail-box {
display: flex;
justify-content: flex-end;
margin-top: 26px;
.right-box {
.detail {
width: 477px;
height: 110px;
border: 1px solid #ff5001;
padding: 16px 19px 19px 19px;
.top {
display: flex;
justify-content: flex-end;
align-items: center;
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #474747;
line-height: 19px;
margin-right: 10px;
}
.price {
font-size: 26px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff552d;
line-height: 33px;
}
}
.bottom {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 15px;
.value {
font-size: 12px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #000000;
line-height: 15px;
margin-right: 10px;
}
.value-content {
font-size: 12px;
font-family: MicrosoftYaHei;
color: #333333;
line-height: 16px;
}
}
}
.detail-sumbit {
display: flex;
justify-content: flex-end;
.btn {
width: 182px;
height: 39px;
background: #ff552d;
border: 1px solid #ff5001;
border-radius: 0;
color: #ffffff;
}
}
}
}
.Payment {
.title {
text-align: center;
font-size: 26px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff552d;
}
}
.addAddress {
.title {
text-align: center;
height: 25px;
font-size: 20px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #000000;
line-height: 25px;
}
.image {
display: flex;
justify-content: center;
align-items: center;
padding: 48px 0 32px;
.addressImg {
width: 150px;
height: 150px;
}
}
.content {
text-align: center;
width: 311px;
height: 38px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #3e454d;
line-height: 19px;
}
}
`
import React , {useState,useRef} from 'react' import React, { useState, useRef } from 'react'
import {Box} from './styled'; import { Box } from './styled'
import { LeftOutlined , RightOutlined } from '@ant-design/icons'; import { LeftOutlined, RightOutlined } from '@ant-design/icons'
import {WareImgsType} from '../../api'; import { WareImgsType } from '../../api'
interface ImagesType{ interface ImagesType {
imgList: Array<WareImgsType> imgList: Array<WareImgsType>
} }
export default function PicturePreview(props:ImagesType) { export default function PicturePreview(props: ImagesType) {
const {imgList} = props const { imgList } = props
console.log(imgList);
const mask =useRef<HTMLDivElement>(null!)
const moveBox =useRef<HTMLDivElement>(null!)
const big =useRef<HTMLImageElement>(null!)
const [moveLeft,setMoveLeft] = useState(0) // 根据这个值设置图片列表向左偏移
// const imgList = [
// 'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
// 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
// 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
// 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
// 'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
// 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
// 'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg'
// ]
const [activeImgIndex,setActiveImgIndex] = useState(0) const mask = useRef<HTMLDivElement>(null!)
const moveBox = useRef<HTMLDivElement>(null!)
const big = useRef<HTMLImageElement>(null!)
const [moveLeft, setMoveLeft] = useState(0) // 根据这个值设置图片列表向左偏移
// const imgList = [
// 'https://fuss10.elemecdn.com/a/3f/3302e58f9a181d2509f3dc0fa68b0jpeg.jpeg',
// 'https://fuss10.elemecdn.com/1/34/19aa98b1fcb2781c4fba33d850549jpeg.jpeg',
// 'https://fuss10.elemecdn.com/0/6f/e35ff375812e6b0020b6b4e8f9583jpeg.jpeg',
// 'https://fuss10.elemecdn.com/9/bb/e27858e973f5d7d3904835f46abbdjpeg.jpeg',
// 'https://fuss10.elemecdn.com/d/e6/c4d93a3805b3ce3f323f7974e6f78jpeg.jpeg',
// 'https://fuss10.elemecdn.com/3/28/bbf893f792f03a54408b3b7a7ebf0jpeg.jpeg',
// 'https://fuss10.elemecdn.com/2/11/6535bcfb26e4c79b48ddde44f4b6fjpeg.jpeg'
// ]
// 改变预览图 const [activeImgIndex, setActiveImgIndex] = useState(0)
const handleChangeImg = (index:number) => {
if (index <= moveLeft + 3) setActiveImgIndex(index) // 改变预览图
} const handleChangeImg = (index: number) => {
// 移动缩略图 if (index <= moveLeft + 3) setActiveImgIndex(index)
const handleSlide = (direction:string) => { }
//左侧按钮 // 移动缩略图
if (direction == 'left') { const handleSlide = (direction: string) => {
moveLeft == 0 ? setMoveLeft(0) : setMoveLeft((props)=>props - 1) //左侧按钮
} else { // 右侧按钮 if (direction == 'left') {
if (imgList.length > 4) { moveLeft == 0 ? setMoveLeft(0) : setMoveLeft((props) => props - 1)
moveLeft >= imgList.length - 4 ? setMoveLeft(imgList.length - 4) : setMoveLeft((props)=>props + 1) } else {
} // 右侧按钮
} if (imgList.length > 4) {
} moveLeft >= imgList.length - 4
// 图片放大镜 ? setMoveLeft(imgList.length - 4)
const handleMouseMove = (event:React.MouseEvent<HTMLDivElement, MouseEvent>) => { : setMoveLeft((props) => props + 1)
let left = event.nativeEvent.offsetX - mask.current.offsetWidth / 2;
let top = event.nativeEvent.offsetY - mask.current.offsetHeight / 2;
// 最右侧和最下侧的临界值
const maxLeft = moveBox.current.offsetWidth - mask.current.offsetWidth
const maxTop = moveBox.current.offsetHeight - mask.current.offsetHeight
//约束范围
if (left <= 0) left = 0;
if (left >= maxLeft) left = maxLeft
if (top <= 0) top = 0;
if (top >= maxTop) top = maxTop
// 设置放大范围遮罩层位置
mask.current.style.left = left + "px";
mask.current.style.top = top + "px";
// 设置大图图片位置,可以用background代替这个方案,有兴趣可以尝试
big.current.style.left = -3 * left + "px"; // 3这个值是 大图除以小图算出来的比例 这里大图是900px 小图是300px
big.current.style.top = -3 * top + "px";
} }
}
}
// 图片放大镜
const handleMouseMove = (
event: React.MouseEvent<HTMLDivElement, MouseEvent>
) => {
let left = event.nativeEvent.offsetX - mask.current.offsetWidth / 2
let top = event.nativeEvent.offsetY - mask.current.offsetHeight / 2
// 最右侧和最下侧的临界值
const maxLeft = moveBox.current.offsetWidth - mask.current.offsetWidth
const maxTop = moveBox.current.offsetHeight - mask.current.offsetHeight
//约束范围
if (left <= 0) left = 0
if (left >= maxLeft) left = maxLeft
if (top <= 0) top = 0
if (top >= maxTop) top = maxTop
// 设置放大范围遮罩层位置
mask.current.style.left = left + 'px'
mask.current.style.top = top + 'px'
// 设置大图图片位置,可以用background代替这个方案,有兴趣可以尝试
big.current.style.left = -3 * left + 'px' // 3这个值是 大图除以小图算出来的比例 这里大图是900px 小图是300px
big.current.style.top = -3 * top + 'px'
}
return ( return (
<Box> <Box>
<div className="img_wrapper"> <div className="img_wrapper">
<div className="img_content"> <div className="img_content">
{/* <!-- 蒙层,绑定鼠标事件 --> */} {/* <!-- 蒙层,绑定鼠标事件 --> */}
<div className="movebox" <div
onMouseMove={(e)=>handleMouseMove(e)} className="movebox"
ref={moveBox}> onMouseMove={(e) => handleMouseMove(e)}
</div> ref={moveBox}
{/* <!-- 主图 --> */} ></div>
<img src={imgList && imgList[activeImgIndex].imgUrl} {/* <!-- 主图 --> */}
<img
src={imgList && imgList[activeImgIndex].imgUrl}
className="img_small" className="img_small"
alt=""/> alt=""
{/* <!-- 放大区域 --> */} />
<div className="mask" {/* <!-- 放大区域 --> */}
ref={mask}></div> <div className="mask" ref={mask}></div>
{/* <!-- 大图预览图 --> */} {/* <!-- 大图预览图 --> */}
<div className="img_big"> <div className="img_big">
<img src={imgList && imgList[activeImgIndex].imgUrl} <img
ref={big} src={imgList && imgList[activeImgIndex].imgUrl}
alt=""/> ref={big}
</div> alt=""
/>
</div>
</div> </div>
{/* <!-- 缩略图列表 --> */} {/* <!-- 缩略图列表 --> */}
<div className="img_list_wrapper"> <div className="img_list_wrapper">
{imgList?.length>4 && <LeftOutlined className="el-icon-arrow-left" onClick={()=>handleSlide('left')}/>} {imgList?.length > 4 && (
<div className="img_list_content"> <LeftOutlined
<div className="img_list" className="el-icon-arrow-left"
style={{marginLeft: - moveLeft * 25 + '%'}}> onClick={() => handleSlide('left')}
{ />
imgList?.map((item,index)=>( )}
<img <div className="img_list_content">
onMouseOver={()=>handleChangeImg(index)} <div
key={index} className="img_list"
className={`${activeImgIndex === index ? 'activeImg' : ''}`} style={{ marginLeft: -moveLeft * 25 + '%' }}
src={item.imgUrl} >
alt="" /> {imgList?.map((item, index) => (
)) <img
} onMouseOver={() => handleChangeImg(index)}
</div> key={index}
</div> className={`${activeImgIndex === index ? 'activeImg' : ''}`}
{ imgList?.length>4 && <RightOutlined className="el-icon-arrow-right" onClick={()=>handleSlide('right')}/>} src={item.imgUrl}
</div> alt=""
</div> />
))}
</div>
</div>
{imgList?.length > 4 && (
<RightOutlined
className="el-icon-arrow-right"
onClick={() => handleSlide('right')}
/>
)}
</div>
</div>
</Box> </Box>
) )
} }
import styled from "styled-components" import styled from 'styled-components'
export const Box = styled.div` export const Box = styled.div`
box-sizing: border-box; box-sizing: border-box;
width: 1200px; width: 1200px;
background-color: #fff; background-color: #fff;
padding: 42px 0 24px 24px; padding: 42px 0 24px 24px;
.item{ .item {
display: flex;
&-right {
height: 300px;
margin-left: 30px;
.title {
height: 26px;
font-size: 28px;
margin-top: 5px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #090909;
line-height: 26px;
}
.function {
display: flex; display: flex;
&-right{ align-items: center;
height: 300px; justify-content: space-evenly;
margin-left: 30px; width: 375px;
.title{ height: 45px;
height: 26px; margin-top: 17px;
font-size: 28px; background: linear-gradient(90deg, #d7f7f5 0%, #eefde9 100%);
margin-top: 5px; &.not {
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; background: none;
font-weight: bold; }
color: #090909; &-item {
line-height: 26px; }
} }
.function{ .menoy {
display: flex; margin-top: 17px;
align-items: center; font-size: 32px;
justify-content: space-evenly; color: #ef2e00;
width: 375px; &-left {
height: 45px; width: 79px;
margin-top: 17px; height: 41px;
background: linear-gradient(90deg, #D7F7F5 0%, #EEFDE9 100%); font-size: 32px;
&.not{ font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
background: none; font-weight: bold;
} color: #ef2e00;
&-item{ line-height: 41px;
} }
} &-right {
.menoy{ width: 40px;
margin-top: 17px; height: 20px;
&-left{ font-size: 16px;
width: 79px; font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
height: 41px; font-weight: bold;
font-size: 32px; color: #ef2e00;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; line-height: 20px;
font-weight: bold; }
color: #EF2E00; }
line-height: 41px; .classification {
} margin-top: 28px;
&-right{ width: 375px;
width: 40px; height: 50px;
height: 20px; .label {
font-size: 16px; height: 21px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; font-size: 16px;
font-weight: bold; font-family: MicrosoftYaHei;
color: #EF2E00; color: #9a9a9a;
line-height: 20px; line-height: 21px;
} margin-right: 36px;
} }
.classification{ .value {
margin-top: 28px; height: 21px;
width: 375px; font-size: 16px;
height: 50px; font-family: MicrosoftYaHei;
.label{ color: #151515;
height: 21px; line-height: 21px;
font-size: 16px; }
font-family: MicrosoftYaHei; .top {
color: #9A9A9A; display: flex;
line-height: 21px; justify-content: space-between;
margin-right: 36px; align-items: center;
} .left {
.value{ }
height: 21px; .right {
font-size: 16px; .selectItem {
font-family: MicrosoftYaHei; .ant-select-selection-placeholder {
color: #151515; color: #000;
line-height: 21px; }
}
.top{
display: flex;
justify-content: space-between;
align-items: center;
.left{
}
.right{
.selectItem{
.ant-select-selection-placeholder {
color: #000;
}
}
}
}
.bottom{
margin-top: 5px;
}
}
.botton-btn{
margin-top: 30px;
.btn-left{
width: 207px;
height: 40px;
background-color: #FFE4D1;
border: 1px solid #EBBAAF;
font-family: MicrosoftYaHei;
color: #FF552D;
letter-spacing: 1px;
margin-right: 12px;
}
.btn-right{
width: 207px;
height: 40px;
background: #FF552D;
font-family: MicrosoftYaHei;
color: #FFFFFF;
letter-spacing: 1px;
}
} }
}
}
.bottom {
margin-top: 5px;
}
}
.botton-btn {
margin-top: 30px;
.btn-left {
width: 207px;
height: 40px;
background-color: #ffe4d1;
border: 1px solid #ebbaaf;
font-family: MicrosoftYaHei;
color: #ff552d;
letter-spacing: 1px;
margin-right: 12px;
} }
.btn-right {
width: 207px;
height: 40px;
background: #ff552d;
font-family: MicrosoftYaHei;
color: #ffffff;
letter-spacing: 1px;
}
}
} }
}
.flow-path{ .flow-path {
width: 100%; width: 100%;
height: 192px; height: 192px;
text-align: center; text-align: center;
margin-top: 72px; margin-top: 72px;
position: relative; position: relative;
.image{ .image {
margin: 0 auto; margin: 0 auto;
}
} }
.prompt{ }
width: 420px; .prompt {
height: 25px; width: 420px;
font-size: 20px; height: 25px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; font-size: 20px;
font-weight: bold; font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
color: #2B2B2B; font-weight: bold;
line-height: 25px; color: #2b2b2b;
margin: 30px auto 58px auto; line-height: 25px;
margin: 30px auto 58px auto;
}
.divider {
display: flex;
justify-content: center;
margin: 46px 0 30px !important;
&::before {
width: 65px !important;
} }
.divider {
display: flex;
justify-content: center;
margin: 46px 0 30px !important;
&::before { &::after {
width: 65px !important; width: 65px !important;
} }
&::after { .ant-divider-inner-text {
width: 65px !important; font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #989898;
}
}
.application {
.title {
display: flex;
align-items: center;
padding-bottom: 25px;
.left {
width: 58px;
height: 58px;
background: #d8d8d8;
border-radius: 2px;
}
.right {
margin-left: 15px;
.top {
.tag {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff0f0f;
}
.money {
font-size: 22px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ff0f0f;
}
.unit {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff0f0f;
}
} }
.bottom {
.ant-divider-inner-text { width: 65px;
font-size: 16px; height: 18px;
font-size: 13px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #121212;
line-height: 18px;
}
}
}
.form-data {
.tagsData {
position: relative;
&.disable {
cursor: no-drop;
}
&.tagsDisable::after {
content: '缺货';
position: absolute;
top: -10px;
right: -10px;
border-radius: 5px 0;
width: 37px;
height: 14px;
line-height: 14px;
text-align: center;
background-color: #ccc;
font-size: 12px;
color: rgb(248, 248, 248);
}
}
.num-box {
display: flex;
justify-content: space-between;
align-items: center;
.num-left {
display: flex;
align-items: center;
.label {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; font-weight: 400;
color: #989898; color: #121212;
margin-right: 5px;
}
} }
}
} }
.application{ }
.title{ .applicationDate {
display: flex; .title {
align-items: center; display: flex;
padding-bottom: 25px; align-items: center;
.left{ .left {
width: 58px; width: 10px;
height: 58px; cursor: pointer;
background: #D8D8D8; }
border-radius: 2px; .right {
} flex: 1;
.right{ text-align: center;
margin-left: 15px; }
.top{ }
.tag{ .bottom-item {
font-size: 14px; display: flex;
font-family: PingFangSC-Regular, PingFang SC; justify-content: space-between;
font-weight: 400; align-items: center;
color: #FF0F0F; height: 50px;
} line-height: 50px;
.money{ border-bottom: 1px solid #d9d9d9;
font-size: 22px; .label {
font-family: PingFangSC-Medium, PingFang SC; font-size: 14px;
font-weight: 500; font-family: ArialMT;
color: #FF0F0F; color: #2f2f2f;
} }
.unit{ .price {
font-size: 12px; display: flex;
font-family: PingFangSC-Regular, PingFang SC; .left {
font-weight: 400; font-size: 14px;
color: #FF0F0F; font-family: Arial-BoldMT, Arial;
} font-weight: normal;
} color: #ff552d;
.bottom{ margin-right: 4px;
width: 65px; }
height: 18px; .right {
font-size: 13px; font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC; font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400; color: #959595;
color: #121212;
line-height: 18px;
}
}
} }
}
} }
` }
\ No newline at end of file `
import React, { useEffect, useState , useRef } from "react"; import { Pagination } from 'antd'
import { useRouter } from "next/router"; import Image from 'next/image'
import { Pagination } from "antd"; import { useRouter } from 'next/router'
import { Box } from "./styled"; import { useContext, useEffect, useRef, useState } from 'react'
import Layout from "~/components/layout"; import ContentBox from '~/components/contentBox'
import ContentBox from "~/components/contentBox"; import Filter, { AdapterResult, FilterResult } from '~/components/filter'
import Filter, { FilterResult, AdapterResult } from "~/components/filter"; import Layout from '~/components/layout'
import Image from "next/image"; import api, { Advertisement, Device } from './api'
import api, { Device, Advertisement } from "./api"; import { Box } from './styled'
import { UserContext } from '~/lib/userProvider'
// 此函数在构建时被调用 // 此函数在构建时被调用
export async function getStaticProps() { export async function getStaticProps() {
//获取筛选数据,进行静态渲染 //获取筛选数据,进行静态渲染
return { return {
props: {}, props: {},
}; }
} }
type Props = {}; type Props = {}
export default function EquipmentLeasing(props: Props) { export default function EquipmentLeasing(props: Props) {
const router = useRouter(); const { userInfo } = useContext(UserContext)
const filter = useRef<any>() const router = useRouter()
const [productList, setProductList] = useState( const [productList, setProductList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const [rightProductList, setRightProductList] = useState( const [rightProductList, setRightProductList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const leftDom = (item: Device) => { const leftDom = (item: Device) => {
return ( return (
...@@ -36,64 +37,62 @@ export default function EquipmentLeasing(props: Props) { ...@@ -36,64 +37,62 @@ export default function EquipmentLeasing(props: Props) {
> >
<div className="item-top"> <div className="item-top">
<div className="item-top-image"> <div className="item-top-image">
<Image <Image src={item.images} alt="error" fill />
src={item.wareImgs[0].imgUrl}
alt="error"
fill
/>
</div> </div>
</div> </div>
<div className="item-bottom"> <div className="item-bottom">
<div className="item-bottom-title" title={item.wareTitle}> <div className="item-bottom-title" title={item.goodsName}>
{item.wareTitle} {item.goodsName}
</div>
<div className="item-bottom-price">
<span className="money">¥{item.minRent}</span>
<span className="unit">/天起</span>
</div> </div>
{userInfo?.cooperationTagId ? (
<div className="item-bottom-price">
<span className="money">¥{item.price}</span>
<span className="unit">/天起</span>
</div>
) : (
<div className="unit">暂无报价</div>
)}
</div> </div>
</div> </div>
); )
}; }
const rightDom = (item: Advertisement) => { const rightDom = (item: Advertisement) => {
return ( return (
<div key={item.id} className="right-box-item right-item"> <div key={item.id} className="right-box-item right-item">
<Image src={item.imageUrl} alt="error" fill /> <Image src={item.imageUrl} alt="error" fill />
</div> </div>
); )
}; }
const [filterResult, setFilterResult] = useState<AdapterResult>({}); //筛选结果 const [filterResult, setFilterResult] = useState<AdapterResult>({}) //筛选结果
const [count, setCount] = useState(0); //商品总数 const [count, setCount] = useState(0) //商品总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断 const [abort, setAbort] = useState<AbortController | null>(null) //请求中断
const [pageParams, setPageParams] = useState({ const [pageParams, setPageParams] = useState({
type: 1,
pageNo: 1, pageNo: 1,
pageSize: 15, pageSize: 15,
}); //分页器对象 }) //分页器对象
const onPageChange = (page: number, pageSize: number) => { const onPageChange = (page: number, pageSize: number) => {
setPageParams({ setPageParams({
...pageParams, ...pageParams,
pageNo: page, pageNo: page,
}); })
}; }
useEffect(() => { useEffect(() => {
//中断前一次列表请求 //中断前一次列表请求
abort?.abort(); abort?.abort()
setAbort(new AbortController()); setAbort(new AbortController())
}, [filterResult, pageParams]); }, [filterResult, pageParams])
//端口列表请求 //端口列表请求
useEffect(() => { useEffect(() => {
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
const idArr = filter.current.idArr
let rs let rs
for (const key in queryVal) { if (Object.keys(queryVal).length) {
if (idArr.includes(key)) { rs = { categoryId: [Number(queryVal['categoryId'])] }
rs = {[key]:router.query[key]}
}
} }
api api
.listPageDeviceInfo( .listPageDeviceInfo(
...@@ -109,59 +108,55 @@ export default function EquipmentLeasing(props: Props) { ...@@ -109,59 +108,55 @@ export default function EquipmentLeasing(props: Props) {
.then((res) => { .then((res) => {
setProductList( setProductList(
res.result?.list?.map((item) => { res.result?.list?.map((item) => {
return { element: leftDom(item) }; return { element: leftDom(item) }
}) || [] }) || []
); )
setCount(res.result?.totalCount || 0); setCount(res.result?.totalCount || 0)
}); })
}, [abort]); }, [abort])
const onFilterChange = ( const onFilterChange = (
filterResult: FilterResult, filterResult: FilterResult,
adapterFilterResult: AdapterResult adapterFilterResult: AdapterResult
) => { ) => {
console.log("filterResult", filterResult, adapterFilterResult); console.log('filterResult', filterResult, adapterFilterResult)
setFilterResult(adapterFilterResult); adapterFilterResult.categoryId = adapterFilterResult.categoryId?.map(
}; (item) => item.id
)
setFilterResult(adapterFilterResult)
}
useEffect(() => { useEffect(() => {
api.listAdvertisementInfo().then((res) => { api.listAdvertisementInfo().then((res) => {
setRightProductList( setRightProductList(
res.result?.map((item) => { res.result?.map((item) => {
return { element: rightDom(item) }; return { element: rightDom(item) }
}) || [] }) || []
); )
}); })
}, []); }, [])
useEffect(() => { useEffect(() => {
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
if (router.query) { if (Object.keys(router.query).length) {
const idArr = filter.current.idArr setFilterResult({ categoryId: [Number(queryVal['categoryId'])] })
for (const key in queryVal) {
if (idArr.includes(key)) {
setFilterResult({ [key]:router.query[key] });
}
}
} }
}, [router]); }, [router])
return ( return (
<Layout> <Layout>
<Box> <Box>
<Filter <Filter
types={["地域", "设备类目", "设备品牌", "设备型号"]} types={['地域', '设备品牌', '设备型号']}
showResultItem showResultItem
onChange={onFilterChange} onChange={onFilterChange}
ref={filter}
></Filter> ></Filter>
<div style={{ paddingTop: 13 }}> <div style={{ paddingTop: 13 }}>
<ContentBox <ContentBox
boxIndex={5} boxIndex={5}
leftcontentstyle={{ leftcontentstyle={{
width: "1010px", width: '1010px',
margin: { top: 0, right: "12px", bottom: "12px", left: 0 }, margin: { top: 0, right: '12px', bottom: '12px', left: 0 },
}} }}
leftRenderDom={{ leftRenderDom={{
columns: productList, columns: productList,
...@@ -185,5 +180,5 @@ export default function EquipmentLeasing(props: Props) { ...@@ -185,5 +180,5 @@ export default function EquipmentLeasing(props: Props) {
</div> </div>
</Box> </Box>
</Layout> </Layout>
); )
} }
import styled from "styled-components"; import styled from 'styled-components'
export default function Style() { export default function Style() {
return <></>; return <></>
} }
export const Box = styled.div` export const Box = styled.div`
...@@ -54,14 +54,14 @@ export const Box = styled.div` ...@@ -54,14 +54,14 @@ export const Box = styled.div`
color: #ff552d; color: #ff552d;
line-height: 22px; line-height: 22px;
} }
.unit { }
width: 58px; .unit {
height: 22px; width: 58px;
font-size: 14px; height: 22px;
font-family: MicrosoftYaHei; font-size: 14px;
color: #ff552d; font-family: MicrosoftYaHei;
line-height: 22px; color: #ff552d;
} line-height: 22px;
} }
} }
} }
...@@ -76,4 +76,4 @@ export const Box = styled.div` ...@@ -76,4 +76,4 @@ export const Box = styled.div`
.pagination-page { .pagination-page {
text-align: right; text-align: right;
} }
`; `
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
import { TypesResp } from '~/components/filter/api'
export interface ListPageFlyingInfoParams { export interface ListPageFlyingInfoParams {
pageNo: number, pageNo: number
pageSize: number, pageSize: number
flightSkillsId?:number, flightSkillsId?: number
licenseId?:number, licenseId?: number
regionId?:number regionId?: number
} }
export interface Flying { export interface Flying {
id: number, id: number
price: number, price: number
supplierName: string, supplierName: string
curriculumName: string, curriculumName: string
free: 0 | 1, free: 0 | 1
curriculumDesc: string, curriculumDesc: string
videoUrl: string videoUrl: string
surfaceUrl: string
} }
export interface ListPageFlyingInfoResp { export interface ListPageFlyingInfoResp {
pageNo: 1, pageNo: 1
pageSize: 10, pageSize: 10
list: Array<Flying>, list: Array<Flying>
totalCount: 0, totalCount: 0
totalPage: 0 totalPage: 0
} }
export interface SkillsType { export interface SkillsType {
type: string; type: string
id: number, id: number
skillsName: string, skillsName: string
label:string | number, label: string | number
value:string | number value: string | number
} }
export interface RegionResp { export interface RegionResp {
childInfo: RegionResp[] | null, childInfo: RegionResp[] | null
id: number, id: number
level: number, level: number
name: string, name: string
pid: number pid: number
} }
export interface PilotRegistrationParams { export interface PilotRegistrationParams {
city?: number, city?: number
drivingLicense?: number, drivingLicense?: number
industryAppAuth?: Array<number>, industryAppAuth?: Array<number>
province?: number, province?: number
remark?: string, remark?: string
telephone?: string, telephone?: string
uavLicenseLevelOne?: number, uavLicenseLevelOne?: number
uavLicenseLevelTwo?: number uavLicenseLevelTwo?: number
} }
export default { export default {
//web-作业服务-分页 //web-飞手培训-分页
listPageJobServicesInfo: (params: ListPageFlyingInfoParams): Promise<Response<ListPageFlyingInfoResp>> => { listPageJobServicesInfo: (
return request('/release/curriculum/queryCurriculumInfoList', 'post', params) params: ListPageFlyingInfoParams
): Promise<Response<ListPageFlyingInfoResp>> => {
return request(
'/release/curriculum/queryCurriculumInfoList',
'post',
params
)
}, },
region: (): Promise<Response<Array<RegionResp>>> => { region: (): Promise<Response<Array<RegionResp>>> => {
return request('/pms/webDevice/getSecondDistrictInfo'); return request('/pms/webDevice/getSecondDistrictInfo')
}, },
PilotLicense: (): Promise<Response<Array<RegionResp>>> => { PilotLicense: (): Promise<Response<Array<RegionResp>>> => {
return request('/release/curriculum/getDronePilotLicense'); return request('/release/curriculum/getDronePilotLicense')
}, },
IndustryFlightSkills: (): Promise<Response<Array<SkillsType>>> => { IndustryFlightSkills: (): Promise<Response<Array<SkillsType>>> => {
return request('/release/curriculum/getIndustryFlightSkills'); return request('/release/curriculum/getIndustryFlightSkills')
}, },
PilotRegistrations: (params:PilotRegistrationParams): Promise<Response<Array<SkillsType>>> => { PilotRegistrations: (
return request('/release/curriculum/pilotRegistration',"post",params); params: PilotRegistrationParams
): Promise<Response<Array<SkillsType>>> => {
return request('/release/curriculum/pilotRegistration', 'post', params)
}, },
} FlightSkills: (params: { type: 3 }): Promise<Response<Array<TypesResp>>> => {
\ No newline at end of file return request('/pms/classify/queryCategoryInfoByType', 'get', params)
},
}
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react'
import Layout from "~/components/layout"; import Layout from '~/components/layout'
import { Box } from "./styled"; import { Box } from './styled'
import { Button } from "antd"; import { Button, Tabs } from 'antd'
import { useRouter } from "next/router"; import { useRouter } from 'next/router'
import { ParsedUrlQuery } from "querystring"; import { ParsedUrlQuery } from 'querystring'
import type { TabsProps } from 'antd'
import api, { ListPageFlyingInfoResp } from './api'
interface RouterDetail { const contentStyle: React.CSSProperties = {
videoUrl:string | '', width: '100%',
curriculumName:string
} }
export default function FlyingDetail() { export default function FlyingDetail() {
const router = useRouter()
const router = useRouter(); const [detail, setDetail] = useState<ListPageFlyingInfoResp | null>()
const [detail,setDetail] =useState<ParsedUrlQuery | RouterDetail>() const onChange = (key: string) => {
useEffect(()=>{ console.log(key)
setDetail(router.query) }
},[router])
const items: TabsProps['items'] = [
{
key: '1',
label: `介绍`,
children: (
<div className="body">
<div className="top">
<div className="title">课程简介</div>
<div className="content">{detail?.curriculumDesc}</div>
</div>
{/* <div className="bottom">详情</div> */}
{detail?.detailContent && (
<div
dangerouslySetInnerHTML={{ __html: detail?.detailContent }}
></div>
)}
</div>
),
},
]
useEffect(() => {
if (Object.keys(router.query).length) {
api
.listPageJobServicesInfo({ id: Number(router.query.id) })
.then((res) => {
console.log(res)
setDetail(res.result)
})
}
}, [router])
return ( return (
<Layout> <Layout contentStyle={contentStyle}>
<Box> <Box>
<div className="box-top"> <div className="box">
<div className="left">{detail?.curriculumName}</div> <div className="box-body">
<div className="right"> <video
{/* <Button className="body-video"
controls
src={detail?.videoUrl as string}
/>
</div>
<div className="box-bottom">
<div className="left">
<div className="top">{detail?.curriculumName}</div>
<div className="bottom">免费</div>
</div>
<div className="right">
{/* <Button
type="primary" type="primary"
className="btn" className="btn"
onClick={() => onClick={() =>
...@@ -32,12 +75,18 @@ export default function FlyingDetail() { ...@@ -32,12 +75,18 @@ export default function FlyingDetail() {
> >
去考试 去考试
</Button> */} </Button> */}
</div>
</div> </div>
</div> </div>
<div className="box-body"> <div className="detail">
<video className="body-video" controls src={detail?.videoUrl as string} /> <Tabs
className="tabs"
defaultActiveKey="1"
items={items}
onChange={onChange}
/>
</div> </div>
</Box> </Box>
</Layout> </Layout>
); )
} }
import request, { Response } from '~/api/request'
export interface ListPageFlyingInfoParams {
id: number
}
export interface Flying {
id: number
price: number
supplierName: string
curriculumName: string
free: 0 | 1
curriculumDesc: string
videoUrl: string
}
export interface ListPageFlyingInfoResp {
id: number
price: number | null
supplierName: string
curriculumName: string
free: number
flightSkills: number
flightSkillsName1: string
flightSkillsName2: string
curriculumDesc: string
surfaceUrl: string | null
videoUrl: string
detailContent: null
}
export default {
//web-飞手培训-详情
listPageJobServicesInfo: (
params: ListPageFlyingInfoParams
): Promise<Response<ListPageFlyingInfoResp>> => {
return request('/release/curriculum/curriculumDetails', 'get', params)
},
}
import styled from "styled-components"; import styled from 'styled-components'
export default function Style() { export default function Style() {
return <></>; return <></>
} }
export const Box = styled.div` export const Box = styled.div`
box-sizing: border-box; box-sizing: border-box;
.box-top { .box {
display: flex; background-color: #fff;
justify-content: space-between; height: 586px;
align-items: center; padding-top: 20px;
padding: 10px 0; .box-body {
.left { margin: 0 auto;
height: 25px; display: flex;
font-size: 20px; width: 1200px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; height: 470px;
font-weight: bold; /* background: #111111; */
color: #000000; .body-video {
line-height: 25px; width: 1200px;
height: 470px;
}
/* .right-box {
width: 362px;
height: 470px;
background: #1b2128;
.tabs {
color: #fff;
}
} */
} }
.right { .box-bottom {
.btn { margin: 0 auto;
width: 180px; width: 1200px;
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 0 38px 0;
.left {
height: 50px; height: 50px;
background: linear-gradient(135deg, #278eff 0%, #0052da 100%); .top {
border-radius: 6px; font-size: 24px;
font-size: 20px; font-family: PingFangSC-Medium, PingFang SC;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; font-weight: 500;
font-weight: bold; color: #000000;
color: #ffffff; margin-bottom: 10px;
&:hover { }
opacity: 0.8; .bottom {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff552d;
}
}
.right {
.btn {
width: 180px;
height: 50px;
background: linear-gradient(135deg, #278eff 0%, #0052da 100%);
border-radius: 6px;
font-size: 20px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ffffff;
&:hover {
opacity: 0.8;
}
} }
} }
} }
} }
.box-body { .detail {
margin-top: 20px; margin: 0 auto;
width: 1200px; width: 1200px;
height: 675px; height: 420px;
background: #111111; background: #ffffff;
.body-video { box-shadow: 0px 2px 6px 0px rgba(183, 188, 197, 0.1);
width: 1200px; border-radius: 12px;
height: 675px; margin-top: 16px;
padding: 20px;
.tabs {
.body {
.top {
.title {
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #000000;
}
.content {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #27323f;
margin-top: 10px;
}
}
.bottom {
font-size: 18px;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #000000;
margin-top: 29px;
}
}
} }
} }
`; `
import React, { useEffect, useState , useContext} from "react"; import {
import { Box } from "./styled"; Button,
import Image from "next/image"; Cascader,
import { Button, Select, Space, Pagination, Cascader, Modal , Form ,Input,Checkbox, message} from "antd"; Checkbox,
import type { CheckboxValueType } from 'antd/es/checkbox/Group'; Form,
import Layout from "~/components/layout"; Input,
import ContentBox from "~/components/contentBox"; Modal,
import api, { Flying, SkillsType, RegionResp } from "./api"; Pagination,
import { useRouter } from "next/router"; Select,
import { UserContext } from "~/lib/userProvider"; Space,
import {phoneNumber} from '~/lib/validateUtils' message,
} from 'antd'
import type { CheckboxValueType } from 'antd/es/checkbox/Group'
import Image from 'next/image'
import { useRouter } from 'next/router'
import { useContext, useEffect, useState } from 'react'
import ContentBox from '~/components/contentBox'
import Layout from '~/components/layout'
import { UserContext } from '~/lib/userProvider'
import { phoneNumber } from '~/lib/validateUtils'
import api, { Flying, RegionResp, SkillsType } from './api'
import { Box } from './styled'
import { TypesResp } from '~/components/filter/api'
interface FilterInfoParams { interface FilterInfoParams {
regionId?: number; provinceId?: number
flightSkillsId?: number; categoryId?: any[]
licenseId?: number;
} }
export default function FlyingHandService() { export default function FlyingHandService() {
const {Option} = Select const { Option } = Select
const router = useRouter(); const router = useRouter()
const { userInfo, setNeedLogin } = useContext(UserContext); const { userInfo, setNeedLogin } = useContext(UserContext)
const [list, setList] = useState([ const [list, setList] = useState([
"https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844-1(1).jpg", 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844-1(1).jpg',
"https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844(1).jpg", 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844(1).jpg',
]); ])
const [productList, setProductList] = useState( const [productList, setProductList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const [rightDomList, setRightDomList] = useState( const [rightDomList, setRightDomList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const [secondDistrictInfo, setSecondDistrictInfo] = useState( const [secondDistrictInfo, setSecondDistrictInfo] = useState(
Array<RegionResp> Array<RegionResp>
); )
const [skills, setSkills] = useState( const [skills, setSkills] = useState(Array<RegionResp>)
Array<RegionResp> const [skillsDefault, setSkillsDefault] = useState<Array<number>>()
); const [flightSkillsList, setFlightSkillsList] = useState<Array<SkillsType>>()
const [skillsDefault, setSkillsDefault] = useState<Array<number>>(); const [flightDefault, setFlightDefault] = useState<number | null>()
const [flightSkillsList, setFlightSkillsList] = useState(Array<SkillsType>); const [selectOption, setSelectOption] = useState<Array<TypesResp> | null>()
const [flightDefault, setFlightDefault] = useState<number | null>(); const [selectDefault, setSelectDefault] = useState<number | null>()
const leftDom = (item: Flying) => { const leftDom = (item: Flying) => {
return ( return (
<div <div
className="item" className="item"
key={item.id} key={item.id}
onClick={() => { onClick={() => {
userInfo ? router.push({ userInfo
pathname: `/flyingHandService/detail/${item.id}`, ? router.push({
query: { pathname: `/flyingHandService/detail/${item.id}`,
videoUrl: item.videoUrl , })
curriculumName: item.curriculumName : setNeedLogin(true)
}, }}
}) : setNeedLogin(true)
} }
> >
<div className="item-top"> <div className="item-top">
<Image <Image
src={`${item.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`} src={
item.videoUrl
? `${item.videoUrl}?x-oss-process=video/snapshot,t_1000,m_fast`
: item.surfaceUrl
}
alt="#" alt="#"
fill fill
/> />
...@@ -72,7 +85,7 @@ export default function FlyingHandService() { ...@@ -72,7 +85,7 @@ export default function FlyingHandService() {
<div className="price-right-label">{item.price}</div> <div className="price-right-label">{item.price}</div>
) : ( ) : (
<div> <div>
<span className="price-right-label">限免</span> <span className="price-right-label">免费听课</span>
{/* <span className='price-right-money'>{`¥${item.price}`}</span> */} {/* <span className='price-right-money'>{`¥${item.price}`}</span> */}
</div> </div>
)} )}
...@@ -80,47 +93,47 @@ export default function FlyingHandService() { ...@@ -80,47 +93,47 @@ export default function FlyingHandService() {
</div> </div>
</div> </div>
</div> </div>
); )
}; }
const rightDom = (item: string) => { const rightDom = (item: string) => {
return ( return (
<div className="right-box-item right-item" key={item}> <div className="right-box-item right-item" key={item}>
<Image src={item} alt="error" fill /> <Image src={item} alt="error" fill />
</div> </div>
); )
}; }
const [pageParams, setPageParams] = useState({ const [pageParams, setPageParams] = useState({
pageNo: 1, pageNo: 1,
pageSize: 12, pageSize: 12,
}); //分页器对象 }) //分页器对象
const [filterParams, setFilterParams] = useState<FilterInfoParams>(); const [filterParams, setFilterParams] = useState<FilterInfoParams>()
const [count, setCount] = useState(0); //商品总数 const [count, setCount] = useState(0) //商品总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断 const [abort, setAbort] = useState<AbortController | null>(null) //请求中断
const onPageChange = (page: number, pageSize: number) => { const onPageChange = (page: number, pageSize: number) => {
setPageParams({ setPageParams({
...pageParams, ...pageParams,
pageNo: page, pageNo: page,
}); })
}; }
useEffect(() => { useEffect(() => {
//中断前一次列表请求 //中断前一次列表请求
abort?.abort(); abort?.abort()
setAbort(new AbortController()); setAbort(new AbortController())
}, [filterParams, pageParams]); }, [filterParams, pageParams])
//端口列表请求 //端口列表请求
useEffect(() => { useEffect(() => {
console.log(router); console.log(router)
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
for (const key in queryVal) { for (const key in queryVal) {
queryVal[key] = Number(queryVal[key]); queryVal[key] = Number(queryVal[key])
} }
api api
.listPageJobServicesInfo({ .listPageJobServicesInfo({
...@@ -131,13 +144,13 @@ export default function FlyingHandService() { ...@@ -131,13 +144,13 @@ export default function FlyingHandService() {
.then((res) => { .then((res) => {
setProductList( setProductList(
res.result?.list?.map((item) => { res.result?.list?.map((item) => {
return { element: leftDom(item) }; return { element: leftDom(item) }
}) || [] }) || []
); )
setCount(res.result?.totalCount || 0); setCount(res.result?.totalCount || 0)
clearRouter() clearRouter()
}); })
}, [abort]); }, [abort])
const clearRouter = () => { const clearRouter = () => {
if (Object.keys(router.query).length) { if (Object.keys(router.query).length) {
...@@ -146,138 +159,172 @@ export default function FlyingHandService() { ...@@ -146,138 +159,172 @@ export default function FlyingHandService() {
} }
} }
const onProvinceChange = (value: number) => { const onSelectChange = (value: number, item: TypesResp) => {
clearRouter() clearRouter()
console.log(value)
if (value) { if (value) {
setFlightDefault(value) setSelectDefault(value)
}else{ } else {
setFlightDefault(null) setSelectDefault(undefined)
} }
setFilterParams((props) => { setFilterParams((props) => {
if (props?.categoryId && value) {
return { return {
...props, ...props,
licenseId: Number(value), categoryId: [...props.categoryId, Number(value)],
}; }
}); }
}; return {
...props,
categoryId: value ? [Number(value)] : undefined,
}
})
}
const onProvinceChange = (value: number) => {
clearRouter()
if (value) {
setFlightDefault(value)
} else {
setFlightDefault(undefined)
}
setFilterParams((props) => {
return {
...props,
licenseId: Number(value),
}
})
}
const onChange = (value: any) => { const onChange = (value: any) => {
clearRouter() clearRouter()
if (value) { if (value) {
setSkillsDefault([value]) setSkillsDefault([value])
}else{ } else {
setSkillsDefault([]) setSkillsDefault([])
} }
setFilterParams((props) => { setFilterParams((props) => {
return { return {
...props, ...props,
flightSkillsId: (value && value[value.length - 1]) || undefined, flightSkillsId: (value && value[value.length - 1]) || undefined,
}; }
}); })
}; }
const onChangeRegion = (value: any) => { const onChangeRegion = (value: any) => {
clearRouter() clearRouter()
// setFilterParams((props) => {
// return {
// ...props,
// regionId: (value && value[value.length - 1]) || undefined,
// };
// });
setFilterParams((props) => { setFilterParams((props) => {
return { return {
...props, ...props,
regionId: (value && value[value.length - 1]) || undefined, provinceId: value || undefined,
}; }
}); })
}; }
useEffect(() => { useEffect(() => {
setRightDomList( setRightDomList(
list.map((item: string) => { list.map((item: string) => {
return { element: rightDom(item) }; return { element: rightDom(item) }
}) })
); )
api.region().then((res) => { api.region().then((res) => {
setSecondDistrictInfo(res.result || []); setSecondDistrictInfo(res.result || [])
}); })
api.PilotLicense().then((res) => { // api.PilotLicense().then((res) => {
setSkills(res.result || []); // setSkills(res.result || [])
}); // })
api.IndustryFlightSkills().then((res) => { // api.IndustryFlightSkills().then((res) => {
const list = res.result?.map((item)=>{ // const list = res.result?.map((item) => {
item.label = item.skillsName // item.label = item.skillsName
item.value = item.id // item.value = item.id
return item // return item
}) // })
setFlightSkillsList(list || []); // setFlightSkillsList(list || [])
}); // })
}, []); api.FlightSkills({ type: 3 }).then((res) => {
console.log(res)
setSelectOption(res.result)
})
}, [])
useEffect(() => { useEffect(() => {
if (Object.keys(router.query).length) { if (Object.keys(router.query).length) {
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
for (const key in queryVal) { for (const key in queryVal) {
queryVal[key] = Number(queryVal[key]); queryVal[key] = Number(queryVal[key])
} }
if (queryVal.flightSkillsId) { if (queryVal.flightSkillsId) {
setSkillsDefault([queryVal.flightSkillsId]) setSkillsDefault([queryVal.flightSkillsId])
}else{ } else {
setFlightDefault(queryVal.licenseId) setFlightDefault(queryVal.licenseId)
} }
setFilterParams((props) => { setFilterParams((props) => {
return { return {
...props, ...props,
...queryVal, ...queryVal,
}; }
}); })
} }
}, [router]); }, [router])
//报名 //报名
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false)
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false)
const handleOk = async (values: any) => { const handleOk = async (values: any) => {
form form
.validateFields() .validateFields()
.then(async (values) => { .then(async (values) => {
setLoading(true); setLoading(true)
try{ try {
const res = await api.PilotRegistrations({ const res = await api.PilotRegistrations({
...values, ...values,
city: values.city[values.city.length - 1] || undefined, city: values.city[values.city.length - 1] || undefined,
province: values.city[0] || undefined, province: values.city[0] || undefined,
uavLicenseLevelOne: values.uavLicenseLevelOne && values.uavLicenseLevelOne[0], uavLicenseLevelOne:
uavLicenseLevelTow: values.uavLicenseLevelOne && values.uavLicenseLevelOne[1], values.uavLicenseLevelOne && values.uavLicenseLevelOne[0],
uavLicenseLevelThree: values.uavLicenseLevelOne && values.uavLicenseLevelOne[2] uavLicenseLevelTow:
}); values.uavLicenseLevelOne && values.uavLicenseLevelOne[1],
if (res.code === "200") { uavLicenseLevelThree:
setLoading(false); values.uavLicenseLevelOne && values.uavLicenseLevelOne[2],
setIsModalOpen(false); })
form.resetFields() if (res.code === '200') {
message.success('报名成功') setLoading(false)
}else{ setIsModalOpen(false)
setLoading(false); form.resetFields()
message.error(res.message) message.success('报名成功')
} } else {
setLoading(false)
}catch(e:any){ message.error(res.message)
message.error(e.message) }
} } catch (e: any) {
}).catch((err) => { message.error(e.message)
message }
.warning({
content: err.errorFields[0].errors[0],
}) })
.then(); .catch((err) => {
}); message
.warning({
}; content: err.errorFields[0].errors[0],
})
.then()
})
}
const handleCancel = () => { const handleCancel = () => {
setIsModalOpen(false); setIsModalOpen(false)
}; }
const [form] = Form.useForm(); const [form] = Form.useForm()
const onChangeCheck = (checkedValues: CheckboxValueType[]) => { const onChangeCheck = (checkedValues: CheckboxValueType[]) => {
console.log('checked = ', checkedValues); console.log('checked = ', checkedValues)
}; }
return ( return (
<Layout> <Layout>
...@@ -285,7 +332,7 @@ export default function FlyingHandService() { ...@@ -285,7 +332,7 @@ export default function FlyingHandService() {
<div className="flyingTop"> <div className="flyingTop">
<div className="flyingTop-left"> <div className="flyingTop-left">
<Space> <Space>
<Cascader {/* <Cascader
allowClear allowClear
placeholder="地域" placeholder="地域"
bordered={false} bordered={false}
...@@ -299,41 +346,40 @@ export default function FlyingHandService() { ...@@ -299,41 +346,40 @@ export default function FlyingHandService() {
options={secondDistrictInfo} options={secondDistrictInfo}
onChange={onChangeRegion} onChange={onChangeRegion}
changeOnSelect changeOnSelect
/> /> */}
<Cascader {/* <Select
allowClear
placeholder="考证"
bordered={false}
className="selectItem"
size="large"
fieldNames={{
label: "licenseType",
value: "id",
children: "childLicenses",
}}
options={skills}
onChange={(value)=>onChange(value)}
changeOnSelect
value={skillsDefault}
/>
<Select
className="selectItem" className="selectItem"
bordered={false} bordered={false}
popupMatchSelectWidth={false} popupMatchSelectWidth={false}
placeholder="技能" placeholder="省份"
size="large" size="large"
onChange={(value) => onProvinceChange(value)} onChange={onChangeRegion}
options={flightSkillsList} options={secondDistrictInfo}
fieldNames={{ value: "id", label: "skillsName" }} fieldNames={{ value: 'id', label: 'name' }}
allowClear allowClear
value={flightDefault} /> */}
/> {/* {selectOption?.map((item) => (
<Select
key={item.directoryId}
className="selectItem"
bordered={false}
popupMatchSelectWidth={false}
placeholder={item.name}
size="large"
onChange={(value) => onSelectChange(value, item)}
options={item.categoriesInfoListDTO}
fieldNames={{ value: 'id', label: 'name' }}
allowClear
/>
))} */}
</Space> </Space>
</div> </div>
<Button <Button
type="primary" type="primary"
className="btn" className="btn"
onClick={() => userInfo ? setIsModalOpen(true) : setNeedLogin(true)} onClick={() =>
userInfo ? setIsModalOpen(true) : setNeedLogin(true)
}
> >
报名学习课程 报名学习课程
</Button> </Button>
...@@ -346,7 +392,11 @@ export default function FlyingHandService() { ...@@ -346,7 +392,11 @@ export default function FlyingHandService() {
getContainer={false} getContainer={false}
footer={[ footer={[
<Button <Button
style={{ width: "100%" ,background: "linear-gradient(135deg, #278EFF 0%, #0052DA 100%)",height: 40 }} style={{
width: '100%',
background: 'linear-gradient(135deg, #278EFF 0%, #0052DA 100%)',
height: 40,
}}
key="submit" key="submit"
type="primary" type="primary"
loading={loading} loading={loading}
...@@ -357,81 +407,91 @@ export default function FlyingHandService() { ...@@ -357,81 +407,91 @@ export default function FlyingHandService() {
]} ]}
> >
<Form <Form
form={form} form={form}
layout="vertical" layout="vertical"
name="application" name="application"
initialValues={{ modifier: 'public' }} initialValues={{ modifier: 'public' }}
>
<div style={{display:"flex",justifyContent:"space-between"}}>
<Form.Item style={{flex:1,marginRight:16}}
name="name"
rules={[{ required: true, message: '请输入姓名!' }]}
> >
<Input placeholder="姓名" /> <div style={{ display: 'flex', justifyContent: 'space-between' }}>
</Form.Item> <Form.Item
<Form.Item style={{flex:1}} name="telephone" rules={[{ required: true, message: '请输入手机号!' }]}> style={{ flex: 1, marginRight: 16 }}
<Input onInput={phoneNumber} allowClear maxLength={11} placeholder="手机号" /> name="name"
</Form.Item> rules={[{ required: true, message: '请输入姓名!' }]}
</div> >
<Form.Item <Input placeholder="姓名" />
name="city" </Form.Item>
rules={[{ required: true, message: '请选择城市!' }]} <Form.Item
> style={{ flex: 1 }}
<Cascader name="telephone"
rules={[{ required: true, message: '请输入手机号!' }]}
>
<Input
onInput={phoneNumber}
allowClear
maxLength={11}
placeholder="手机号"
/>
</Form.Item>
</div>
<Form.Item
name="city"
rules={[{ required: true, message: '请选择城市!' }]}
>
<Cascader
allowClear allowClear
placeholder="城市" placeholder="城市"
className="selectItem" className="selectItem"
fieldNames={{ fieldNames={{
label: "name", label: 'name',
value: "id", value: 'id',
children: "childInfo", children: 'childInfo',
}} }}
options={secondDistrictInfo} options={secondDistrictInfo}
changeOnSelect changeOnSelect
/> />
</Form.Item> </Form.Item>
<Form.Item <Form.Item name="drivingLicense">
name="drivingLicense" <Select allowClear placeholder="是否有驾照">
> <Option value="0"></Option>
<Select allowClear placeholder="是否有驾照"> <Option value="1"></Option>
<Option value="0"></Option> </Select>
<Option value="1"></Option> </Form.Item>
</Select> <Form.Item name="uavLicenseLevelOne">
</Form.Item> <Cascader
<Form.Item
name="uavLicenseLevelOne"
>
<Cascader
allowClear allowClear
placeholder="是否有无人机执照" placeholder="是否有无人机执照"
className="selectItem" className="selectItem"
fieldNames={{ fieldNames={{
label: "licenseType", label: 'licenseType',
value: "id", value: 'id',
children: "childLicenses", children: 'childLicenses',
}} }}
options={skills} options={skills}
changeOnSelect changeOnSelect
/> />
</Form.Item> </Form.Item>
<Form.Item name="industryAppAuth" label="行业应用认证(多选)" className="collection-create-form_last-form-item"> <Form.Item
<Checkbox.Group name="industryAppAuth"
options={flightSkillsList} label="行业应用认证(多选)"
onChange={onChangeCheck} className="collection-create-form_last-form-item"
/> >
</Form.Item> <Checkbox.Group
<Form.Item name="remark"> options={flightSkillsList}
<Input placeholder="备注" /> onChange={onChangeCheck}
</Form.Item> />
</Form> </Form.Item>
<Form.Item name="remark">
<Input placeholder="备注" />
</Form.Item>
</Form>
</Modal> </Modal>
<ContentBox <ContentBox
boxIndex={4} boxIndex={4}
leftcontentstyle={{ leftcontentstyle={{
width: "925px", width: '925px',
margin: { top: 0, right: "10px", bottom: "10px", left: 0 }, margin: { top: 0, right: '10px', bottom: '10px', left: 0 },
}} }}
leftRenderDom={{ leftRenderDom={{
columns: productList, columns: productList,
...@@ -454,5 +514,5 @@ export default function FlyingHandService() { ...@@ -454,5 +514,5 @@ export default function FlyingHandService() {
/> />
</Box> </Box>
</Layout> </Layout>
); )
} }
...@@ -2,12 +2,13 @@ import { PlusOutlined } from "@ant-design/icons"; ...@@ -2,12 +2,13 @@ import { PlusOutlined } from "@ant-design/icons";
import { Form, Input, Modal, Upload, Image, Button, Row, Col } from "antd"; import { Form, Input, Modal, Upload, Image, Button, Row, Col } from "antd";
import type { RcFile, UploadProps } from "antd/es/upload"; import type { RcFile, UploadProps } from "antd/es/upload";
import type { UploadFile } from "antd/es/upload/interface"; import type { UploadFile } from "antd/es/upload/interface";
import { useContext, useState } from "react"; import { useContext, useEffect, useState } from "react";
import gApi from "~/api"; import gApi from "~/api";
import NImage from "next/image"; import NImage from "next/image";
import api from "./api"; import api from "./api";
import { useGeolocation } from "~/lib/hooks"; import { useGeolocation } from "~/lib/hooks";
import { UserContext } from "~/lib/userProvider"; import { UserContext } from "~/lib/userProvider";
import { useToken } from "antd/es/theme/internal";
type Props = { type Props = {
open: boolean; open: boolean;
...@@ -33,6 +34,11 @@ export default function PublishMessage(props: Props) { ...@@ -33,6 +34,11 @@ export default function PublishMessage(props: Props) {
const [form] = Form.useForm(); const [form] = Form.useForm();
const { userInfo, setNeedLogin } = useContext(UserContext); const { userInfo, setNeedLogin } = useContext(UserContext);
const position = useGeolocation(); const position = useGeolocation();
const [token, setToken] = useState('');
useEffect(() => {
setToken(window.localStorage.getItem('token') || '');
}, [])
//预览关闭 //预览关闭
const handlePreviewCancel = () => setPreviewOpen(false); const handlePreviewCancel = () => setPreviewOpen(false);
...@@ -155,6 +161,7 @@ export default function PublishMessage(props: Props) { ...@@ -155,6 +161,7 @@ export default function PublishMessage(props: Props) {
onPreview={handlePreview} onPreview={handlePreview}
onChange={handleChange} onChange={handleChange}
maxCount={1} maxCount={1}
headers={{ token: token }}
> >
{fileList.length >= 8 ? null : ( {fileList.length >= 8 ? null : (
<div> <div>
......
import request, { Response } from "~/api/request"; import request, { Response } from '~/api/request'
export interface AllType { export interface AllType {
type?: string; categoryName: string
id?: number; id: number
name?: string;
appName?: string;
createTime?: string;
industryIcon?: string;
shortName?: null;
industryType?: null;
propagate1?: string;
propagate2?: string;
image?: string;
video?: string;
newsTitle?: string;
newsAuthor?: string;
userAccountId?: number;
surfaceImg?: string;
newsContents?: string;
updateTime?: string | null;
tenderNewsId?: number;
tenderInfoNo?: string;
tenderContent?: string;
tenderPrice?: number;
apply?: number;
skillsName?: string;
} }
export interface FilterOptionResp { export interface FilterOptionResp {
type: string; type: string
id: number; id: number
name: string; name: string
} }
export interface RegionResp { export interface RegionResp {
childInfo: RegionResp[] | null; childInfo: RegionResp[] | null
id: number; id: number
level: number; level: number
name: string; name: string
pid: number; pid: number
} }
export const equipmentLeasingApi = { export const equipmentLeasingApi = {
deviceBrand: (): Promise<Response<Array<FilterOptionResp>>> => { deviceBrand: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/deviceBrand"); return request('/pms/webDevice/deviceBrand')
},
deviceCategory: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/category");
}, },
// deviceCategory: (): Promise<Response<Array<FilterOptionResp>>> => {
// return request("/pms/webDevice/category");
// },
deviceModel: (): Promise<Response<Array<FilterOptionResp>>> => { deviceModel: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/deviceModel"); return request('/pms/webDevice/deviceModel')
}, },
}; }
export interface AppType { export interface AppType {
id: number; id: number
name: string; name: string
appName: string; appName: string
createTime: string; createTime: string
type: string; type: string
} }
export interface IndustryType { export interface IndustryType {
id: number; id: number
industryIcon: string; industryIcon: string
name: string; name: string
shortName: string; shortName: string
industryType: string; industryType: string
propagate1: string; propagate1: string
propagate2: string; propagate2: string
image: string; image: string
video: string; video: string
type: string; type: string
appName: string; appName: string
} }
export const jobServicesApi = { export const jobServicesApi = {
listAllAppType: (): Promise<Response<Array<AppType>>> => { listAllAppType: (): Promise<Response<Array<AppType>>> => {
return request("/release/work/listAllAppType"); return request('/release/work/listAllAppType')
}, },
listAllIndustry: (): Promise<Response<Array<IndustryType>>> => { listAllIndustry: (): Promise<Response<Array<IndustryType>>> => {
return request("/release/work/listAllIndustry"); return request('/release/work/listAllIndustry')
}, },
}; }
export const mallApi = { export const mallApi = {
listAllBrand: (): Promise<Response<Array<FilterOptionResp>>> => { listAllBrand: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/brand"); return request('/pms/webDevice/brand')
}, },
listAllCategory: (): Promise<Response<Array<FilterOptionResp>>> => { listAllCategory: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/category"); return request('/pms/webProductMall/category')
}, },
listAllParts: (): Promise<Response<Array<FilterOptionResp>>> => { listAllParts: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/parts"); return request('/pms/webProductMall/parts')
}, },
listAllModel: (): Promise<Response<Array<FilterOptionResp>>> => { listAllModel: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webDevice/model"); return request('/pms/webDevice/model')
}, },
listAllQuality: (): Promise<Response<Array<FilterOptionResp>>> => { listAllQuality: (): Promise<Response<Array<FilterOptionResp>>> => {
return request("/pms/webProductMall/quality"); return request('/pms/webProductMall/quality')
}, },
}; }
export interface SkillsType { export interface SkillsType {
name: string; name: string
type: string; type: string
id: number; id: number
skillsName: string; skillsName: string
licenseType:string licenseType: string
} }
export const flightSkillsApi = { export const flightSkillsApi = {
IndustryFlightSkills: (): Promise<Response<Array<SkillsType>>> => { IndustryFlightSkills: (): Promise<Response<Array<SkillsType>>> => {
return request("/release/curriculum/getIndustryFlightSkills"); return request('/release/curriculum/getIndustryFlightSkills')
}, },
InDronePilotLicense: (): Promise<Response<Array<SkillsType>>> => { InDronePilotLicense: (): Promise<Response<Array<SkillsType>>> => {
return request("/release/curriculum/getDronePilotLicense"); return request('/release/curriculum/getDronePilotLicense')
}, },
}; }
export interface NewsPageType { export interface NewsPageType {
id: number; id: number
newsTitle: string; newsTitle: string
newsAuthor: string; newsAuthor: string
userAccountId: number; userAccountId: number
surfaceImg: string; surfaceImg: string
newsContents: string; newsContents: string
createTime: string; createTime: string
updateTime: string | null; updateTime: string | null
} }
export interface NewsTenderType { export interface NewsTenderType {
id: number; id: number
tenderNewsId: number; tenderNewsId: number
tenderInfoNo: string; tenderInfoNo: string
tenderContent: string; tenderContent: string
tenderPrice: number; tenderPrice: number
createTime: string; createTime: string
apply: number; apply: number
} }
export interface ListPageNewsInfoResp { export interface ListPageNewsInfoResp {
pageNo: number; pageNo: number
pageSize: number; pageSize: number
list: Array<NewsPageType>; list: Array<NewsPageType>
totalCount: number; totalCount: number
totalPage: number; totalPage: number
} }
export interface ListTenderNewsInfoResp { export interface ListTenderNewsInfoResp {
pageNo: number; pageNo: number
pageSize: number; pageSize: number
list: Array<NewsTenderType>; list: Array<NewsTenderType>
totalCount: number; totalCount: number
totalPage: number; totalPage: number
} }
interface ListPageNewsInfoParams { interface ListPageNewsInfoParams {
pageNo: number; pageNo: number
pageSize: number; pageSize: number
cityCode?: number; cityCode?: number
date?: string; date?: string
districtCode?: number; districtCode?: number
provinceCode?: number; provinceCode?: number
} }
interface ListTenderNewsInfoParams { interface ListTenderNewsInfoParams {
pageNo: number; pageNo: number
pageSize: number; pageSize: number
cityCode?: number; cityCode?: number
date?: string; date?: string
districtCode?: number; districtCode?: number
provinceCode?: number; provinceCode?: number
} }
export interface TenderApplyType{ export interface TenderApplyType {
tenderInfoId: number, tenderInfoId: number
tenderNewsId: number, tenderNewsId: number
userAccountId: number userAccountId: number
} }
...@@ -185,16 +163,33 @@ export const listNewsApi = { ...@@ -185,16 +163,33 @@ export const listNewsApi = {
listNewsPage: ( listNewsPage: (
params: ListPageNewsInfoParams params: ListPageNewsInfoParams
): Promise<Response<ListPageNewsInfoResp>> => { ): Promise<Response<ListPageNewsInfoResp>> => {
return request("/release/industry-news/listNewsPage", "post", params); return request('/release/industry-news/listNewsPage', 'post', params)
}, },
//招标列表 //招标列表
listNewTenderInfo: ( listNewTenderInfo: (
params: ListTenderNewsInfoParams params: ListTenderNewsInfoParams
): Promise<Response<ListTenderNewsInfoResp>> => { ): Promise<Response<ListTenderNewsInfoResp>> => {
return request("/release/tender/listNewTenderInfo", "post", params); return request('/release/tender/listNewTenderInfo', 'post', params)
}, },
//web-招标-合作申请提交 //web-招标-合作申请提交
tenderApply: (params: TenderApplyType): Promise<Response<number>> => { tenderApply: (params: TenderApplyType): Promise<Response<number>> => {
return request('/release/tender/apply', 'post', params) return request('/release/tender/apply', 'post', params)
} },
}
export interface HomeCategoriesType {
type: 1 | 2 | 3 | 4
}
export interface ResHomeCategoriesType {
id: number
categoryName: string
}
export default {
//新闻列表
HomeCategories: (
params: HomeCategoriesType
): Promise<Response<ResHomeCategoriesType>> => {
return request('/pms/product/mall/getPageHomeCategories', 'get', params)
},
} }
import request, { Response } from "~/api/request"; import request, { Response } from '~/api/request'
export interface PositioningInfoParams { export interface PositioningInfoParams {
lat?: number; lat: number
lon?: number; lon: number
pageNo?:number, pageNo: number
pageSize?:number pageSize: number
} }
export interface Entiy { export interface Entiy {
dizhi: string; dizhi: string
jd: number; jd: number
wd: number; wd: number
range: number; range: number
} }
export interface ListPageJobInfoResp { export interface ListPageJobInfoType {
id: number; address: string
adCode: string; name: string
province: string; lon: number
locationList: Array<Entiy>; lat: number
distance: number
} }
export interface FlyerBitmapEntiy { export interface FlyerBitmapEntiy {
flyerName: string, flyerName: string
phoneNum: string, phoneNum: string
lon: number, lon: number
lat: number, lat: number
distance: number distance: number
} }
export interface UavBitmapEntiy { export interface UavBitmapEntiy {
uavName: string, uavName: string
online: number, online: number
lon: number, lon: number
lat: number, lat: number
distance: number, distance: number
id: string id: string
} }
export interface BitmapInfo<T> { export interface BitmapInfo<T> {
pageNo: number, pageNo: number
pageSize: number, pageSize: number
list: T[], list: T[]
totalCount: number, totalCount: number
totalPage: number totalPage: number
} }
...@@ -48,19 +49,25 @@ export default { ...@@ -48,19 +49,25 @@ export default {
//web-首页-地图-全国点位 //web-首页-地图-全国点位
listPositioningInfo: ( listPositioningInfo: (
params: PositioningInfoParams params: PositioningInfoParams
): Promise<Response<ListPageJobInfoResp[]>> => { ): Promise<Response<BitmapInfo<ListPageJobInfoType>>> => {
return request("/release/website/getWebsiteList", "get", params); return request('/release/website/getWebsiteList', 'get', params)
}, },
//web-首页-地图-全国飞手 //web-首页-地图-全国飞手
listFlyerBitmap: ( listFlyerBitmap: (
params: PositioningInfoParams params: PositioningInfoParams
): Promise<Response<BitmapInfo<FlyerBitmapEntiy>>> => { ): Promise<Response<BitmapInfo<FlyerBitmapEntiy>>> => {
return request("/release/website/flyer/bitmap", "get", params); return request('/release/website/flyer/bitmap', 'get', params)
}, },
//web-首页-地图-全国无人机 //web-首页-地图-全国无人机
listUavBitmap: ( listUavBitmap: (
params: PositioningInfoParams params: PositioningInfoParams
): Promise<Response<BitmapInfo<UavBitmapEntiy>>> => { ): Promise<Response<BitmapInfo<UavBitmapEntiy>>> => {
return request("/release/website/uav/bitmap", "get", params); return request('/release/website/uav/bitmap', 'get', params)
}, },
}; //web-首页-地图-全国维修-海点数据
listMaintainBitmap: (
params: PositioningInfoParams
): Promise<Response<BitmapInfo<ListPageJobInfoType>>> => {
return request('/release/website/maintain/bitmap', 'get', params)
},
}
import React, { Component, useEffect, useState } from "react"; import React, { Component, useEffect, useState } from 'react'
import { message } from 'antd'; import { message } from 'antd'
import { Box } from "./styled"; import { Box } from './styled'
import api from "./api"; import api from './api'
import icon from './assets/img.png' import icon from './assets/img.png'
import {useRouter} from 'next/router' import { useRouter } from 'next/router'
let MAP :any ; let MAP: any
let Amap:any; let Amap: any
interface UserInfoType { interface UserInfoType {
lat: number; lat: number
lon: number; lon: number
pageNo?:number, pageNo?: number
pageSize?:number pageSize?: number
} }
export default function MapComponent() { export default function MapComponent() {
const router = useRouter() const router = useRouter()
const [mapItem, setMapItem] = useState(0); const [mapItem, setMapItem] = useState(0)
const [userPositioning, setUserPositioning] = useState<UserInfoType>(); const [userPositioning, setUserPositioning] = useState<UserInfoType>()
const [markerCol, setMarkerCol] = useState<any>([]); const [markerCol, setMarkerCol] = useState<any>([])
//初始化地图 //初始化地图
const init = async () => { const init = async () => {
try { try {
const AMapLoader = await import( const AMapLoader = await import(
/* webpackChunkName: "amap" */ "@amap/amap-jsapi-loader" /* webpackChunkName: "amap" */ '@amap/amap-jsapi-loader'
); )
await AMapLoader.load({ await AMapLoader.load({
key: "87b424e68754efc3ba9d11ae07475091", // 申请好的Web端开发者Key,首次调用 load 时必填 key: '87b424e68754efc3ba9d11ae07475091', // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [""], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 plugins: [''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}) })
.then(async (AMap) => { .then(async (AMap) => {
Amap = AMap Amap = AMap
MAP = new AMap.Map("container", { MAP = new AMap.Map('container', {
// 设置地图容器id // 设置地图容器id
viewMode: "3D", // 是否为3D地图模式 viewMode: '3D', // 是否为3D地图模式
zoom: 9, // 初始化地图级别 zoom: 9, // 初始化地图级别
center: [113.93029, 22.53291], // 初始化地图中心点位置 center: [113.93029, 22.53291], // 初始化地图中心点位置
}); })
//用户定位 //用户定位
AMap.plugin('AMap.Geolocation', function() { AMap.plugin('AMap.Geolocation', function () {
const geolocation = new AMap.Geolocation({ const geolocation = new AMap.Geolocation({
enableHighAccuracy: true,//是否使用高精度定位,默认:true enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:5s timeout: 10000, //超过10秒后停止定位,默认:5s
position:'RB', //定位按钮的停靠位置 position: 'RB', //定位按钮的停靠位置
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20] offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点 zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
}); })
MAP.addControl(geolocation); MAP.addControl(geolocation)
geolocation.getCurrentPosition(function(status:string,result:any){ geolocation.getCurrentPosition(function (
if(status=='complete'){ status: string,
onComplete(result) result: any
}else{ ) {
onError(result) if (status == 'complete') {
} onComplete(result)
}); } else {
}); onError(result)
//解析定位结果 }
async function onComplete(data:any) { })
console.log('定位成功'); })
//解析定位结果
async function onComplete(data: any) {
console.log('定位成功')
setUserPositioning(data.position) setUserPositioning(data.position)
// return await mapEntiy(0,data.position); // return await mapEntiy(0,data.position);
} }
//解析定位错误信息 //解析定位错误信息
async function onError(data:any) { async function onError(data: any) {
// message.error(`定位失败 // message.error(`定位失败
// 失败原因排查信息:${data.message} // 失败原因排查信息:${data.message}
// 浏览器返回信息:${data.originMessage} // 浏览器返回信息:${data.originMessage}
// `) // `)
} }
await mapEntiy(0) await mapEntiy(0)
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.log(e)
}); })
} catch (error) { } catch (error) {
console.log(error); console.log(error)
} }
}; }
const showPositioningInfo = async (index:number,data?:UserInfoType) => { const showPositioningInfo = async (index: number, data?: UserInfoType) => {
const res = await api.listPositioningInfo({ const res = await api.listPositioningInfo({
lon: userPositioning?.lon || data?.lon || 113.93029, lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
}); pageNo: 1,
const list = res.result pageSize: 10,
?.map((item) => item.locationList) })
.flat() const list = res.result?.list
.filter((item: { dizhi: string }) => item.dizhi.includes("省")); const markerList: any = []
const markerList: any = [];
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.jd, item.wd, item.dizhi); const EntiyValue = addEntiy(item.lon, item.lat, item.name)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
if(markerList.length) MAP?.add(markerList);setMarkerCol([...markerList]); if (markerList.length) MAP?.add(markerList)
setMarkerCol([...markerList])
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
} }
const showFlyerBitmap = async (index:number,data?:UserInfoType,pageSize?:number) => { const showFlyerBitmap = async (
index: number,
data?: UserInfoType,
pageSize?: number
) => {
const res = await api.listFlyerBitmap({ const res = await api.listFlyerBitmap({
lon: userPositioning?.lon || data?.lon || 113.93029, lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
pageNo:1, pageNo: 1,
pageSize: pageSize || 40 pageSize: pageSize || 40,
}); })
const list = res.result?.list const list = res.result?.list
const markerList: any = []; const markerList: any = []
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.lon, item.lat, item.flyerName); const EntiyValue = addEntiy(item.lon, item.lat, item.flyerName)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
if(markerList.length) MAP?.add(markerList);setMarkerCol(markerList) if (markerList.length) MAP?.add(markerList)
setMarkerCol(markerList)
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
} }
const showUavBitmap = async (index:number,data?:UserInfoType) => { const showUavBitmap = async (index: number, data?: UserInfoType) => {
const res = await api.listUavBitmap({ const res = await api.listUavBitmap({
lon: userPositioning?.lon || data?.lon || 113.93029, lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
pageNo:1, pageNo: 1,
pageSize: 40 pageSize: 40,
}); })
const list = res.result?.list const list = res.result?.list
const markerList: any = []; const markerList: any = []
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.lon, item.lat, item.uavName); const EntiyValue = addEntiy(item.lon, item.lat, item.uavName)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
if(markerList.length) MAP?.add(markerList);setMarkerCol(markerList) if (markerList.length) MAP?.add(markerList)
setMarkerCol(markerList)
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
}
//添加点位
const mapEntiy = async (index: number, data?: UserInfoType) => {
MAP?.remove(markerCol)
if (index === 0) {
showPositioningInfo(index, data)
} else if (index === 1) {
showFlyerBitmap(index, data, 30)
} else if (index === 2) {
showUavBitmap(index, data)
} else {
router.push('/home/waterfallFlowBody/components/map/moreServicePoints')
}
setMapItem(index)
} }
//添加点位
const mapEntiy = async (index: number,data?:UserInfoType) => {
MAP?.remove(markerCol);
if (index === 0) {
showPositioningInfo(index,data)
}else if (index === 1) {
showFlyerBitmap(index,data,30)
} else if(index === 2) {
showUavBitmap(index,data)
}else{
router.push('/home/waterfallFlowBody/components/map/moreServicePoints')
}
setMapItem(index);
};
const addEntiy = ( lon: any, lat: any, name: string) => {
if (!Amap) return;
const icons = new Amap.Icon({
size: new Amap.Size(60, 60), // 图标尺寸
image: icon.src, // Icon的图像
imageSize: new Amap.Size(60, 60) // 根据所设置的大小拉伸或压缩图片
});
const marker = new Amap.Marker({
position: new Amap.LngLat(lon, lat),
offset: new Amap.Pixel(-10, -10),
icon: icons, // 添加 Icon 实例
title: name,
zoom: 13
});
return marker;
};
useEffect(() => {
(async () => {
await init();
})();
return MAP && MAP.destroy();
}, []);
const addEntiy = (lon: any, lat: any, name: string) => {
if (!Amap) return
const icons = new Amap.Icon({
size: new Amap.Size(60, 60), // 图标尺寸
image: icon.src, // Icon的图像
imageSize: new Amap.Size(60, 60), // 根据所设置的大小拉伸或压缩图片
})
const marker = new Amap.Marker({
position: new Amap.LngLat(lon, lat),
offset: new Amap.Pixel(-10, -10),
icon: icons, // 添加 Icon 实例
title: name,
zoom: 13,
})
return marker
}
useEffect(() => {
;(async () => {
await init()
})()
return MAP && MAP.destroy()
}, [])
return ( return (
<Box className="right-box-item"> <Box className="right-box-item">
<div id="container" className="map"></div> <div id="container" className="map"></div>
<div className="map-dosome"> <div className="map-dosome">
<div <div
className={`itemBox ${mapItem === 0 ? "active" : ""}`} className={`itemBox ${mapItem === 0 ? 'active' : ''}`}
onClick={() => mapEntiy(0)} onClick={() => mapEntiy(0)}
> >
服务网点 服务网点
</div> </div>
<div <div
className={`itemBox ${mapItem === 1 ? "active" : ""}`} className={`itemBox ${mapItem === 1 ? 'active' : ''}`}
onClick={() => mapEntiy(1)} onClick={() => mapEntiy(1)}
> >
租赁网点 租赁网点
</div> </div>
<div <div
className={`itemBox ${mapItem === 2 ? "active" : ""}`} className={`itemBox ${mapItem === 2 ? 'active' : ''}`}
onClick={() => mapEntiy(2)} onClick={() => mapEntiy(2)}
> >
培训网点 培训网点
</div> </div>
<div <div
className={`${mapItem === 3 ? "active" : ""}`} className={`${mapItem === 3 ? 'active' : ''}`}
onClick={() => mapEntiy(3)} onClick={() => mapEntiy(3)}
> >
更多网点 更多网点
</div> </div>
</div> </div>
</Box> </Box>
); )
} }
import React,{useState,useEffect} from 'react' import { message } from 'antd'
import Layout from "~/components/layout"; import { useEffect, useState } from 'react'
import {Box} from './styled' import Layout from '~/components/layout'
import api from "../api"; import api from '../api'
import icon from '../assets/img.png' import icon from '../assets/img.png'
import { message } from 'antd'; import { Box } from './styled'
let MAP :any ; let MAP: any
let Amap:any; let Amap: any
interface UserInfoType { interface UserInfoType {
lat: number; lat: number
lon: number; lon: number
pageNo?:number, pageNo?: number
pageSize?:number pageSize?: number
} }
export default function MoreServicePoints() { export default function MoreServicePoints() {
const [mapItem, setMapItem] = useState(0); const [mapItem, setMapItem] = useState(0)
const [userPositioning, setUserPositioning] = useState<UserInfoType>(); const [userPositioning, setUserPositioning] = useState<UserInfoType>()
const [markerCol, setMarkerCol] = useState<any>([]); const [markerCol, setMarkerCol] = useState<any>([])
const [servicePoints, setServicePoints] = useState<any>([]); const [servicePoints, setServicePoints] = useState<any>([])
//初始化地图 //初始化地图
const init = async () => { const init = async () => {
try { try {
const AMapLoader = await import( const AMapLoader = await import(
/* webpackChunkName: "amap" */ "@amap/amap-jsapi-loader" /* webpackChunkName: "amap" */ '@amap/amap-jsapi-loader'
); )
await AMapLoader.load({ await AMapLoader.load({
key: "87b424e68754efc3ba9d11ae07475091", // 申请好的Web端开发者Key,首次调用 load 时必填 key: '87b424e68754efc3ba9d11ae07475091', // 申请好的Web端开发者Key,首次调用 load 时必填
version: "2.0", // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [""], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 plugins: [''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}) })
.then(async (AMap) => { .then(async (AMap) => {
Amap = AMap; Amap = AMap
MAP = new AMap.Map("container", { MAP = new AMap.Map('container', {
// 设置地图容器id // 设置地图容器id
viewMode: "3D", // 是否为3D地图模式 viewMode: '3D', // 是否为3D地图模式
zoom: 9, // 初始化地图级别 zoom: 9, // 初始化地图级别
center: [113.93029, 22.53291], // 初始化地图中心点位置 center: [113.93029, 22.53291], // 初始化地图中心点位置
}); })
//用户定位 //用户定位
AMap.plugin("AMap.Geolocation", function () { AMap.plugin('AMap.Geolocation', function () {
const geolocation = new AMap.Geolocation({ const geolocation = new AMap.Geolocation({
enableHighAccuracy: true, //是否使用高精度定位,默认:true enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:5s timeout: 10000, //超过10秒后停止定位,默认:5s
position: "RB", //定位按钮的停靠位置 position: 'RB', //定位按钮的停靠位置
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20] offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点 zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
}); })
MAP.addControl(geolocation); MAP.addControl(geolocation)
geolocation.getCurrentPosition(function ( geolocation.getCurrentPosition(function (
status: string, status: string,
result: any result: any
) { ) {
console.log(result); console.log(result)
if (status == "complete") { if (status == 'complete') {
onComplete(result); onComplete(result)
} else { } else {
onError(result); onError(result)
} }
}); })
}); })
//解析定位结果 //解析定位结果
async function onComplete(data: any) { async function onComplete(data: any) {
console.log("定位成功"); console.log('定位成功')
setUserPositioning(data.position); setUserPositioning(data.position)
// return await mapEntiy(0,data.position); // return await mapEntiy(0,data.position);
} }
//解析定位错误信息 //解析定位错误信息
...@@ -74,37 +74,36 @@ export default function MoreServicePoints() { ...@@ -74,37 +74,36 @@ export default function MoreServicePoints() {
// 浏览器返回信息:${data.originMessage} // 浏览器返回信息:${data.originMessage}
// `) // `)
} }
await mapEntiy(0); await mapEntiy(0)
}) })
.catch((e) => { .catch((e) => {
console.log(e); console.log(e)
}); })
} catch (error) { } catch (error) {
console.log(error); console.log(error)
} }
}; }
const showPositioningInfo = async (index: number, data?: UserInfoType) => { const showPositioningInfo = async (index: number, data?: UserInfoType) => {
const res = await api.listPositioningInfo({ const res = await api.listPositioningInfo({
lon: userPositioning?.lon || data?.lon || 113.93029, lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
}); pageNo: 1,
const list = res.result pageSize: 10,
?.map((item) => item.locationList) })
.flat() const list = res.result?.list
.filter((item: { dizhi: string }) => item.dizhi.includes("省")); const markerList: any = []
const markerList: any = [];
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.jd, item.wd, item.dizhi); const EntiyValue = addEntiy(item.lon, item.lat, item.name)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
setServicePoints(list); setServicePoints(list)
if (markerList.length) MAP?.add(markerList); if (markerList.length) MAP?.add(markerList)
setMarkerCol([...markerList]); setMarkerCol([...markerList])
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
}; }
const showFlyerBitmap = async ( const showFlyerBitmap = async (
index: number, index: number,
data?: UserInfoType, data?: UserInfoType,
...@@ -115,99 +114,124 @@ export default function MoreServicePoints() { ...@@ -115,99 +114,124 @@ export default function MoreServicePoints() {
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
pageNo: 1, pageNo: 1,
pageSize: pageSize || 40, pageSize: pageSize || 40,
}); })
const list = res.result?.list; const list = res.result?.list
const markerList: any = []; const markerList: any = []
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.lon, item.lat, item.flyerName); const EntiyValue = addEntiy(item.lon, item.lat, item.flyerName)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
setServicePoints(list); setServicePoints(list)
if (markerList.length) MAP?.add(markerList); if (markerList.length) MAP?.add(markerList)
setMarkerCol(markerList); setMarkerCol(markerList)
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
}; }
const showMaintainBitmap = async (
index: number,
data?: UserInfoType,
pageSize?: number
) => {
const res = await api.listMaintainBitmap({
lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291,
pageNo: 1,
pageSize: pageSize || 40,
})
const list = res.result?.list
const markerList: any = []
if (list?.length) {
list?.map((item) => {
const EntiyValue = addEntiy(item.lon, item.lat, item.name)
markerList.push(EntiyValue)
})
setServicePoints(list)
if (markerList.length) MAP?.add(markerList)
setMarkerCol(markerList)
}
//自适应显示多个点位
MAP?.setFitView()
}
const showUavBitmap = async (index: number, data?: UserInfoType) => { const showUavBitmap = async (index: number, data?: UserInfoType) => {
const res = await api.listUavBitmap({ const res = await api.listUavBitmap({
lon: userPositioning?.lon || data?.lon || 113.93029, lon: userPositioning?.lon || data?.lon || 113.93029,
lat: userPositioning?.lat || data?.lat || 22.53291, lat: userPositioning?.lat || data?.lat || 22.53291,
pageNo: 1, pageNo: 1,
pageSize: 40, pageSize: 40,
}); })
const list = res.result?.list; const list = res.result?.list
const markerList: any = []; const markerList: any = []
if (list?.length) { if (list?.length) {
list?.map((item) => { list?.map((item) => {
const EntiyValue = addEntiy(item.lon, item.lat, item.uavName); const EntiyValue = addEntiy(item.lon, item.lat, item.uavName)
markerList.push(EntiyValue); markerList.push(EntiyValue)
}); })
setServicePoints(list); setServicePoints(list)
if (markerList.length) MAP?.add(markerList); if (markerList.length) MAP?.add(markerList)
setMarkerCol(markerList); setMarkerCol(markerList)
} }
//自适应显示多个点位 //自适应显示多个点位
MAP?.setFitView(); MAP?.setFitView()
}; }
//添加点位 //添加点位
const mapEntiy = async (index: number, data?: UserInfoType) => { const mapEntiy = async (index: number, data?: UserInfoType) => {
MAP?.remove(markerCol); MAP?.remove(markerCol)
if (userPositioning) { if (userPositioning) {
MAP?.setCenter([userPositioning.lon, userPositioning.lat]); MAP?.setCenter([userPositioning.lon, userPositioning.lat])
} }
if (index === 0) { if (index === 0) {
showPositioningInfo(index, data); showPositioningInfo(index, data)
} else if (index === 1) { } else if (index === 1) {
showFlyerBitmap(index, data, 30); showFlyerBitmap(index, data, 30)
} else if (index === 2) { } else if (index === 2) {
showUavBitmap(index, data); showUavBitmap(index, data)
} else { } else {
showFlyerBitmap(index, data, 30); showMaintainBitmap(index, data, 30)
} }
setMapItem(index); setMapItem(index)
}; }
const addEntiy = (lon: any, lat: any, name: string) => { const addEntiy = (lon: any, lat: any, name: string) => {
if (!Amap) return; if (!Amap) return
const icons = new Amap.Icon({ const icons = new Amap.Icon({
size: new Amap.Size(60, 60), // 图标尺寸 size: new Amap.Size(60, 60), // 图标尺寸
image: icon.src, // Icon的图像 image: icon.src, // Icon的图像
imageSize: new Amap.Size(60, 60), // 根据所设置的大小拉伸或压缩图片 imageSize: new Amap.Size(60, 60), // 根据所设置的大小拉伸或压缩图片
}); })
const marker = new Amap.Marker({ const marker = new Amap.Marker({
position: new Amap.LngLat(lon, lat), position: new Amap.LngLat(lon, lat),
offset: new Amap.Pixel(-10, -10), offset: new Amap.Pixel(-10, -10),
icon: icons, // 添加 Icon 实例 icon: icons, // 添加 Icon 实例
title: name, title: name,
zoom: 13, zoom: 13,
}); })
return marker; return marker
}; }
const moveTo = (item: any,index:number) => { const moveTo = (item: any, index: number) => {
// const p = markerCol[index].getPosition() const p = markerCol[index].getPosition()
// var infoWindow = new Amap.InfoWindow({ var infoWindow = new Amap.InfoWindow({
// position: p, position: p,
// offset: new Amap.Pixel(20, -10), offset: new Amap.Pixel(20, -10),
// content: item.dizhi content: item.dizhi || item.flyerName || item.uavName || item.name,
// }); })
// infoWindow.open(MAP); infoWindow.open(MAP)
if (item.dizhi) { if (item.dizhi) {
return MAP?.setCenter([item.jd, item.wd]); return MAP?.setCenter([item.jd, item.wd])
} else if (item.flyerName || item.uavName) { } else if (item.flyerName || item.uavName || item.name) {
return MAP?.setCenter([item.lon, item.lat]); return MAP?.setCenter([item.lon, item.lat])
} }
return message.warning("暂无位置信息"); return message.warning('暂无位置信息')
}; }
useEffect(() => { useEffect(() => {
(async () => { ;(async () => {
await init(); await init()
})(); })()
return MAP && MAP.destroy(); return MAP && MAP.destroy()
}, []); }, [])
return ( return (
<Layout> <Layout>
...@@ -215,41 +239,46 @@ export default function MoreServicePoints() { ...@@ -215,41 +239,46 @@ export default function MoreServicePoints() {
<div className="title"> <div className="title">
<div <div
onClick={() => mapEntiy(0)} onClick={() => mapEntiy(0)}
className={`item ${mapItem === 0 ? "active" : ""}`} className={`item ${mapItem === 0 ? 'active' : ''}`}
> >
服务网点 服务网点
</div> </div>
<div <div
onClick={() => mapEntiy(1)} onClick={() => mapEntiy(1)}
className={`item ${mapItem === 1 ? "active" : ""}`} className={`item ${mapItem === 1 ? 'active' : ''}`}
> >
培训网点 培训网点
</div> </div>
<div <div
onClick={() => mapEntiy(2)} onClick={() => mapEntiy(2)}
className={`item ${mapItem === 2 ? "active" : ""}`} className={`item ${mapItem === 2 ? 'active' : ''}`}
> >
租赁网点 租赁网点
</div> </div>
<div <div
onClick={() => mapEntiy(3)} onClick={() => mapEntiy(3)}
className={`item ${mapItem === 3 ? "active" : ""}`} className={`item ${mapItem === 3 ? 'active' : ''}`}
> >
机构网点 维修网点
</div> </div>
</div> </div>
<div className="content"> <div className="content">
<div className="left"> <div className="left">
<div className="left-title">服务网点</div> {mapItem === 0 && <div className="left-title">服务网点</div>}
{mapItem === 1 && <div className="left-title">培训网点</div>}
{mapItem === 2 && <div className="left-title">租赁网点</div>}
{mapItem === 3 && <div className="left-title">维修网点</div>}
<div className="left-content"> <div className="left-content">
{servicePoints.map((item: any,index:number) => ( {servicePoints.map((item: any, index: number) => (
<div <div
key={item.id} key={item.id}
onClick={() => moveTo(item,index)} onClick={() => moveTo(item, index)}
className="left-content-item" className="left-content-item"
title={item.dizhi || item.flyerName || item.uavName} title={
item.dizhi || item.flyerName || item.uavName || item.name
}
> >
{item.dizhi || item.flyerName || item.uavName} {item.dizhi || item.flyerName || item.uavName || item.name}
</div> </div>
))} ))}
</div> </div>
...@@ -260,5 +289,5 @@ export default function MoreServicePoints() { ...@@ -260,5 +289,5 @@ export default function MoreServicePoints() {
</div> </div>
</Box> </Box>
</Layout> </Layout>
); )
} }
import styled from "styled-components"; import styled from 'styled-components'
export default function Style() { export default function Style() {
return <></>; return <></>
} }
export const Box = styled.div` export const Box = styled.div`
...@@ -12,7 +12,7 @@ export const Box = styled.div` ...@@ -12,7 +12,7 @@ export const Box = styled.div`
position: relative; position: relative;
padding: 0px; padding: 0px;
margin: 0px; margin: 0px;
width: 384px; width: 100%;
height: 220px; height: 220px;
} }
...@@ -46,9 +46,4 @@ export const Box = styled.div` ...@@ -46,9 +46,4 @@ export const Box = styled.div`
color: #ff552d; color: #ff552d;
} }
} }
#container { `
padding: 0px;
margin: 0px;
width: 100%;
}
`;
import React, { useEffect, useState , useContext } from "react"; import { Select, Space, message } from 'antd'
import { Space, Select, Button, message } from "antd"; import { useRouter } from 'next/router'
import Image from "next/image"; import { useContext, useEffect, useState } from 'react'
import { useRouter } from "next/router"; import ContentBox from '~/components/contentBox'
import { Box } from "./styled"; import Map from './components/map'
import ContentBox from "~/components/contentBox"; import RotationChart from './components/rotationChart'
import RotationChart from "./components/rotationChart"; import { Box } from './styled'
import Map from "./components/map";
import { import { UserContext } from '~/lib/userProvider'
FilterOptionResp, import api, {
RegionResp,
AllType, AllType,
AppType,
IndustryType,
SkillsType,
NewsPageType, NewsPageType,
NewsTenderType, NewsTenderType,
equipmentLeasingApi, equipmentLeasingApi,
jobServicesApi,
mallApi,
flightSkillsApi, flightSkillsApi,
jobServicesApi,
listNewsApi, listNewsApi,
} from "./api"; mallApi,
import { BaseOptionType, DefaultOptionType } from "antd/es/select"; } from './api'
import { UserContext } from "~/lib/userProvider";
interface ColumnsType { interface ColumnsType {
title: string; title: string
router: string; router: string
} }
export default function WaterfallFlowBody() { export default function WaterfallFlowBody() {
const router = useRouter(); const router = useRouter()
const { userInfo, setNeedLogin } = useContext(UserContext); const { userInfo, setNeedLogin } = useContext(UserContext)
const [list, setList] = useState([ const [list, setList] = useState([
"中国人寿", '中国人寿',
"中国平安", '中国平安',
"中国人保", '中国人保',
"太平洋保险", '太平洋保险',
"新华保险", '新华保险',
"中国太平", '中国太平',
"泰康保险", '泰康保险',
"华夏保险", '华夏保险',
"阳光保险", '阳光保险',
"富德生命人寿", '富德生命人寿',
"中邮人寿", '中邮人寿',
"前海人寿", '前海人寿',
"百年人寿", '百年人寿',
"国华人寿", '国华人寿',
"工银安盛人寿", '工银安盛人寿',
"恒大人寿", '恒大人寿',
"君康人寿", '君康人寿',
"友邦保险", '友邦保险',
"建信人寿", '建信人寿',
"大家人寿", '大家人寿',
"农银人寿", '农银人寿',
"中信保城人寿", '中信保城人寿',
"合众人寿", '合众人寿',
]); ])
const [list2, setList2] = useState([ const [list2, setList2] = useState([
"天目将PAAS平台", '天目将PAAS平台',
"天目将公安平台", '天目将公安平台',
"天目将应急平台", '天目将应急平台',
"天目将城管平台", '天目将城管平台',
"天目将电力平台", '天目将电力平台',
"天目将石油平台", '天目将石油平台',
"SESP-U1无人机仿真软件", 'SESP-U1无人机仿真软件',
"云享飞服务号", '云享飞服务号',
"无人机商城", '无人机商城',
"云飞手", '云飞手',
"云仓", '云仓',
"云享飞", '云享飞',
"科比特智教", '科比特智教',
]); ])
const columns = [ const columns = [
{ {
title: "无人机出租", title: '无人机出租',
router: "/equipmentLeasing", router: '/equipmentLeasing',
}, },
{ {
title: "无人机销售", title: '无人机销售',
router: "/mall", router: '/mall',
}, },
{ {
title: "无人机保险", title: '无人机保险',
router: "", router: '',
}, },
{ {
title: "无人机培训", title: '无人机培训',
router: "flyingHandService", router: 'flyingHandService',
}, },
{ {
title: "无人机服务", title: '无人机服务',
router: "/jobServices", router: '/jobServices',
}, },
{ {
title: "无人机工具软件", title: '无人机工具软件',
router: "", router: '',
}, },
]; ]
const [leftDomList, setLeftDomList] = useState( const [leftDomList, setLeftDomList] = useState(
Array<{ element: JSX.Element; type?: string }> Array<{ element: JSX.Element; type?: string }>
); )
const [rightTopDomList, setRightTopDomList] = useState<JSX.Element>(); const [rightTopDomList, setRightTopDomList] = useState<JSX.Element>()
const [rightBottomDomList, setRightBottomDomList] = useState<JSX.Element>(); const [rightBottomDomList, setRightBottomDomList] = useState<JSX.Element>()
const { deviceBrand , deviceCategory, deviceModel } = equipmentLeasingApi; // const { deviceBrand, deviceModel } = equipmentLeasingApi
const eqApiTypeList = ["brandId", "categoryId", "modelId"]; // const eqApiTypeList = ['brandId', 'categoryId', 'modelId']
const { listAllModel , listAllBrand , listAllCategory, listAllParts, listAllQuality } = mallApi; // const {
const mallApiTypeList = [ // listAllModel,
"brandId", // listAllBrand,
"productCategoryId", // listAllCategory,
"partsId", // listAllParts,
"modelId", // listAllQuality,
"qualityId", // } = mallApi
]; // const mallApiTypeList = [
const { IndustryFlightSkills , InDronePilotLicense} = flightSkillsApi; // 'brandId',
const flightApiTypeList = ["licenseId", "flightSkillsId"]; // 'productCategoryId',
// 'partsId',
// 'modelId',
// 'qualityId',
// ]
// const { IndustryFlightSkills, InDronePilotLicense } = flightSkillsApi
// const flightApiTypeList = ['licenseId', 'flightSkillsId']
const { listAllIndustry, listAllAppType } = jobServicesApi; // const { listAllIndustry, listAllAppType } = jobServicesApi
const jobApiTypeList = ["industryId", "appTypeId"]; // const jobApiTypeList = ['industryId', 'appTypeId']
const onMoreChange = ( const onMoreChange = (
value: { value: string; label: number }, value: { value: string; label: number },
index: number, index: number,
option: [] option: []
) => { ) => {
const [item] = option.filter((item: any) => item.name === value.value); const [item] = option.filter((item: any) => item.name === value.value)
routerPath(index, item); routerPath(index, item)
}; }
useEffect(() => { // useEffect(() => {
(async () => { // ;(async () => {
let res1 = await Promise.all([ // let res1 = await Promise.all([deviceBrand(), deviceModel()])
deviceBrand(), // let res2 = await Promise.all([listAllBrand(), listAllCategory(), listAllParts(), listAllModel(), listAllQuality()])
deviceCategory(), // let res3 = await Promise.all([IndustryFlightSkills(), InDronePilotLicense()])
deviceModel(), // let res4 = await Promise.all([listAllIndustry(), listAllAppType()])
]); // // let res4 = await Promise.all([deviceCategory(),deviceBrand(),deviceModel()])
let res2 = await Promise.all([ // // let res6 = await Promise.all([deviceCategory(),deviceBrand(),deviceModel()])
listAllBrand(),
listAllCategory(),
listAllParts(),
listAllModel(),
listAllQuality(),
]);
let res3 = await Promise.all([IndustryFlightSkills(),InDronePilotLicense()]);
let res4 = await Promise.all([listAllIndustry(), listAllAppType()]);
// let res4 = await Promise.all([deviceCategory(),deviceBrand(),deviceModel()])
// let res6 = await Promise.all([deviceCategory(),deviceBrand(),deviceModel()])
const resValuelist1 = res1
.map((item, index) => {
if (item.code === "200") {
return item.result?.map((it) => {
it.type = eqApiTypeList[index];
return it;
});
}
return {}
})
.flat();
const resValuelist2 = res2
.map((item, index) => {
if (item.code === "200") {
return item.result?.map((it) => {
it.type = mallApiTypeList[index];
return it;
});
}
return {}
})
.flat();
const resValuelist3 = res3
.map((item, index) => {
if (item.code === "200") {
return item.result?.map((it) => {
it.type = flightApiTypeList[index];
it.name = it.name || it.skillsName || it.licenseType;
return it;
});
}
return {}
})
.flat();
const resValuelist4 = res4
.map((item, index) => {
if (item.code === "200") {
return item.result?.map((it) => {
it.type = jobApiTypeList[index];
it.name = it.name || it.appName;
return it;
});
}
return {}
})
.flat();
let res7 = await listNewsApi.listNewsPage({ pageNo: 1, pageSize: 5 }); // const resValuelist1 = res1
let res8 = await listNewsApi.listNewTenderInfo({ // .map((item, index) => {
pageNo: 1, // if (item.code === '200') {
pageSize: 6, // return item.result?.map(it => {
}); // it.type = eqApiTypeList[index]
const listValue: any = [ // return it
resValuelist1, // })
resValuelist2, // }
[], // return {}
resValuelist3, // })
resValuelist4, // .flat()
[],
]; // const resValuelist2 = res2
// .map((item, index) => {
// if (item.code === '200') {
// return item.result?.map(it => {
// it.type = mallApiTypeList[index]
// return it
// })
// }
// return {}
// })
// .flat()
// const resValuelist3 = res3
// .map((item, index) => {
// if (item.code === '200') {
// return item.result?.map(it => {
// it.type = flightApiTypeList[index]
// it.name = it.name || it.skillsName || it.licenseType
// return it
// })
// }
// return {}
// })
// .flat()
// const resValuelist4 = res4
// .map((item, index) => {
// if (item.code === '200') {
// return item.result?.map(it => {
// it.type = jobApiTypeList[index]
// it.name = it.name || it.appName
// return it
// })
// }
// return {}
// })
// .flat()
// let res7 = await listNewsApi.listNewsPage({ pageNo: 1, pageSize: 5 })
// let res8 = await listNewsApi.listNewTenderInfo({
// pageNo: 1,
// pageSize: 6
// })
// const listValue: any = [resValuelist1, resValuelist2, [], resValuelist3, resValuelist4, []]
// const listOption = JSON.parse(JSON.stringify(list)).map((item: string, index: number) => {
// return { id: index, name: item, value: index }
// })
// const list2Option = JSON.parse(JSON.stringify(list2)).map((item: string, index: number) => {
// return { id: index, name: item, value: index }
// })
// const optionList = [resValuelist1, resValuelist2, listOption, resValuelist3, resValuelist4, list2Option]
// setLeftDomList(
// columns.map((item, index) => {
// if (index < 3) {
// return {
// element: leftDom(item, index, listValue, optionList[index]),
// type: 'left'
// }
// }
// return {
// element: leftDom(item, index, listValue, optionList[index]),
// type: 'right'
// }
// })
// )
// setRightTopDomList(rightDom(res7.result?.list!))
// setRightBottomDomList(rightDom2(res8.result?.list!))
// })()
// }, [])
useEffect(() => {
;(async () => {
const res2 = await api.HomeCategories({ type: 2 }) //无人机培训
const res4 = await api.HomeCategories({ type: 4 }) //无人机销售
const res1 = await api.HomeCategories({ type: 1 }) //无人机出租
const res3 = await api.HomeCategories({ type: 3 }) //无人机服务
console.log(res1, res2, res3, res4)
const listOption = JSON.parse(JSON.stringify(list)).map( const listOption = JSON.parse(JSON.stringify(list)).map(
(item: string, index: number) => { (item: string, index: number) => {
return { id: index, name: item, value: index }; return { id: index, categoryName: item, value: index }
} }
); )
const list2Option = JSON.parse(JSON.stringify(list2)).map( const list2Option = JSON.parse(JSON.stringify(list2)).map(
(item: string, index: number) => { (item: string, index: number) => {
return { id: index, name: item, value: index }; return { id: index, categoryName: item, value: index }
} }
); )
const optionList = [ const optionList = [
resValuelist1, res2.result,
resValuelist2, res4.result,
listOption, listOption,
resValuelist3, res3.result,
resValuelist4, res1.result,
list2Option, list2Option,
]; ]
const listValue: any = [
res2.result,
res4.result,
[],
res3.result,
res1.result,
[],
]
setLeftDomList( setLeftDomList(
columns.map((item, index) => { columns.map((item, index) => {
if (index < 3) { if (index < 3) {
return { return {
element: leftDom(item, index, listValue, optionList[index]), element: leftDom(item, index, listValue, optionList[index]),
type: "left", type: 'left',
}; }
} }
return { return {
element: leftDom(item, index, listValue, optionList[index]), element: leftDom(item, index, listValue, optionList[index]),
type: "right", type: 'right',
}; }
}) })
); )
let res7 = await listNewsApi.listNewsPage({ pageNo: 1, pageSize: 5 })
setRightTopDomList(rightDom(res7.result?.list!)); let res8 = await listNewsApi.listNewTenderInfo({
setRightBottomDomList(rightDom2(res8.result?.list!)); pageNo: 1,
})(); pageSize: 6,
}, []); })
setRightTopDomList(rightDom(res7.result?.list!))
setRightBottomDomList(rightDom2(res8.result?.list!))
})()
}, [])
const routerPath = (index: number, item?: AllType) => { const routerPath = (index: number, item?: AllType) => {
if ( item && (index === 0 || index === 1 || index === 3 || index === 4) ) { if (item && (index === 0 || index === 1 || index === 3 || index === 4)) {
router.push({ router.push({
pathname: columns[index].router, pathname: columns[index].router,
query: { [item?.type!]: item?.id! , name: item?.name || item?.appName || item?.skillsName }, query: {
}); categoryId: item.id,
}else{ name: item.categoryName,
},
})
} else {
router.push({ router.push({
pathname: columns[index].router, pathname: columns[index].router,
}); })
} }
}; }
const handleTenderApply = async (item:NewsTenderType)=>{ const handleTenderApply = async (item: NewsTenderType) => {
if (item.apply) return; if (item.apply) return
if (userInfo) { if (userInfo) {
let res = await listNewsApi.tenderApply({ let res = await listNewsApi.tenderApply({
tenderInfoId: item.id, tenderInfoId: item.id,
tenderNewsId: item.tenderNewsId, tenderNewsId: item.tenderNewsId,
userAccountId: userInfo.id, userAccountId: userInfo.id,
})
try {
if (res.code === '200') {
message.success('申请成功')
let res8 = await listNewsApi.listNewTenderInfo({
pageNo: 1,
pageSize: 6,
}) })
try{ setRightBottomDomList(rightDom2(res8.result?.list!))
if (res.code==="200") { } else {
message.success("申请成功")
let res8 = await listNewsApi.listNewTenderInfo({
pageNo: 1,
pageSize: 6,
});
setRightBottomDomList(rightDom2(res8.result?.list!));
}else{
message.error(res.message) message.error(res.message)
} }
}catch(e){ } catch (e) {
console.log(e); console.log(e)
} }
}else{ } else {
setNeedLogin(true) setNeedLogin(true)
} }
} }
...@@ -319,8 +350,8 @@ export default function WaterfallFlowBody() { ...@@ -319,8 +350,8 @@ export default function WaterfallFlowBody() {
dropdownMatchSelectWidth={false} dropdownMatchSelectWidth={false}
options={option} options={option}
fieldNames={{ fieldNames={{
value: "name", value: 'categoryName',
label: "name", label: 'categoryName',
}} }}
/> />
</div> </div>
...@@ -332,7 +363,7 @@ export default function WaterfallFlowBody() { ...@@ -332,7 +363,7 @@ export default function WaterfallFlowBody() {
<div <div
key={item} key={item}
className={`item-bubble ${ className={`item-bubble ${
index === 0 || index === 1 || index === 2 ? "active" : "" index === 0 || index === 1 || index === 2 ? 'active' : ''
}`} }`}
> >
{item} {item}
...@@ -343,7 +374,7 @@ export default function WaterfallFlowBody() { ...@@ -343,7 +374,7 @@ export default function WaterfallFlowBody() {
<div <div
key={item} key={item}
className={`item-bubble ${ className={`item-bubble ${
index === 0 || index === 1 || index === 2 ? "active" : "" index === 0 || index === 1 || index === 2 ? 'active' : ''
}`} }`}
> >
{item} {item}
...@@ -352,43 +383,47 @@ export default function WaterfallFlowBody() { ...@@ -352,43 +383,47 @@ export default function WaterfallFlowBody() {
: resultList[index].map((item, indexer) => { : resultList[index].map((item, indexer) => {
return ( return (
<div <div
key={item?.name || item?.appName || item?.skillsName} key={item.categoryName}
className={`item-bubble ${ className={`item-bubble ${
indexer === 0 || indexer === 1 || indexer === 2 indexer === 0 || indexer === 1 || indexer === 2
? "active" ? 'active'
: "" : ''
}`} }`}
onClick={() => routerPath(index, item)} onClick={() => routerPath(index, item)}
> >
{item?.name || item?.appName || item?.skillsName} {item.categoryName}
</div> </div>
); )
})} })}
</Space> </Space>
</div> </div>
</div> </div>
); )
}; }
const rightDom = (list: Array<NewsPageType>) => { const rightDom = (list: Array<NewsPageType>) => {
if(!list?.length) return; if (!list?.length) return
return ( return (
<div key={1009} className="right-box-item right-item"> <div key={1009} className="right-box-item right-item">
<div className="title"> <div className="title">
<div <div
className="title-label" className="title-label"
onClick={() => router.push("/projectInfo")} onClick={() => router.push('/projectInfo')}
> >
行业新闻 行业新闻
</div> </div>
</div> </div>
<div className="body"> <div className="body">
{list?.map((item, index) => ( {list?.map((item, index) => (
<div key={item.id} className="body-item" onClick={()=>router.push(`/projectInfo/newsArticle/${item.id}`)}> <div
key={item.id}
className="body-item"
onClick={() => router.push(`/projectInfo/newsArticle/${item.id}`)}
>
<div <div
className={`item-ranking ${index === 0 ? "one" : ""} ${ className={`item-ranking ${index === 0 ? 'one' : ''} ${
index === 1 ? "two" : "" index === 1 ? 'two' : ''
} ${index === 2 ? "san" : ""}`} } ${index === 2 ? 'san' : ''}`}
> >
{index + 1} {index + 1}
</div> </div>
...@@ -399,18 +434,18 @@ export default function WaterfallFlowBody() { ...@@ -399,18 +434,18 @@ export default function WaterfallFlowBody() {
))} ))}
</div> </div>
</div> </div>
); )
}; }
const rightDom2 = (list: Array<NewsTenderType>) => { const rightDom2 = (list: Array<NewsTenderType>) => {
if(!list?.length) return; if (!list?.length) return
return ( return (
<div key={1008} className="right-box-item right-item-second"> <div key={1008} className="right-box-item right-item-second">
<div className="item-box"> <div className="item-box">
<div className="title"> <div className="title">
<div <div
className="title-label" className="title-label"
onClick={() => router.push("/projectInfo")} onClick={() => router.push('/projectInfo')}
> >
招标快讯 招标快讯
</div> </div>
...@@ -422,28 +457,34 @@ export default function WaterfallFlowBody() { ...@@ -422,28 +457,34 @@ export default function WaterfallFlowBody() {
{item.tenderContent} {item.tenderContent}
<div className="label-bottom">{item.tenderPrice}</div> <div className="label-bottom">{item.tenderPrice}</div>
</div> </div>
<div className={`item-right ${item.apply ? 'apply' : ''}`} onClick={()=>handleTenderApply(item)}> <div
<div className="left">{`${item.tenderPrice}W`}</div> className={`item-right ${item.apply ? 'apply' : ''}`}
{ onClick={() => handleTenderApply(item)}
item.apply ? <div className="right">已申请</div> : <> >
<div className="right">申请合作</div></> <div className="left">{`${item.tenderPrice}W`}</div>
} {item.apply ? (
<div className="right">已申请</div>
) : (
<>
<div className="right">申请合作</div>
</>
)}
</div> </div>
</div> </div>
))} ))}
</div> </div>
</div> </div>
</div> </div>
); )
}; }
return ( return (
<Box> <Box>
<ContentBox <ContentBox
boxIndex={1} //分为左右两列,每列一个,从上而下 boxIndex={1} //分为左右两列,每列一个,从上而下
leftcontentstyle={{ leftcontentstyle={{
width: "806px", width: '806px',
margin: { top: 0, right: "10px", bottom: "10px", left: 0 }, margin: { top: 0, right: '10px', bottom: '10px', left: 0 },
}} }}
leftWaterfallDom={{ leftWaterfallDom={{
columns: [ columns: [
...@@ -459,7 +500,6 @@ export default function WaterfallFlowBody() { ...@@ -459,7 +500,6 @@ export default function WaterfallFlowBody() {
], ],
}} }}
/> />
</Box> </Box>
); )
} }
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
export interface ListPageJobInfoParams { export interface ListPageJobInfoParams {
pageNo:number, pageNo: number
pageSize:number, pageSize: number
appTypeId?:number, appTypeId?: number
industryId?:number, industryId?: number
inspectionName?:string, inspectionName?: string
string?:number, string?: number
regionId?:number, regionId?: number
} }
export interface Job { export interface Job {
id:number, id: number
serviceName:string, serviceName: string
teamName:string, teamName: string
price:number, price: number
} }
export interface ListPageJobInfoResp { export interface ListPageJobInfoResp {
pageNo: 1, pageNo: 1
pageSize: 10, pageSize: 10
list: Array<Job>, list: Array<Job>
totalCount: 0, totalCount: 0
totalPage: 0 totalPage: 0
} }
export default { export default {
//web-作业服务-分页 //web-作业服务-分页
listPageJobServicesInfo: (params: ListPageJobInfoParams,option:{}): Promise<Response<ListPageJobInfoResp>> => { listPageJobServicesInfo: (
return request('/release/work/queryTaskServiceList', 'post', params,option) params: ListPageJobInfoParams,
option: {}
): Promise<Response<ListPageJobInfoResp>> => {
return request(
'/pms/backstage/work/queryWorkServiceList',
'post',
params,
option
)
}, },
} }
\ No newline at end of file
import React,{useEffect, useState} from 'react' import React, { useEffect, useState } from 'react'
import Layout from "~/components/layout"; import Layout from '~/components/layout'
import {Box} from './styled'; import { Box } from './styled'
import { Tabs , Button } from 'antd'; import moment from 'moment'
import type { TabsProps } from 'antd'; import {
import Evaluate from './components/evaluate'; Tabs,
import { useRouter } from "next/router"; Modal,
import api , {ListPageJobInfoResp} from './api'; Button,
import Image from 'next/image'; Form,
message,
DatePicker,
Image as AImage,
Input,
Cascader,
} from 'antd'
import { RangePickerProps } from 'antd/es/date-picker'
import type { TabsProps } from 'antd'
import Evaluate from './components/evaluate'
import { useRouter } from 'next/router'
import api, { ListPageJobInfoResp } from './api'
import Image from 'next/image'
import { RegionResp } from '~/components/filter/api'
import AddressMap from './components/map'
const { RangePicker } = DatePicker
const { TextArea } = Input
export default function JobServicesDetail() { export default function JobServicesDetail() {
const router = useRouter(); const router = useRouter()
const [id, setId] = useState<number | null>(null)
const [id, setId] = useState<number | null>(null); const [detail, setDetail] = useState<ListPageJobInfoResp | null>()
const [sale, setSale] = useState<string | null>()
const [detail,setDetail] = useState<ListPageJobInfoResp | null>()
const [sale,setSale] = useState<string | null>()
const onChange = (key: string) => { const onChange = (key: string) => {
console.log(key); console.log(key)
}; }
const items: TabsProps['items'] = [ const items: TabsProps['items'] = [
{ {
key: '1', key: '1',
label: `团队介绍`, label: `团队介绍`,
children: <div className='teamIntroduction'> children: (
{/* <Image width={1100} height={800} src={detail?.teamPoster ? detail?.teamPoster : ''} alt='error'/> */} <div className="teamIntroduction">
<img style={{width:"100%"}} src={detail?.teamPoster ? detail?.teamPoster : ''} alt="error" /> {/* <Image width={1100} height={800} src={detail?.teamPoster ? detail?.teamPoster : ''} alt='error'/> */}
</div>, {/* <img
style={{ width: '100%' }}
src={detail?.teamPoster ? detail?.teamPoster : ''}
alt="error"
/> */}
{detail?.serviceIntroduction ? (
<div
dangerouslySetInnerHTML={{ __html: detail?.serviceIntroduction }}
></div>
) : null}
</div>
),
}, },
{ {
key: '2', key: '2',
label: `团队评价`, label: `团队评价`,
children: <Evaluate evaluateInfo={detail?.evaluateInfo || []}/>, children: <Evaluate evaluateInfo={detail?.inspComtList || []} />,
}, },
]; ]
useEffect(()=>{ useEffect(() => {
setId(Number(router.query.id)) setId(Number(router.query.id))
},[router]) }, [router])
useEffect(() => { useEffect(() => {
if (id) { if (id) {
api api.listDetailJobServicesInfo({ id }).then((res) => {
.listDetailJobServicesInfo({id}) setDetail(res.result || null)
.then((res) => { })
setDetail(res.result || null);
});
} }
}, [id]); }, [id])
useEffect(()=>{ useEffect(() => {
setSale((Math.floor(Math.random() * 901) + 100).toFixed(0)) setSale((Math.floor(Math.random() * 901) + 100).toFixed(0))
},[]) }, [])
//预约弹框
const [visible, setVisible] = useState(false)
const [formDate] = Form.useForm()
const [isModalOpen, setIsModalOpen] = useState(false)
const [loading, setLoading] = useState(false)
const [provinceList, setProvinceList] = useState<RegionResp[]>([])
const [isAddressMapShow, setIsAddressMapShow] = useState(false)
const [addressContent, setAddressContent] = useState<any>()
useEffect(() => {
api.region().then((res) => {
console.log(res)
console.log(res?.result?.map((item) => item.childInfo).flat())
setProvinceList(res?.result || [])
})
}, [])
const disabledDate: RangePickerProps['disabledDate'] = (current) => {
return current && current < moment().endOf('day')
}
useEffect(() => {
//选择地点后重新验证
formDate.setFieldValue('latitudeAndLongitude', addressContent)
formDate.validateFields()
}, [addressContent])
const handleOk = () => {
setLoading(true)
formDate
.validateFields()
.then(async (values) => {
console.log(values)
if (!addressContent) {
return message.warning('请选择地点')
}
const res = await api.insertOrderTask({
address: addressContent.addressDteail,
taskDescription: values.taskDescription,
city: addressContent.city,
inspectionId: detail?.id || 1,
lat: addressContent.lat,
lon: addressContent.lon,
province: addressContent.province,
startTime: moment(new Date(values.dateDetail[0])).format(
'YYYY-MM-DD HH:MM:SS'
),
endTime: moment(new Date(values.dateDetail[1])).format(
'YYYY-MM-DD HH:MM:SS'
),
})
console.log(res)
if (res.code === '200') {
message.success('提交成功')
formDate.resetFields()
setAddressContent(undefined)
setLoading(false)
setIsModalOpen(false)
} else {
message.error(res.message)
setLoading(false)
}
})
.catch((err) => {
message
.warning({
content: err.errorFields[0].errors[0],
})
.then()
setLoading(false)
})
}
const handleCancel = () => {
setAddressContent(undefined)
setIsModalOpen(false)
formDate.resetFields()
}
return ( return (
<Layout> <Layout>
<Box> <Box>
<div className='top'> <div className="top">
<div className="top-image"> <div className="top-image">
<Image fill src={detail?.pictureUrl ? detail?.pictureUrl : ''} alt='error'/> <Image
fill
src={detail?.coverPlan ? detail?.coverPlan : ''}
alt="error"
/>
</div> </div>
<div className='top-right'> <div className="top-right">
<div className='right-top'> <div className="right-top">
<div className='title'> <div className="title">{detail?.serviceName}</div>
{detail?.serviceName} <div className="detail">
</div> <div className="tab">专业飞手</div>
<div className='detail'> <span className="content">飞手需通过认证培训才可作业</span>
<div className='tab'>专业飞手</div>
<span className='content'>飞手需通过认证培训才可作业</span>
</div>
<div className='more'>
<div className='tab filst'>测绘场景榜第1名</div>
<div className='tab'>7x24小时服务</div>
<div className='tab'>{`月售${sale}`}</div>
</div>
</div> </div>
<div className='right-bottom'> <div className="more">
<div className='bottom-btn'> <div className="tab filst">测绘场景榜第1名</div>
<Button className='btn-left' size='small' type="primary">电话沟通</Button> <div className="tab">7x24小时服务</div>
<Button className='btn-right' size='small' type="primary">立即预约</Button> <div className="tab">{`月售${sale}`}</div>
</div> </div>
</div>
<div className="right-bottom">
<div className="bottom-btn">
<Button className="btn-left" size="small" type="primary">
电话沟通
</Button>
<Button
onClick={() => setIsModalOpen(true)}
className="btn-right"
size="small"
type="primary"
>
立即预约
</Button>
</div> </div>
</div>
</div> </div>
</div> </div>
<Tabs className='tabs' defaultActiveKey="1" items={items} onChange={onChange} /> <Tabs
className="tabs"
defaultActiveKey="1"
items={items}
onChange={onChange}
/>
<Modal
wrapClassName="reservation"
open={isModalOpen}
onOk={handleOk}
onCancel={handleCancel}
getContainer={false}
maskClosable={false}
width={420}
footer={[
<Button
style={{ width: '100%', height: 44 }}
key="submit"
type="primary"
loading={loading}
onClick={handleOk}
>
立即预约
</Button>,
]}
>
<div className="title">
<div className="left">
<AImage
preview={{ visible: false }}
src={detail?.coverPlan ? detail?.coverPlan : ''}
onClick={() => setVisible(true)}
style={{ width: 58, height: 58 }}
/>
<div style={{ display: 'none' }}>
<AImage.PreviewGroup
preview={{
visible,
onVisibleChange: (vis) => setVisible(vis),
}}
>
<AImage src={detail?.coverPlan ? detail?.coverPlan : ''} />
</AImage.PreviewGroup>
</div>
</div>
<div className="right">{detail?.serviceName}</div>
</div>
<Form
form={formDate}
layout="vertical"
name="reservationForm"
initialValues={{ modifier: 'public' }}
className="form-data"
>
<Form.Item
label="选择日期"
style={{ flex: 1, marginRight: 16 }}
name="dateDetail"
rules={[{ required: true, message: '请选择日期' }]}
>
<RangePicker
style={{ width: 376, marginTop: 10 }}
disabledDate={disabledDate}
/>
</Form.Item>
<Form.Item
label="选择地点"
style={{ flex: 1, marginRight: 16 }}
name="latitudeAndLongitude"
rules={[{ required: true, message: '请选择地点' }]}
>
{addressContent ? (
<div className="address-map">
<div className="value">
已选择:{addressContent.addressDteail}
</div>
<Button
onClick={() => setIsAddressMapShow(true)}
type="primary"
>
修改位置
</Button>
</div>
) : (
<Button onClick={() => setIsAddressMapShow(true)} type="text">
点击从地图选择地点
</Button>
)}
</Form.Item>
<div>
任务描述(选填) 项目号、 业务负责人、
客户名称、演示设备(注明飞机、挂载、地面站)、现场联系人及电话
</div>
<Form.Item
style={{ flex: 1, marginRight: 16 }}
name="taskDescription"
>
<TextArea
placeholder="补充描述有助于方案沟通更高效哦~"
autoSize={{ minRows: 3, maxRows: 5 }}
style={{ width: 385, height: 72 }}
/>
</Form.Item>
</Form>
</Modal>
{isAddressMapShow ? (
<Modal
wrapClassName="reservation"
open={isAddressMapShow}
onCancel={() => setIsAddressMapShow(false)}
getContainer={false}
maskClosable={false}
width={850}
footer={false}
>
<div style={{ textAlign: 'center', fontWeight: '700' }}>
选择地点
</div>
<AddressMap
setAddressContent={setAddressContent}
setIsAddressMapShow={setIsAddressMapShow}
/>
</Modal>
) : null}
</Box> </Box>
</Layout> </Layout>
) )
......
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
import { RegionResp } from '~/components/filter/api'
export interface ListPageJobInfoParams { export interface ListPageJobInfoParams {
pageNo:number, pageNo: number
pageSize:number, pageSize: number
appTypeId?:number, appTypeId?: number
industryId?:number, industryId?: number
inspectionName?:string, inspectionName?: string
string?:number, string?: number
regionId?:number, regionId?: number
} }
export interface JobDetail { export interface JobDetail {
id?: number, id?: number
content?: string, content?: string
contentImgs?: string[] | null, contentImgs?: string[] | null
contentVideo?: string | null, contentVideo?: string | null
star?: number, star?: number
img?: string | null, img?: string | null
type?: number, type?: number
name?:string, name?: string
time?:number | string time?: number | string
} }
export interface ListPageJobInfoResp { export interface ListPageJobInfoResp {
id: number, id: number
serviceName: string, serviceName: string
pictureUrl: string, pictureUrl: string
videoUrl: string, videoUrl: string
teamPoster:string, teamPoster: string
evaluateInfo:Array<JobDetail>, evaluateInfo: Array<JobDetail>
item:number item: number
coverPlan: string
serviceIntroduction: string
inspComtList: []
} }
export interface GetJobServicesDetailParams { export interface GetJobServicesDetailParams {
id: number id: number
} }
export interface GetOrderTaskParams {
address: string
city: string
endTime: string
images?: []
inspectionId: number
lat: number
lon: number
province: string
startTime: string
taskDescription?: string
}
export default { export default {
//web-作业服务-详情 //web-作业服务-详情
listDetailJobServicesInfo: (params:GetJobServicesDetailParams): Promise<Response<ListPageJobInfoResp>> => { listDetailJobServicesInfo: (
return request('/release/work/selectInspection', 'get', params) params: GetJobServicesDetailParams
): Promise<Response<ListPageJobInfoResp>> => {
return request('/pms/backstage/work/queryWorkService', 'get', params)
}, },
} //web-作业服务-详情-立即预约
\ No newline at end of file insertOrderTask: (params: GetOrderTaskParams): Promise<Response<null>> => {
return request('/oms/serviceOrderTask/insertOrderTask', 'post', params)
},
//区域
region: (): Promise<Response<Array<RegionResp>>> => {
return request('/pms/webDevice/getSecondDistrictInfo')
},
}
import React, {
Component,
Dispatch,
SetStateAction,
useEffect,
useState,
} from 'react'
import { message } from 'antd'
import { Box } from './styled'
import { useRouter } from 'next/router'
let MAP: any
let Amap: any
interface UserInfoType {
lat: number
lon: number
pageNo?: number
pageSize?: number
}
interface BoxProps {
setAddressContent: Dispatch<SetStateAction<any>>
setIsAddressMapShow: Dispatch<SetStateAction<boolean>>
}
export default function MapComponent(props: BoxProps) {
const { setAddressContent, setIsAddressMapShow } = props
const router = useRouter()
const [mapItem, setMapItem] = useState(0)
const [userPositioning, setUserPositioning] = useState<UserInfoType>()
const [markerCol, setMarkerCol] = useState<any>([])
//初始化地图
const init = async () => {
try {
const AMapLoader = await import(
/* webpackChunkName: "amap" */ '@amap/amap-jsapi-loader'
)
await AMapLoader.load({
key: '87b424e68754efc3ba9d11ae07475091', // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [''], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then(async (AMap) => {
Amap = AMap
MAP = new AMap.Map('container', {
// 设置地图容器id
viewMode: '3D', // 是否为3D地图模式
zoom: 9, // 初始化地图级别
center: [113.93029, 22.53291], // 初始化地图中心点位置
})
//用户定位
AMap.plugin('AMap.Geolocation', function () {
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位,默认:5s
position: 'RB', //定位按钮的停靠位置
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
})
MAP.addControl(geolocation)
geolocation.getCurrentPosition(function (
status: string,
result: any
) {
if (status == 'complete') {
onComplete(result)
} else {
onError(result)
}
})
})
//解析定位结果
async function onComplete(data: any) {
console.log('定位成功')
setUserPositioning(data.position)
// return await mapEntiy(0,data.position);
}
//解析定位错误信息
async function onError(data: any) {
// message.error(`定位失败
// 失败原因排查信息:${data.message}
// 浏览器返回信息:${data.originMessage}
// `)
}
await mapEntiy(0)
})
.catch((e) => {
console.log(e)
})
} catch (error) {
console.log(error)
}
}
//选择点位
const mapEntiy = async (index: number, data?: UserInfoType) => {
MAP.on('click', mapGet)
setMapItem(index)
}
const mapGet = (e: any) => {
console.log(e)
// 在这里获取点位信息
const lnglat = e.lnglat
console.log(lnglat)
const geocoder = new Amap.Geocoder({
radius: 1000,
extensions: 'all',
})
geocoder.getAddress(lnglat, function (status: any, result: any) {
if (status === 'complete' && result.regeocode) {
const address = result.regeocode.addressComponent
const addressDteail =
address.province +
address.city +
address.district +
address.township +
address.street +
address.streetNumber
setAddressContent({
province: address.province,
city: address.city,
lon: lnglat.lng,
lat: lnglat.lat,
addressDteail,
})
setIsAddressMapShow(false)
// console.log(
// address.province +
// address.city +
// address.district +
// address.township +
// address.street +
// address.streetNumber
// ) // 打印省市区信息
}
})
// MAP.off('click', mapGet); // 移除click事件
}
const addEntiy = (lon: any, lat: any, name: string) => {
if (!Amap) return
const icons = new Amap.Icon({
size: new Amap.Size(60, 60), // 图标尺寸
imageSize: new Amap.Size(60, 60), // 根据所设置的大小拉伸或压缩图片
})
const marker = new Amap.Marker({
position: new Amap.LngLat(lon, lat),
offset: new Amap.Pixel(-10, -10),
icon: icons, // 添加 Icon 实例
title: name,
zoom: 13,
})
return marker
}
useEffect(() => {
;(async () => {
await init()
})()
return MAP && MAP.destroy()
}, [])
return (
<Box className="right-box-item">
<div id="container" className="map"></div>
</Box>
)
}
import styled from 'styled-components'
export default function Style() {
return <></>
}
export const Box = styled.div`
box-sizing: border-box;
width: 800px;
height: 800px;
#container {
position: relative;
padding: 0px;
margin: 0px;
width: 100%;
height: 800px;
}
.amap-logo {
//去除高德地图水印
display: none !important;
visibility: hidden !important;
}
.amap-copyright {
//去除高德地图水印
display: none !important;
visibility: hidden !important;
}
`
import styled from "styled-components" import styled from 'styled-components'
export default function Style() { export default function Style() {
return <></>; return <></>
} }
export const Box = styled.div` export const Box = styled.div`
box-sizing: border-box; box-sizing: border-box;
width: 1200px; width: 1200px;
height: 1338px; height: 1338px;
margin-top: 18px; margin-top: 18px;
background-color: #FFFFFF; background-color: #ffffff;
.top{ .top {
display: flex; display: flex;
height: 300px; height: 300px;
padding: 24px 0 0 24px; padding: 24px 0 0 24px;
&-image{ &-image {
width: 300px; width: 300px;
height: 300px; height: 300px;
background-color: #F4F5F7; background-color: #f4f5f7;
border-radius: 6px; border-radius: 6px;
margin-right: 32px; margin-right: 32px;
position: relative; position: relative;
}
&-right {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 300px;
.right-top {
.title {
height: 26px;
font-size: 28px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #090909;
line-height: 26px;
} }
&-right{ .detail {
display: flex; display: flex;
flex-direction: column; margin-top: 27px;
justify-content: space-between; .tab {
height: 300px; width: 64px;
.right-top{ height: 18px;
.title{ line-height: 18px;
height: 26px; text-align: center;
font-size: 28px; background: linear-gradient(270deg, #3e62e5 0%, #3588f7 100%);
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; border-radius: 9px;
font-weight: bold; font-size: 12px;
color: #090909; font-family: PingFangSC-Medium, PingFang SC;
line-height: 26px; font-weight: 500;
} color: #f6fdfe;
.detail{ margin-right: 5px;
display: flex; }
margin-top: 27px; .content {
.tab{ font-size: 14px;
width: 64px; font-family: PingFangSC-Regular, PingFang SC;
height: 18px; font-weight: 400;
line-height: 18px; color: #999999;
text-align: center; line-height: 20px;
background: linear-gradient(270deg, #3E62E5 0%, #3588F7 100%); }
border-radius: 9px; }
font-size: 12px; .more {
font-family: PingFangSC-Medium, PingFang SC; display: flex;
font-weight: 500; margin-top: 25px;
color: #F6FDFE; .tab {
margin-right: 5px; width: 131px;
} height: 23px;
.content{ line-height: 23px;
font-size: 14px; text-align: center;
font-family: PingFangSC-Regular, PingFang SC; border-radius: 3px;
font-weight: 400; font-family: MicrosoftYaHei;
color: #999999; background-color: #f4f4f4;
line-height: 20px; color: #333333;
} margin-right: 8px;
} &.filst {
.more{ color: #6e411e;
display: flex; background-color: #f9e3d1;
margin-top: 25px;
.tab{
width: 131px;
height: 23px;
line-height: 23px;
text-align: center;
border-radius: 3px;
font-family: MicrosoftYaHei;
background-color: #F4F4F4;
color: #333333;
margin-right: 8px;
&.filst{
color: #6E411E;
background-color: #F9E3D1;
}
}
}
}
.right-bottom{
.bottom-btn{
.btn-left{
width: 207px;
height: 40px;
background-color: #FFE4D1;
border: 1px solid #EBBAAF;
font-family: MicrosoftYaHei;
color: #FF552D;
letter-spacing: 1px;
margin-right: 12px;
}
.btn-right{
width: 207px;
height: 40px;
background: #FF552D;
font-family: MicrosoftYaHei;
color: #FFFFFF;
letter-spacing: 1px;
}
}
} }
}
} }
} }
.tabs{ .right-bottom {
padding: 0 24px; .bottom-btn {
margin-top: 69px; .btn-left {
.teamIntroduction{ width: 207px;
width: 100%; height: 40px;
background-color: #ffe4d1;
border: 1px solid #ebbaaf;
font-family: MicrosoftYaHei;
color: #ff552d;
letter-spacing: 1px;
margin-right: 12px;
}
.btn-right {
width: 207px;
height: 40px;
background: #ff552d;
font-family: MicrosoftYaHei;
color: #ffffff;
letter-spacing: 1px;
}
} }
}
}
}
.tabs {
padding: 0 24px;
margin-top: 69px;
.teamIntroduction {
width: 100%;
}
}
.reservation {
.title {
display: flex;
align-items: center;
padding-bottom: 25px;
.left {
width: 58px;
height: 58px;
background: #d8d8d8;
border-radius: 2px;
}
.right {
margin-left: 10px;
font-weight: 700;
font-size: 16px;
}
}
}
.form-data {
.address-map {
display: flex;
align-items: center;
.value {
margin-right: 20px;
}
} }
` }
\ No newline at end of file `
import React, { useEffect, useState , useRef } from "react"; import React, { useEffect, useState, useRef } from 'react'
import { Box } from "./styled"; import { Box } from './styled'
import { Pagination } from "antd"; import { Pagination } from 'antd'
import Layout from "~/components/layout"; import Layout from '~/components/layout'
import ContentBox from "~/components/contentBox"; import ContentBox from '~/components/contentBox'
import { useRouter } from "next/router"; import { useRouter } from 'next/router'
import Filter, { FilterResult, AdapterResult } from "~/components/filter"; import Filter, { FilterResult, AdapterResult } from '~/components/filter'
import api, { Job } from "./api"; import api, { Job } from './api'
import Image from "next/image"; import Image from 'next/image'
// 此函数在构建时被调用 // 此函数在构建时被调用
export async function getServerSideProps() { export async function getServerSideProps() {
return { return {
props: {}, props: {},
}; }
} }
interface ImageListType {} interface ImageListType {}
export default function JobServices() { export default function JobServices() {
const router = useRouter(); const router = useRouter()
const filter = useRef<any>()
const [list, setList] = useState([ const [list, setList] = useState([
"https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844-2(1).jpg", 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/540X844-2(1).jpg',
// "https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/665512fd-12e6-49a9-93c1-f9dcd0e82083.jpg", // "https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/665512fd-12e6-49a9-93c1-f9dcd0e82083.jpg",
]); ])
const [productList, setProductList] = useState( const [productList, setProductList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const [rightDomList, setRightDomList] = useState( const [rightDomList, setRightDomList] = useState(
Array<{ element: JSX.Element }> Array<{ element: JSX.Element }>
); )
const leftDom = (item: Job) => { const leftDom = (item: Job) => {
return ( return (
<div <div
...@@ -43,8 +42,9 @@ export default function JobServices() { ...@@ -43,8 +42,9 @@ export default function JobServices() {
{/* <div className="com">{item.teamName}</div> */} {/* <div className="com">{item.teamName}</div> */}
</div> </div>
<div className="value-right"> <div className="value-right">
<span className="money">¥{item.price}</span>{" "} {/* <span className="money">¥{item.price}</span> */}
<span className="unit">/平</span> {/* <span className="unit">/平</span> */}
<span className="money">获取报价</span>
</div> </div>
</div> </div>
</div> </div>
...@@ -56,49 +56,46 @@ export default function JobServices() { ...@@ -56,49 +56,46 @@ export default function JobServices() {
<div className="com">{item.teamName}</div> <div className="com">{item.teamName}</div>
</div> </div>
</div> </div>
); )
}; }
const rightDom = (item: string) => { const rightDom = (item: string) => {
return ( return (
<div className="right-box-item advertisement" key={item}> <div className="right-box-item advertisement" key={item}>
<Image src={item} alt="error" width={260} height={420} /> <Image src={item} alt="error" width={260} height={420} />
</div> </div>
); )
}; }
const [filterResult, setFilterResult] = useState<AdapterResult>({}); //筛选结果 const [filterResult, setFilterResult] = useState<AdapterResult>({}) //筛选结果
const [pageParams, setPageParams] = useState({ const [pageParams, setPageParams] = useState({
pageNo: 1, pageNo: 1,
pageSize: 14, pageSize: 14,
}); //分页器对象 }) //分页器对象
const [count, setCount] = useState(0); //商品总数 const [count, setCount] = useState(0) //商品总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断 const [abort, setAbort] = useState<AbortController | null>(null) //请求中断
const onPageChange = (page: number, pageSize: number) => { const onPageChange = (page: number, pageSize: number) => {
setPageParams({ setPageParams({
...pageParams, ...pageParams,
pageNo: page, pageNo: page,
}); })
}; }
useEffect(() => { useEffect(() => {
//中断前一次列表请求 //中断前一次列表请求
abort?.abort(); abort?.abort()
setAbort(new AbortController()); setAbort(new AbortController())
}, [filterResult, pageParams]); }, [filterResult, pageParams])
//端口列表请求 //端口列表请求
useEffect(() => { useEffect(() => {
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
const idArr = filter.current.idArr
let rs let rs
for (const key in queryVal) { if (Object.keys(queryVal).length) {
if (idArr.includes(key)) { rs = { categoryId: [Number(queryVal['categoryId'])] }
rs = {[key]:router.query[key]}
}
} }
api api
.listPageJobServicesInfo( .listPageJobServicesInfo(
...@@ -114,49 +111,46 @@ export default function JobServices() { ...@@ -114,49 +111,46 @@ export default function JobServices() {
.then((res) => { .then((res) => {
setProductList( setProductList(
res.result?.list?.map((item) => { res.result?.list?.map((item) => {
return { element: leftDom(item) }; return { element: leftDom(item) }
}) || [] }) || []
); )
setCount(res.result?.totalCount || 0); setCount(res.result?.totalCount || 0)
}); })
}, [abort]); }, [abort])
const onFilterChange = ( const onFilterChange = (
filterResult: FilterResult, filterResult: FilterResult,
adapterFilterResult: AdapterResult adapterFilterResult: AdapterResult
) => { ) => {
console.log("filterResult", filterResult, adapterFilterResult); console.log('filterResult', filterResult, adapterFilterResult)
setFilterResult(adapterFilterResult); adapterFilterResult.categoryId = adapterFilterResult.categoryId?.map(
}; (item) => item.id
)
setFilterResult(adapterFilterResult)
}
useEffect(() => { useEffect(() => {
setRightDomList( setRightDomList(
list.map((item) => { list.map((item) => {
return { element: rightDom(item) }; return { element: rightDom(item) }
}) })
); )
}, []); }, [])
useEffect(() => { useEffect(() => {
let queryVal = JSON.parse(JSON.stringify(router.query)); let queryVal = JSON.parse(JSON.stringify(router.query))
if (router.query) { if (Object.keys(router.query).length) {
const idArr = filter.current.idArr setFilterResult({ categoryId: [Number(queryVal['categoryId'])] })
for (const key in queryVal) {
if (idArr.includes(key)) {
setFilterResult({ [key]:router.query[key] });
}
}
} }
}, [router]); }, [router])
return ( return (
<Layout> <Layout>
<Box> <Box>
<Filter <Filter
types={["地域", "行业", "应用"]} types={['地域', '行业', '应用']}
showResultItem showResultItem
onChange={onFilterChange} onChange={onFilterChange}
ref={filter}
></Filter> ></Filter>
<div style={{ marginTop: 10 }}> <div style={{ marginTop: 10 }}>
<ContentBox <ContentBox
...@@ -179,12 +173,12 @@ export default function JobServices() { ...@@ -179,12 +173,12 @@ export default function JobServices() {
}} }}
rightRenderDom={{ columns: rightDomList }} rightRenderDom={{ columns: rightDomList }}
leftcontentstyle={{ leftcontentstyle={{
width: "924px", width: '924px',
margin: { top: 0, right: "10px", bottom: "10px", left: 0 }, margin: { top: 0, right: '10px', bottom: '10px', left: 0 },
}} }}
/> />
</div> </div>
</Box> </Box>
</Layout> </Layout>
); )
} }
import request, { Response } from '~/api/request'; import request, { Response } from '~/api/request'
export interface ListPageGoodsInfoParams { export interface DeviceListParams {
"brandId"?: number, categoryId?: any[];
"districtId"?: number, pageNo: number;
"modelId"?: number, pageSize: number;
"pageNo": number, provinceId?: number;
"pageSize": number, type: number;
"partsId"?: number,
"productCategoryId"?: number,
"qualityId"?: number
} }
export interface Goods { export interface Goods {
"createTime": string, id: number;
"directoryId": number, goodsName: string;
"directoryName": string, images: string;
"goodsName": string, price?: any;
"goodsOneLevelTypeName": string,
"goodsTwoLevelTypeName": string,
"id": number,
"imgUrl": string,
"isCoupons": number,
"status": number
} }
export interface ListPageGoodsInfoResp { export interface DeviceListResp {
"pageNo": 1, "pageNo": 1,
"pageSize": 10, "pageSize": 10,
"list": Array<Goods>, "list": Array<Goods>,
...@@ -33,17 +24,19 @@ export interface ListPageGoodsInfoResp { ...@@ -33,17 +24,19 @@ export interface ListPageGoodsInfoResp {
} }
export interface Ad { export interface Ad {
id: number; id: number
imageUrl: string; bannerImg: string
} }
export default { export default {
//web-商品信息-分页 //web-商品信息-分页
listPageGoodsInfo: (params: ListPageGoodsInfoParams, options = {}): Promise<Response<ListPageGoodsInfoResp>> => { deviceList: (params: DeviceListParams, options = {}): Promise<Response<DeviceListResp>> => {
return request('/pms/webProductMall/listPageGoodsInfo', 'post', params, options) return request('/pms/product/mall/deviceList', 'post', params, options)
}, },
//产品商城广告位 //产品商城广告位
ad: (): Promise<Response<Array<Ad>>> => { listBannerImg: () => {
return request('/pms/webProductMall/ad') return request('/release/module/listBannerImg', 'get', {
} moduleCode: 'PRODUCT_MARKETP'
} })
\ No newline at end of file },
}
...@@ -13,7 +13,7 @@ import { Navigation } from "swiper"; ...@@ -13,7 +13,7 @@ import { Navigation } from "swiper";
// Import Swiper styles // Import Swiper styles
import "swiper/css"; import "swiper/css";
import "swiper/css/navigation"; import "swiper/css/navigation";
import api, { GetAppGoodsInfoDetailResult } from "./api"; import api, { GetLeaseGoodsDetailResp, ProductSpecList } from "./api";
import IntentionModal from "./components/intentionModal"; import IntentionModal from "./components/intentionModal";
import { UserContext } from "~/lib/userProvider"; import { UserContext } from "~/lib/userProvider";
...@@ -22,11 +22,24 @@ export default function MallDetail() { ...@@ -22,11 +22,24 @@ export default function MallDetail() {
const [visible, setVisible] = useState(false); //商品图预览 const [visible, setVisible] = useState(false); //商品图预览
const router = useRouter(); const router = useRouter();
const [id, setId] = useState<number | null>(null); const [id, setId] = useState<number | null>(null);
const [detail, setDetail] = useState<GetAppGoodsInfoDetailResult | null>( const [detail, setDetail] = useState<GetLeaseGoodsDetailResp | null>(null); //详情数据
null
); //详情数据
const [intentionModalOpen, setIntentionModalOpen] = useState(false); //意向弹窗 const [intentionModalOpen, setIntentionModalOpen] = useState(false); //意向弹窗
const [productImg, setProductImg] = useState(''); //展示的商品图 const [productImg, setProductImg] = useState(""); //展示的商品图
const [previewIndex, setPreviewIndex] = useState(0); //预览开始索引
const [checkItems, setCheckItems] = useState<ProductSpecList[]>([]); //选中的规格
const [specCount, setSpecCount] = useState(0); //规格数量
useEffect(() => {
if (detail) {
let count = 0;
detail.goodsSpec?.forEach((good) => {
good.productSpecList?.forEach((product) => {
count++;
});
});
setSpecCount(count);
}
}, [detail]);
//打开意向modal //打开意向modal
const openIntentionModal = () => { const openIntentionModal = () => {
...@@ -53,8 +66,9 @@ export default function MallDetail() { ...@@ -53,8 +66,9 @@ export default function MallDetail() {
useEffect(() => { useEffect(() => {
if (id) { if (id) {
api api
.getAppGoodsInfoDetail({ .getLeaseGoodsDetail({
id: id, goodsId: id,
type: 0,
}) })
.then((res) => { .then((res) => {
setDetail(res.result || null); setDetail(res.result || null);
...@@ -71,11 +85,16 @@ export default function MallDetail() { ...@@ -71,11 +85,16 @@ export default function MallDetail() {
detail={detail} detail={detail}
onOk={handleIntentionOk} onOk={handleIntentionOk}
onCancel={handleIntentionCancel} onCancel={handleIntentionCancel}
onChange={(items: ProductSpecList[]) => setCheckItems(items)}
></IntentionModal> ></IntentionModal>
<div className="page" style={{ marginTop: 20, backgroundColor: "#fff" }}> <div className="page" style={{ marginTop: 20, backgroundColor: "#fff" }}>
<div style={{ display: "none" }}> <div style={{ display: "none" }}>
<AImage.PreviewGroup <AImage.PreviewGroup
preview={{ visible, onVisibleChange: (vis) => setVisible(vis) }} preview={{
visible,
onVisibleChange: (vis) => setVisible(vis),
current: previewIndex,
}}
> >
{detail?.images?.map((item) => { {detail?.images?.map((item) => {
return <AImage key={item.id} src={item.imgUrl} />; return <AImage key={item.id} src={item.imgUrl} />;
...@@ -106,7 +125,7 @@ export default function MallDetail() { ...@@ -106,7 +125,7 @@ export default function MallDetail() {
onSlideChange={() => console.log("slide change")} onSlideChange={() => console.log("slide change")}
onSwiper={(swiper) => console.log(swiper)} onSwiper={(swiper) => console.log(swiper)}
> >
{detail?.images?.map((item) => { {detail?.images?.map((item, i) => {
return ( return (
<SwiperSlide key={item.id}> <SwiperSlide key={item.id}>
<AImage <AImage
...@@ -116,7 +135,9 @@ export default function MallDetail() { ...@@ -116,7 +135,9 @@ export default function MallDetail() {
src={item.imgUrl} src={item.imgUrl}
fallback={errImg} fallback={errImg}
style={{ cursor: "pointer" }} style={{ cursor: "pointer" }}
onClick={() => setProductImg(item.imgUrl)} onClick={() => {
setProductImg(item.imgUrl), setPreviewIndex(i);
}}
/> />
</SwiperSlide> </SwiperSlide>
); );
...@@ -128,11 +149,8 @@ export default function MallDetail() { ...@@ -128,11 +149,8 @@ export default function MallDetail() {
<div className={`${styles.font1} ${styles.ellipsis}`}> <div className={`${styles.font1} ${styles.ellipsis}`}>
{detail?.goodsName} {detail?.goodsName}
</div> </div>
<div <div className={`${styles.font2} ${styles.ellipsis2}`} style={{}}>
className={`${styles.font2} ${styles.ellipsis}`} {detail?.goodsDetail?.goodsDesc}
style={{ height: 22 }}
>
{detail?.goodsDesc}
</div> </div>
<Space <Space
size={24} size={24}
...@@ -149,14 +167,14 @@ export default function MallDetail() { ...@@ -149,14 +167,14 @@ export default function MallDetail() {
选择 选择
</Col> </Col>
<Col flex="auto" className={styles.font4} style={{}}> <Col flex="auto" className={styles.font4} style={{}}>
已选:1 已选:{checkItems.length}
</Col> </Col>
</Row> </Row>
</Col> </Col>
<Col> <Col>
<Row align="middle" style={{ cursor: "pointer" }}> <Row align="middle" style={{ cursor: "pointer" }}>
<Col className={styles.font4} onClick={openIntentionModal}> <Col className={styles.font4} onClick={openIntentionModal}>
3种可选 {specCount}种可选
</Col> </Col>
<Col style={{ marginLeft: 9 }}> <Col style={{ marginLeft: 9 }}>
<DownOutlined <DownOutlined
......
import request, { Response } from "~/api/request" import request, { Response } from "~/api/request"
export interface GetAppGoodsInfoDetailParams { export interface GetLeaseGoodsDetailParams {
id: number goodsId: number,
type: 1 | 0, //租赁:1 销售商品:0
} }
export interface GetAppGoodsInfoDetailResult { export interface GetLeaseGoodsDetailResp {
id: number; id: number;
pid?: number; images: Image[];
goodsName?: string; goodsVideo?: any;
shareFlyServiceId?: number; goodsVideoId?: any;
repoId?: number; goodsName: string;
goodsSpec?: GoodsSpec[]; goodsNo: string;
images?: Image[]; goodsDetail: GoodsDetail;
goodsVideo?: string; directoryId: number;
goodsVideoId?: number; categoryByOne: number;
goodsDetail?: GoodsDetail; categoryByTwo?: any;
sortTypeId?: number; tag?: any;
masterTypeId?: number; shelfStatus: number;
slaveTypeId?: number; goodsSpec: GoodsSpec[];
tag?: string; otherService: OtherService[];
shelfStatus?: number; price?: any;
otherService?: OtherService[];
question?: Question[];
goodsDesc?: string
} }
export interface GoodsDetail { export interface OtherService {
id: number;
goodsDesc: string;
content: string;
remark?: any;
}
export interface Image {
id: number; id: number;
imgUrl: string; saleServiceId: number;
imgType: number; serviceName: string;
} }
export interface GoodsSpec { export interface GoodsSpec {
id: number; id: number;
goodsSpecName: string; goodsSpecName: string;
goodsTypeId: number; categoryId: number;
typeName: string; typeName: string;
skuId: number; skuId: number;
brandInfoId: number; brandInfoId?: any;
skuName: string; skuName: string;
productSpecList: ProductSpec[]; productSpecList: ProductSpecList[];
industrySpecList?: any; industrySpecList?: any;
chooseType: number; chooseType: number;
skuUnitId: number; skuUnitId: number;
unitName: string; unitName: string;
must: number; must: number;
flag?: any; flag: number;
} }
export interface ProductSpec { export interface ProductSpecList {
id: number; id: number;
productSpec: number; productSpec: number;
productSkuId: number; productSkuId: number;
...@@ -64,26 +55,46 @@ export interface ProductSpec { ...@@ -64,26 +55,46 @@ export interface ProductSpec {
partNo: string; partNo: string;
versionDesc: string; versionDesc: string;
createTime?: any; createTime?: any;
productSpecCPQVO?: any; productSpecCPQVO: ProductSpecCPQVO;
} }
export interface Question { export interface ProductSpecCPQVO {
answer: string, productSpecId: number;
id: number, type: number;
question: string leaseTerm?: any;
specPrice: any[];
} }
//其他服务: 1:免费配送,2:专业飞手培训2日, 3:半年保修, 4:一年保修 export interface GoodsDetail {
export interface OtherService { id: number;
id: number, goodsDesc: string;
saleServiceId: number, content: string;
serviceName: string remark?: any;
}
export interface Image {
id: number;
imgUrl: string;
imgType: number;
}
interface CommitMallOrderParams {
buyNum: number;
directoryId: number;
goodsInfoId: number;
mallSpecIds: any[];
remark: string;
userAddressId: number;
} }
export default { export default {
//web-获取商品详细信息--共多少种选择 //web-获取商品详细信息--共多少种选择
getAppGoodsInfoDetail(params: GetAppGoodsInfoDetailParams): Promise<Response<GetAppGoodsInfoDetailResult>> { getLeaseGoodsDetail(params: GetLeaseGoodsDetailParams): Promise<Response<GetLeaseGoodsDetailResp>> {
return request('/pms/webProductMall/getAppGoodsInfoDetail', 'get', params) return request('/pms/product/mall/getLeaseGoodsDetail', 'get', params)
},
//提交订单V1.0.0
commitMallOrder(params: CommitMallOrderParams){
return request('/oms/app-order/commitMallOrder', 'post', params);
} }
} }
\ No newline at end of file
import request from '~/api/request'
interface CommitMallOrderParams {
buyNum: number
directoryId: number
goodsInfoId: number
mallSpecIds: any[]
remark?: string
userAddressId: number
}
export default {
//提交订单V1.0.0
commitMallOrder(params: CommitMallOrderParams) {
return request('/oms/app-order/confirmMallOrder', 'post', params)
},
}
...@@ -59,6 +59,23 @@ ...@@ -59,6 +59,23 @@
padding: 0 39px 0 38px; padding: 0 39px 0 38px;
height: 364px; height: 364px;
overflow-y: auto; overflow-y: auto;
.numBox {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 10px;
.numLeft {
display: flex;
align-items: center;
.label {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #121212;
margin-right: 5px;
}
}
}
@include scrollbar(); @include scrollbar();
} }
import { Button, Col, Image, Modal, Row, Space } from "antd"; import { Button, Col, Image, message, Modal, Row, Space } from "antd";
import { useState } from "react"; import { useEffect, useState } from "react";
import errImg from "~/assets/errImg"; import errImg from "~/assets/errImg";
import { GetAppGoodsInfoDetailResult } from "../../api"; import { GetLeaseGoodsDetailResp, ProductSpecList } from "../../api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import api from "./api";
import Item from "antd/es/list/Item";
type Props = { type Props = {
open?: boolean; open?: boolean;
onOk?: (e: React.MouseEvent<HTMLButtonElement>) => void; onOk?: () => void;
onCancel: (e: React.MouseEvent<HTMLButtonElement>) => void; onCancel: () => void;
detail: GetAppGoodsInfoDetailResult | null; detail: GetLeaseGoodsDetailResp | null;
onChange?: (checkItems: ProductSpecList[]) => void;
}; };
export default function IntentionModal(props: Props) { export default function IntentionModal(props: Props) {
const [checkedMap, setCheckedMap] = useState<{ string?: boolean }>({}); //通过索引记录选中的产品规格 例: {'1,1': true|false} const [checkedMap, setCheckedMap] = useState<{ string?: boolean }>({}); //通过索引记录选中的产品规格 例: {'1,1': true|false} props.detail?.goodsSpec[1].productSpecList[1]
const [checkItems, setCheckItems] = useState<ProductSpecList[]>([]); //选中的规格
const [loading, setLoading] = useState(false); //下单中
useEffect(() => {
let list: ProductSpecList[] = [];
Object.keys(checkedMap).forEach((key) => {
if (checkedMap[key as keyof typeof checkedMap]) {
let arr = key.split(",");
let item =
props.detail?.goodsSpec[Number(arr[0])].productSpecList[
Number(arr[1])
];
if (item) {
list.push(item);
}
}
});
setCheckItems(list);
props.onChange && props.onChange(list);
}, [checkedMap]);
//添加规格到购物车 //添加规格到购物车
function addProductSpec(goodsSpecIndex: number, productSpecIndex: number) { function addProductSpec(goodsSpecIndex: number, productSpecIndex: number) {
...@@ -27,6 +50,58 @@ export default function IntentionModal(props: Props) { ...@@ -27,6 +50,58 @@ export default function IntentionModal(props: Props) {
}); });
} }
//提交
function onSubmit() {
let buyNum = 0;
let mallSpecIds: number[] = [];
Object.keys(checkedMap).forEach((key) => {
if (checkedMap[key as keyof typeof checkedMap]) {
buyNum++;
let arr = key.split(",");
let specId =
props.detail?.goodsSpec[Number(arr[0])].productSpecList[
Number(arr[1])
].id;
if (specId) {
mallSpecIds.push(specId);
}
}
});
if (buyNum > 0) {
setLoading(true);
api
.commitMallOrder({
buyNum,
directoryId: 1,
goodsInfoId: props.detail!.id,
mallSpecIds,
userAddressId: 1,
})
.then((res) => {
if (res.code == "200") {
message.success("提交意向成功");
//重置为未选中
let temp = {
...checkedMap,
};
Object.keys(temp).forEach((key) => {
temp[key as keyof typeof temp] = false;
});
setCheckedMap(temp);
props.onCancel();
} else {
}
setLoading(false);
})
.catch((err) => {
message.error("提交意向失败");
console.log("err", err);
setLoading(false);
});
}
}
return ( return (
<Modal <Modal
open={props.open} open={props.open}
...@@ -41,6 +116,9 @@ export default function IntentionModal(props: Props) { ...@@ -41,6 +116,9 @@ export default function IntentionModal(props: Props) {
type="primary" type="primary"
className={styles.font5} className={styles.font5}
style={{ width: "100%", height: 44 }} style={{ width: "100%", height: 44 }}
onClick={onSubmit}
loading={loading}
disabled={checkItems.length == 0}
> >
提交意向 提交意向
</Button> </Button>
...@@ -68,7 +146,12 @@ export default function IntentionModal(props: Props) { ...@@ -68,7 +146,12 @@ export default function IntentionModal(props: Props) {
className={`${styles.font2} ${styles.ellipsis2}`} className={`${styles.font2} ${styles.ellipsis2}`}
style={{ marginTop: 7 }} style={{ marginTop: 7 }}
> >
已选: 已选:{" "}
{checkItems
.map((item) => {
return item.specName;
})
.join("+")}
</div> </div>
</Col> </Col>
</Row> </Row>
......
import request, { Response } from '~/api/request'
export interface GetWebDeviceDetailParams {
buyNum: number
directoryId: number
goodsInfoId: number
mallSpecIds: number[]
remark?: string
userAddressId: number
}
export interface WareImgsType {
id: number
imgUrl: string
imgType: number
}
export interface UserAddress {
id: number
takeName: string
takePhone: string
takeRegion: string
takeAddress: string
type: number
}
export interface GetOrderForGoods {
realityAmount: number
orderNo: string
}
export default {
//web-地址管理-查询用户地址列表-条件查询
listUserAddress: (params: {}): Promise<Response<UserAddress[]>> => {
return request('/oms/user-address/selectList', 'POST', params)
},
//web-产品商城-下单
FeignAddLease: (
params: GetWebDeviceDetailParams
): Promise<Response<GetOrderForGoods>> => {
return request('/oms/app-order/commitMallOrder', 'post', params)
},
//web-产品商城-订单支付
OrderPayment: (params: {
orderNo: string
}): Promise<Response<GetOrderForGoods>> => {
return request(`/payment/repocash/orderPayment`, 'get', params)
},
}
import React, { useContext, useEffect, useState } from 'react'
import { OrderForGoodsBox } from './styled'
import type { FormInstance, RadioChangeEvent } from 'antd'
import { Button, Radio, Space, Input, message, Modal, Image } from 'antd'
import api, { UserAddress, GetOrderForGoods } from './api'
import moment from 'moment'
// import { ShopDetail } from '../../[id].page'
// import {
// GetWebDeviceDetailResult,
// GetWebDeviceWareSkuById,
// GetLeaseGoodsResult,
// } from '../../api'
import { UserContext } from '~/lib/userProvider'
const { TextArea } = Input
interface PropsBox {
setIsorderForGoods: (boolean: boolean) => void
mallDetail?: any
detailData?: any
shopDetail?: any
wareSkuList?: any
discount?: any
}
export default function OrderForGoods(props: PropsBox) {
const {
setIsorderForGoods,
shopDetail,
detailData,
wareSkuList,
discount,
mallDetail,
} = props
const [value, setValue] = useState(1)
const [areaValue, setAreaValue] = useState<string>()
const [list, setList] = useState<Array<UserAddress> | null>()
const onChange = (e: RadioChangeEvent) => {
console.log('radio checked', e.target.value)
setValue(e.target.value)
}
const onChangeValue = (index: number) => {
setValue(index)
}
const detailSumbit = () => {
if (!list?.length && !value) return message.warning('暂无地址信息')
if (list?.length && !value) return message.warning('请选择地址')
if (detailData && list && mallDetail) {
const pushList = {
buyNum: mallDetail.buyNum,
directoryId: mallDetail.directoryId,
goodsInfoId: mallDetail.goodsInfoId,
mallSpecIds: mallDetail.mallSpecIds,
userAddressId: value,
remark: areaValue,
}
api.FeignAddLease(pushList).then((res) => {
if (res.code === '200') {
message.success('提交成功')
setIsorderForGoods(false)
} else {
message.error(res.message)
}
})
}
}
useEffect(() => {
api
.listUserAddress({})
.then((res) => {
console.log(res)
setList(res.result)
res.result?.map((item, index) => {
if (item.type === 0) {
setValue(item.id)
}
})
})
.catch((err) => {
console.log(err)
})
}, [])
//图片预览
const [visible, setVisible] = useState(false)
//扫码管理地址
const [isAddAddressOpen, setIsAddAddressOpen] = useState(false)
const [addressVisible, setAddressVisible] = useState(false)
return (
<OrderForGoodsBox>
<div className="address">
<div className="top">
<div className="left">确认收货地址</div>
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
管理收货地址
</Button>
</div>
</div>
<div className="bottom">
{list?.length ? (
list?.map((item, index) => (
<div
key={item.id}
className={`item ${value === item.id ? 'active' : ''}`}
onClick={() => onChangeValue(item.id)}
>
<div className="left">
<div className="active">
<div className="icon"></div>
<div className="label">寄送至</div>
</div>
<Radio.Group onChange={onChange} value={value}>
<Space direction="vertical">
<Radio value={item.id}>{item.takeAddress}</Radio>
</Space>
</Radio.Group>
</div>
{value === item.id ? (
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
修改地址
</Button>
</div>
) : null}
</div>
))
) : (
<div className="item active">
<div className="left">
<div className="active">
<div className="icon"></div>
<div className="label">
暂无地址,请打开手机端【云享飞】微信小程序,【我的】-【个人设置】-【地址管理】添加
</div>
</div>
</div>
<div className="right">
<Button
onClick={() => setIsAddAddressOpen(true)}
type="link"
style={{ color: '#007aff' }}
>
添加地址
</Button>
</div>
</div>
)}
</div>
</div>
<div className="info">
<div className="title">确认订单信息</div>
<div className="table">
<div className="table-title">
<div className="table-item" style={{ width: 290 }}>
宝贝
</div>
<div className="table-item" style={{ width: 130 }}>
单价
</div>
<div className="table-item" style={{ width: 130 }}>
数量
</div>
<div className="table-item" style={{ width: 435 }}>
合计
</div>
</div>
{mallDetail.orderGoodsProdDetailDTOS.map((item: any) => (
<div className="table-body" key={item.id}>
<div className="body-item article" style={{ width: 290 }}>
<div className="image">
<Image
className="image-box"
preview={{ visible: false }}
src={item.prodSkuSpecImage || ''}
onClick={() => setVisible(true)}
/>
<div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible,
onVisibleChange: (vis) => setVisible(vis),
}}
>
<Image src={item.prodSkuSpecImage || ''} />
</Image.PreviewGroup>
</div>
</div>
<div className="right">
<div className="top">
{`【${item.productName}】${item.specName}` || ''}
</div>
<div className="bottom">版本:{item.versionDesc || ''}</div>
<div className="bottom">料号:{item.partNo || ''}</div>
</div>
</div>
<div className="body-item" style={{ width: 130 }}>
{item.unitPrice || 0}
</div>
<div className="body-item" style={{ width: 130 }}>
{item.buyNum || 1}
</div>
<div className="body-item total-price" style={{ width: 435 }}>
{item.skuSpecAmount}
</div>
</div>
))}
</div>
</div>
<div className="notes">
<div className="left">
<div className="label">备注:</div>
<TextArea
value={areaValue}
onChange={(e) => setAreaValue(e.target.value)}
placeholder="请输入备注"
autoSize={{ minRows: 3, maxRows: 5 }}
style={{ width: 385, height: 72 }}
/>
</div>
<div className="right">
<div className="top">
<div className="font">
<div className="label">运费:</div>
<div className="value">邮寄到付,由客户自己承担</div>
</div>
<div className="price">0.00</div>
</div>
<div className="bottom">
<div className="font">
<div className="label">押金:</div>
<div className="value">渠道商可免押金</div>
</div>
<div className="price">0.00</div>
</div>
</div>
</div>
<div className="detail-box">
<div className="right-box">
<div className="detail">
<div className="top">
<div className="label">实付款</div>
<div className="price">¥{mallDetail.orderAmount}</div>
</div>
<div className="bottom">
<div className="value">寄送至</div>
{list ? (
<div className="value-content">{list![value]?.takeAddress}</div>
) : null}
</div>
</div>
<div className="detail-sumbit">
<Button className="btn" onClick={detailSumbit}>
提交订单
</Button>
</div>
</div>
</div>
<Modal
wrapClassName="addAddress"
open={isAddAddressOpen}
onCancel={() => setIsAddAddressOpen(false)}
getContainer={false}
maskClosable={false}
width={420}
footer={false}
>
<div className="title">扫码管理地址</div>
<div className="image">
<Image
className="addressImg"
preview={{ visible: false }}
src={
window.location.href.includes('https://test.iuav.shop/')
? 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-trial.jpg'
: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-formal.jpg' ||
''
}
onClick={() => setAddressVisible(true)}
/>
<div style={{ display: 'none' }}>
<Image.PreviewGroup
preview={{
visible: addressVisible,
onVisibleChange: (vis) => setAddressVisible(vis),
}}
>
<Image
src={
window.location.href.includes('https://test.iuav.shop/')
? 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-trial.jpg'
: 'https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/image/app-iuav-formal.jpg' ||
''
}
/>
</Image.PreviewGroup>
</div>
</div>
<div className="content">
【打开微信扫一扫】-进入云享飞【我的】- 【个人设置】-【地址管理】
</div>
</Modal>
</OrderForGoodsBox>
)
}
import styled from 'styled-components'
export const OrderForGoodsBox = styled.div`
box-sizing: border-box;
width: 1000px;
.address {
.top {
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #e6e6e6;
height: 30px;
line-height: 30px;
margin-top: 30px;
.left {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #333333;
line-height: 18px;
}
.right {
.btn {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #007aff;
line-height: 19px;
}
}
}
.bottom {
.item {
display: flex;
justify-content: space-between;
align-items: center;
width: 1000px;
height: 48px;
border: 1px solid transparent;
margin-top: 8px;
&.active {
background: #fff1e8;
border-radius: 6px;
border: 1px solid #ff552d;
}
.left {
display: flex;
align-items: center;
justify-content: space-around;
.active {
margin-right: 18px;
display: flex;
.icon {
width: 15px;
height: 22px;
background: #ff552d;
margin-left: 17px;
}
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
margin-left: 18px;
}
}
}
.right {
margin-right: 22px;
}
}
}
}
.info {
margin-top: 30px;
.title {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #333333;
line-height: 18px;
}
.table {
.table-title {
display: flex;
align-items: center;
width: 1000px;
border-bottom: 1px solid #e6e6e6;
padding: 10px 0;
margin-top: 20px;
.table-item {
text-align: center;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
}
}
.table-body {
display: flex;
align-items: center;
height: 100px;
margin-top: 10px;
.body-item {
text-align: center;
&.article {
display: flex;
justify-content: space-between;
.image {
margin-right: 10px;
.image-box {
width: 80px;
height: 80px;
}
}
.right {
.top {
width: 171px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #141414;
line-height: 20px;
}
.bottom {
width: 171px;
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
}
}
&.total-price {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff3100;
line-height: 18px;
}
}
}
}
}
.notes {
display: flex;
align-items: center;
justify-content: space-between;
width: 1000px;
height: 110px;
background: #e1efff;
border: 1px solid #d0eaf5;
padding: 0 22px 0 16px;
.left {
display: flex;
align-items: top;
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
margin-top: 4px;
}
}
.right {
width: 430px;
.top {
display: flex;
align-items: center;
justify-content: space-between;
}
.font {
display: flex;
}
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 18px;
}
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000000;
line-height: 19px;
margin-right: 12px;
}
.value {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #2b2b2b;
line-height: 20px;
}
.price {
font-size: 14px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff3100;
line-height: 18px;
}
}
}
.detail-box {
display: flex;
justify-content: flex-end;
margin-top: 26px;
.right-box {
.detail {
width: 477px;
height: 110px;
border: 1px solid #ff5001;
padding: 16px 19px 19px 19px;
.top {
display: flex;
justify-content: flex-end;
align-items: center;
.label {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #474747;
line-height: 19px;
margin-right: 10px;
}
.price {
font-size: 26px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff552d;
line-height: 33px;
}
}
.bottom {
display: flex;
justify-content: flex-end;
align-items: center;
margin-top: 15px;
.value {
font-size: 12px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #000000;
line-height: 15px;
margin-right: 10px;
}
.value-content {
font-size: 12px;
font-family: MicrosoftYaHei;
color: #333333;
line-height: 16px;
}
}
}
.detail-sumbit {
display: flex;
justify-content: flex-end;
.btn {
width: 182px;
height: 39px;
background: #ff552d;
border: 1px solid #ff5001;
border-radius: 0;
color: #ffffff;
}
}
}
}
.Payment {
.title {
text-align: center;
font-size: 26px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #ff552d;
}
}
.addAddress {
.title {
text-align: center;
height: 25px;
font-size: 20px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #000000;
line-height: 25px;
}
.image {
display: flex;
justify-content: center;
align-items: center;
padding: 48px 0 32px;
.addressImg {
width: 150px;
height: 150px;
}
}
.content {
text-align: center;
width: 311px;
height: 38px;
font-size: 14px;
font-family: MicrosoftYaHei;
color: #3e454d;
line-height: 19px;
}
}
`
...@@ -4,6 +4,10 @@ ...@@ -4,6 +4,10 @@
@include ellipsis(1); @include ellipsis(1);
} }
.ellipsis2 {
@include ellipsis(2);
}
.font1 { .font1 {
font-size: 28px; font-size: 28px;
font-weight: bold; font-weight: bold;
......
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from 'react'
import { Empty, Pagination, Image, Spin } from "antd"; import { Empty, Pagination, Image, Spin } from 'antd'
import Layout from "~/components/layout"; import Layout from '~/components/layout'
import styles from "./index.module.scss"; import styles from './index.module.scss'
import { useRouter } from "next/router"; import { useRouter } from 'next/router'
import Filter, { AdapterResult, FilterResult } from "~/components/filter"; import Filter, { AdapterResult, FilterResult } from '~/components/filter'
import api, { Ad, Goods, ListPageGoodsInfoParams } from "./api"; import api, { Ad, Goods } from './api'
import errImg from "~/assets/errImg"; import errImg from '~/assets/errImg'
// 此函数在构建时被调用 // 此函数在构建时被调用
export async function getServerSideProps() { export async function getServerSideProps() {
return { return {
props: {}, props: {},
}; }
} }
type Props = {}; type Props = {}
export default function Mall(props: Props) { export default function Mall(props: Props) {
const router = useRouter(); const router = useRouter()
const [productList, setProductList] = useState<Array<Goods>>([]); //商品列表 const [productList, setProductList] = useState<Array<Goods>>([]) //商品列表
const [filterResult, setFilterResult] = useState<AdapterResult>({}); //筛选结果 const [filterResult, setFilterResult] = useState<AdapterResult>({}) //筛选结果
const [pageParams, setPageParams] = useState({ const [pageParams, setPageParams] = useState<{
pageNo: number
pageSize: number
}>({
pageNo: 1, pageNo: 1,
pageSize: 15, pageSize: 15,
}); //分页器对象 }) //分页器对象
const [count, setCount] = useState(0); //商品总数 const [count, setCount] = useState(0) //商品总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断对你 const [abort, setAbort] = useState<AbortController | null>(null) //请求中断对象
const [adList, setAdList] = useState<Array<Ad>>([]); //广告列表 const [adList, setAdList] = useState<Array<Ad>>([]) //广告列表
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false)
useEffect(() => { useEffect(() => {
//中断前一次列表请求 //中断前一次列表请求
abort?.abort(); abort?.abort()
setAbort(new AbortController()); setAbort(new AbortController())
}, [filterResult, pageParams]); }, [filterResult, pageParams])
//端口列表请求 //商品列表请求
useEffect(() => { useEffect(() => {
if (!abort) { if (!abort) {
return; return
} }
setLoading(true); setLoading(true)
api api
.listPageGoodsInfo( .deviceList(
{ {
...filterResult, type: 0,
...pageParams, ...pageParams,
...filterResult,
}, },
{ {
signal: abort?.signal, signal: abort?.signal,
...@@ -56,34 +60,37 @@ export default function Mall(props: Props) { ...@@ -56,34 +60,37 @@ export default function Mall(props: Props) {
setCount(res.result?.totalCount || 0); setCount(res.result?.totalCount || 0);
setLoading(false); setLoading(false);
}); });
}, [abort]); }, [abort])
//广告请求 //广告请求
useEffect(() => { useEffect(() => {
api.ad().then((res) => { api.listBannerImg().then((res) => {
setAdList(res.result || []); setAdList(res.result || []);
}); });
}, []); }, [])
const onFilterChange = ( const onFilterChange = (
filterResult: FilterResult, filterResult: FilterResult,
adapterFilterResult: AdapterResult adapterFilterResult: AdapterResult
) => { ) => {
console.log("filterResult", filterResult, adapterFilterResult); console.log('filterResult', filterResult, adapterFilterResult)
setFilterResult(adapterFilterResult); adapterFilterResult.categoryId = adapterFilterResult.categoryId?.map(
}; (item) => item.id
)
setFilterResult(adapterFilterResult)
}
const onPageChange = (page: number, pageSize: number) => { const onPageChange = (page: number, pageSize: number) => {
setPageParams({ setPageParams({
...pageParams, ...pageParams,
pageNo: page, pageNo: page,
}); })
}; }
return ( return (
<Layout> <Layout>
<div className="page" style={{ paddingTop: "18px" }}> <div className="page" style={{ paddingTop: "18px" }}>
<Filter <Filter
types={["类目", "地域", "品牌", "部件", "型号", "成色"]} types={["地域"]}
showResultItem showResultItem
onChange={onFilterChange} onChange={onFilterChange}
></Filter> ></Filter>
...@@ -91,42 +98,45 @@ export default function Mall(props: Props) { ...@@ -91,42 +98,45 @@ export default function Mall(props: Props) {
<div className={styles.productList}> <div className={styles.productList}>
<div className={styles.main}> <div className={styles.main}>
<div className={styles.listContent}> <div className={styles.listContent}>
<ul className={styles.listWrap}> <Spin spinning={loading} delay={500}>
{productList.map((item, i) => { <ul className={styles.listWrap}>
return ( {productList.map((item, i) => {
<li return (
key={i} <li
className={styles.item} key={i}
onClick={() => router.push("/mall/detail/" + item.id)} className={styles.item}
> onClick={() => router.push("/mall/detail/" + item.id)}
<div className={styles.imgBox}> >
<Image <div className={styles.imgBox}>
alt="" <Image
src={item.imgUrl} alt=""
className={styles.img} src={item.images}
width={116} className={styles.img}
height={116} width={116}
preview={false} height={116}
></Image> preview={false}
</div> ></Image>
<div className={styles.title}>{item.goodsName}</div> </div>
<div className={styles.sellCount}> <div className={styles.title}>{item.goodsName}</div>
半年售 <div className={styles.sellCount}>
{(Math.floor(Math.random() * 901) + 100).toFixed(0)} 半年售
</div> {(Math.floor(Math.random() * 901) + 100).toFixed(0)}
</li> </div>
); </li>
})} );
{productList.length === 0 && ( })}
<Empty {productList.length === 0 && (
style={{ <Empty
paddingTop: 20, style={{
width: "100%", paddingTop: 20,
textAlign: "center", width: "100%",
}} textAlign: "center",
></Empty> }}
)} ></Empty>
</ul> )}
</ul>
</Spin>
<div className={styles.paginationPage}> <div className={styles.paginationPage}>
<Pagination <Pagination
current={pageParams.pageNo} current={pageParams.pageNo}
...@@ -147,7 +157,7 @@ export default function Mall(props: Props) { ...@@ -147,7 +157,7 @@ export default function Mall(props: Props) {
<Image <Image
key={item.id} key={item.id}
className={styles.ad} className={styles.ad}
src={item.imageUrl} src={item.bannerImg}
width={189} width={189}
height={295} height={295}
preview={false} preview={false}
......
.Sider {
width: 129px;
background: #fafafa;
}
.menu {
width: 128px;
min-height: 507px;
background: #fafafa;
border-right: 0 !important;
:global .ant-menu-title-content {
font-size: 12px;
}
}
.title {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #000;
line-height: 19px;
padding-top: 18px;
padding-left: 27px;
padding-bottom: 8px;
border-bottom: 1px solid #e5e5e5;
}
import LayoutView from "~/components/layout";
import React, { useState } from "react";
import type { MenuProps } from "antd";
import { Button, Menu } from "antd";
import styles from "./index.module.scss";
import Router from "next/router";
function getItem(
label: React.ReactNode,
key: React.Key,
icon?: React.ReactNode,
children?: MenuItem[],
type?: "group"
): MenuItem {
return {
key,
icon,
children,
label,
type,
} as MenuItem;
}
const items: MenuItem[] = [
getItem("我的订单", "1", undefined, [
getItem("服务订单", "/personalCenter/servicesOrders"),
getItem("租赁订单", "/personalCenter/leasingOrders"),
getItem("商城订单", "/personalCenter/mallOrders"),
// getItem("培训订单", "/personalCenter/trainOrders"),
]),
/* getItem("账户信息", "2"),
getItem("优惠券卡包", "3"),
getItem("福利活动", "4"),
getItem("身份认证", "5"),
getItem("客服中心", "6"),
getItem("推广海报", "7"),
getItem("副业赚钱", "8"), */
];
type MenuItem = Required<MenuProps>["items"][number];
type Props = {
style?: React.CSSProperties;
selectedKeys?: string[];
};
export default function Sider(props: Props) {
return (
<div className={styles.Sider} style={props.style}>
<div className={styles.title}>个人中心</div>
<Menu
selectedKeys={props.selectedKeys}
openKeys={["1"]}
mode="inline"
items={items}
className={styles.menu}
onClick={(info) => {
Router.push(info.key);
}}
/>
</div>
);
}
import request, { Response } from "~/api/request"
export interface ListPageWechatOrderParams {
buyerAccount?: string;
endTime?: string;
orderNo?: string;
pageNo: number;
pageSize: number;
startTime?: string;
tranStatus?: string;
wareNo?: string;
wareTitle?: string;
}
export interface ListPageWechatOrderResp {
pageNo: number;
pageSize: number;
list: LeasingList[];
totalCount: number;
totalPage: number;
}
export interface LeasingList {
id: number;
orderNo: string;
createTime?: any;
wareInfoId?: any;
wareNo?: any;
wareTitle: string;
wareImg: string;
skuInfoId?: any;
skuTitle?: any;
repoAccountId?: any;
uid?: any;
buyerName?: any;
buyerPhone?: any;
unitPrice?: any;
wareNum: number;
shouldPay: number;
actualPay: number;
orderType?: any;
deposit?: any;
rentPrice?: any;
startDate?: any;
endDate?: any;
payDay?: any;
tranStatus: string;
exWare?: any;
remark?: any;
pfRemark?: any;
shutReason?: any;
payNo?: any;
payTime?: any;
sendWareTime?: any;
receipt: Receipt;
orderRefund?: any;
express?: any;
refundExpress?: any;
vcus?: any;
returnTime?: any;
couponId?: any;
specsId?: any;
balance?: any;
doing?: any;
waiting?: any;
leaseOrderStatus?: any;
nickName?: any;
wareDescription?: any;
}
interface Receipt {
id: number;
receiptMethod: number;
takeName: string;
takePhone: string;
region: string;
detailAddress: string;
repoName?: any;
repoAddress?: any;
bookPhone?: any;
sendExCode?: any;
sendExNo?: any;
sendAddress?: any;
renMethod?: any;
renPhone?: any;
renName?: any;
renExCode?: any;
renExNo?: any;
renAddress?: any;
renRepoName?: any;
renRepoAddr?: any;
renRepoPhone?: any;
}
export interface ListTranStatusResp {
status: string;
doing: string;
waiting: string;
leaseOrderStatus: string;
}
export default {
//订单分页列表
listPageWechatOrder(params: ListPageWechatOrderParams, options?: any): Promise<Response<ListPageWechatOrderResp>> {
return request('/oms/RentalOrders/listPageWechatOrder', 'post', params, options)
},
//订单状态-字典
listTranStatus(): Promise<Response<ListTranStatusResp[]>> {
return request('/oms/RentalOrders/listTranStatus', 'get');
}
}
\ No newline at end of file
import request, { Response } from "~/api/request"
export interface OrderDetailResp {
id: number;
orderNo: string;
createTime: number;
wareInfoId: number;
wareNo: string;
wareTitle: string;
wareImg: string;
skuInfoId?: any;
skuTitle?: any;
repoAccountId: number;
uid: string;
buyerName?: any;
buyerPhone: string;
unitPrice: number;
wareNum: number;
shouldPay: number; //应付款金额
actualPay: number; //实收款金额
orderType?: any;
deposit: number;
rentPrice: number;
startDate: number;
endDate: number;
payDay: number;
tranStatus: string;
exWare?: any;
remark: string;
pfRemark?: any;
shutReason?: any;
payNo?: any;
payTime?: any;
sendWareTime?: any;
receipt: Receipt;
orderRefund?: any;
express?: any;
refundExpress?: any;
vcus?: any;
returnTime?: any;
couponId?: any;
specsId?: any;
balance?: any;
doing: string;
waiting: string;
leaseOrderStatus: string;
nickName: string;
wareDescription: string;
}
interface Receipt {
id: number;
receiptMethod: number;
takeName: string;
takePhone: string;
region: string;
detailAddress: string;
repoName?: any;
repoAddress?: any;
bookPhone?: any;
sendExCode?: any;
sendExNo?: any;
sendAddress?: any;
renMethod?: any;
renPhone?: any;
renName?: any;
renExCode?: any;
renExNo?: any;
renAddress?: any;
renRepoName?: any;
renRepoAddr?: any;
renRepoPhone?: any;
}
export default {
//订单详情
orderDetail(params: {
orderNo: string
}): Promise<Response<OrderDetailResp>>{
return request('/oms/RentalOrders/orderDetail', 'get', params);
}
}
\ No newline at end of file
.font1 {
font-size: 36px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #ff440e;
line-height: 42px;
}
.font2 {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff440e;
line-height: 25px;
}
.font3 {
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #959595;
line-height: 21px;
}
.font4 {
font-size: 15px;
font-family: ArialMT;
color: #282828;
line-height: 21px;
}
.font5 {
font-size: 18px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 25px;
}
.btn {
background: linear-gradient(90deg, #ff552d 0%, #ff812d 100%);
border-radius: 6px;
height: 40px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 22px;
width: 100%;
}
import { Button, Col, Divider, Modal, Row } from "antd";
import { useContext, useEffect, useState } from "react";
import { UserContext } from "~/lib/userProvider";
import api, { OrderDetailResp } from "./api";
import styles from "./index.module.scss";
function formatNumber(num: number) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
type Props = {
open?: boolean;
onOk?: () => void;
onCancel?: () => void;
orderNo?: string;
};
export default function PayModal(props: Props) {
const [data, setData] = useState<OrderDetailResp | null>(null);
const { userInfo } = useContext(UserContext);
useEffect(() => {
if (props.orderNo) {
api.orderDetail({ orderNo: props.orderNo }).then((res) => {
setData(res.result || null);
});
} else {
setData(null);
}
}, [props.orderNo]);
return (
<>
<Modal
width={420}
open={props.open}
onOk={props.onOk}
onCancel={props.onCancel}
title={
<>
<div style={{ textAlign: "center" }} className={styles.font5}>
租赁付款
</div>
</>
}
footer={
<Button
type="primary"
className={styles.btn}
style={{ marginTop: 43 }}
>
立即付款
</Button>
}
>
<div
style={{ marginTop: 16, marginBottom: 34, textAlign: "center" }}
className={styles.font1}
>
{formatNumber(data?.shouldPay || 0)}{" "}
<span
className={styles.font2}
style={{ transform: "translateY(-3px)", display: "inline-block" }}
>
</span>
</div>
<Row gutter={[0, 16]}>
<Col span={6} className={styles.font3}>
云仓账号
</Col>
<Col span={18} className={styles.font4}>
UID{userInfo?.uid}
</Col>
<Col span={6} className={styles.font3}>
付款方式
</Col>
<Col span={18} className={styles.font4}>
充值余额(可用:¥2000000)
</Col>
</Row>
</Modal>
</>
);
}
import request, { Response } from "~/api/request"
export interface OrderDetailResp {
id: number;
orderNo: string;
createTime: number;
wareInfoId: number;
wareNo: string;
wareTitle: string;
wareImg: string;
skuInfoId?: any;
skuTitle?: any;
repoAccountId: number;
uid: string;
buyerName?: any;
buyerPhone: string;
unitPrice: number;
wareNum: number;
shouldPay: number; //应付款金额
actualPay: number; //实收款金额
orderType?: any;
deposit: number;
rentPrice: number;
startDate: number;
endDate: number;
payDay: number;
tranStatus: string;
exWare?: any;
remark: string;
pfRemark?: any;
shutReason?: any;
payNo?: any;
payTime?: any;
sendWareTime?: any;
receipt: Receipt;
orderRefund?: any;
express?: any;
refundExpress?: any;
vcus?: any;
returnTime?: any;
couponId?: any;
specsId?: any;
balance?: any;
doing: string;
waiting: string;
leaseOrderStatus: string;
nickName: string;
wareDescription: string;
}
interface Receipt {
id: number;
receiptMethod: number;
takeName: string;
takePhone: string;
region: string;
detailAddress: string;
repoName?: any;
repoAddress?: any;
bookPhone?: any;
sendExCode?: any;
sendExNo?: any;
sendAddress?: any;
renMethod?: any;
renPhone?: any;
renName?: any;
renExCode?: any;
renExNo?: any;
renAddress?: any;
renRepoName?: any;
renRepoAddr?: any;
renRepoPhone?: any;
}
export interface UserWalletResp {
id: number;
repoAccountId: number;
cashAmt: number;
cashPaid: number;
cashFreeze: number;
remark?: any;
phoneNum?: any;
userName?: any;
nickName?: any;
portType?: any;
uid?: any;
}
export default {
//订单详情
orderDetail(params: {
orderNo: string
}): Promise<Response<OrderDetailResp>> {
return request('/oms/RentalOrders/orderDetail', 'get', params);
},
//获取用户钱包
userWallet(): Promise<Response<UserWalletResp>> {
return request('/payment/repocash/userWallet')
},
//租赁——订单支付
orderPayment(params: { orderNo: string }) {
return request('/payment/repocash/orderPayment', 'post', params)
}
}
\ No newline at end of file
.font1 {
font-size: 36px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #ff440e;
line-height: 42px;
}
.font2 {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff440e;
line-height: 25px;
}
.font3 {
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #959595;
line-height: 21px;
}
.font4 {
font-size: 15px;
font-family: ArialMT;
color: #282828;
line-height: 21px;
}
.font5 {
font-size: 18px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 25px;
}
.btn {
background: linear-gradient(90deg, #ff552d 0%, #ff812d 100%);
border-radius: 6px;
height: 40px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 22px;
width: 100%;
}
import { Button, Col, Divider, message, Modal, Row } from "antd";
import { useContext, useEffect, useState } from "react";
import { UserContext } from "~/lib/userProvider";
import api, { OrderDetailResp, UserWalletResp } from "./api";
import styles from "./index.module.scss";
function formatNumber(num: number) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
type Props = {
open?: boolean;
onOk?: () => void;
onCancel?: () => void;
orderNo?: string;
};
export default function PayModal(props: Props) {
const [data, setData] = useState<OrderDetailResp | null>(null);
const { userInfo } = useContext(UserContext);
const [wallet, setWallet] = useState<UserWalletResp | null>(null); //钱包
const [loading, setLoading] = useState(false); //付款按钮loading
useEffect(() => {
if (props.open) {
api.userWallet().then((res) => {
setWallet(res.result || null);
});
}
}, [props.open]);
useEffect(() => {
if (props.orderNo) {
api.orderDetail({ orderNo: props.orderNo }).then((res) => {
setData(res.result || null);
});
} else {
setData(null);
}
}, [props.orderNo]);
function onPay() {
if (props.orderNo) {
setLoading(true);
api
.orderPayment({
orderNo: props.orderNo,
})
.then((res) => {
if (res.code == "200") {
message.success("付款成功");
setTimeout(() => {
props.onCancel && props.onCancel();
setLoading(false);
}, 1000);
}else{
res.message && message.error(res.message);
setLoading(false);
}
}).catch(err=> {
setLoading(false);
});
}
}
return (
<>
<Modal
width={420}
open={props.open}
onOk={props.onOk}
onCancel={props.onCancel}
title={
<>
<div style={{ textAlign: "center" }} className={styles.font5}>
租赁付款
</div>
</>
}
footer={
<Button
type="primary"
className={styles.btn}
style={{ marginTop: 43 }}
onClick={onPay}
loading={loading}
>
立即付款
</Button>
}
>
<div
style={{ marginTop: 16, marginBottom: 34, textAlign: "center" }}
className={styles.font1}
>
{formatNumber(data?.shouldPay || 0)}{" "}
<span
className={styles.font2}
style={{ transform: "translateY(-3px)", display: "inline-block" }}
>
</span>
</div>
<Row gutter={[0, 16]}>
<Col span={6} className={styles.font3}>
云仓账号
</Col>
<Col span={18} className={styles.font4}>
UID{userInfo?.uid}
</Col>
<Col span={6} className={styles.font3}>
付款方式
</Col>
<Col span={18} className={styles.font4}>
充值余额(可用:¥{wallet?.cashAmt}
</Col>
</Row>
</Modal>
</>
);
}
import request, { Response } from "~/api/request"
export interface OrderDetailResp {
id: number;
orderNo: string;
createTime: number;
wareInfoId: number;
wareNo: string;
wareTitle: string;
wareImg: string;
skuInfoId?: any;
skuTitle?: any;
repoAccountId: number;
uid: string;
buyerName?: any;
buyerPhone: string;
unitPrice: number;
wareNum: number;
shouldPay: number; //应付款金额
actualPay: number; //实收款金额
orderType?: any;
deposit: number;
rentPrice: number;
startDate: number;
endDate: number;
payDay: number;
tranStatus: string;
exWare?: any;
remark: string;
pfRemark?: any;
shutReason?: any;
payNo?: any;
payTime?: any;
sendWareTime?: any;
receipt: Receipt;
orderRefund?: any;
express?: any;
refundExpress?: any;
vcus?: any;
returnTime?: any;
couponId?: any;
specsId?: any;
balance?: any;
doing: string;
waiting: string;
leaseOrderStatus: string;
nickName: string;
wareDescription: string;
}
interface Receipt {
id: number;
receiptMethod: number;
takeName: string;
takePhone: string;
region: string;
detailAddress: string;
repoName?: any;
repoAddress?: any;
bookPhone?: any;
sendExCode?: any;
sendExNo?: any;
sendAddress?: any;
renMethod?: any;
renPhone?: any;
renName?: any;
renExCode?: any;
renExNo?: any;
renAddress?: any;
renRepoName?: any;
renRepoAddr?: any;
renRepoPhone?: any;
}
export interface UserWalletResp {
id: number;
repoAccountId: number;
cashAmt: number;
cashPaid: number;
cashFreeze: number;
remark?: any;
phoneNum?: any;
userName?: any;
nickName?: any;
portType?: any;
uid?: any;
}
export default {
//订单详情
orderDetail(params: {
orderNo: string
}): Promise<Response<OrderDetailResp>> {
return request('/oms/RentalOrders/orderDetail', 'get', params);
},
//获取用户钱包
userWallet(): Promise<Response<UserWalletResp>> {
return request('/payment/repocash/userWallet')
},
//租赁——订单支付
orderPayment(params: { orderNo: string }) {
return request('/payment/repocash/orderPayment', 'post', params)
}
}
\ No newline at end of file
.font1 {
font-size: 36px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #ff440e;
line-height: 42px;
}
.font2 {
font-size: 18px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff440e;
line-height: 25px;
}
.font3 {
font-size: 15px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #959595;
line-height: 21px;
}
.font4 {
font-size: 15px;
font-family: ArialMT;
color: #282828;
line-height: 21px;
}
.font5 {
font-size: 18px;
font-family: PingFangSC-Semibold, PingFang SC;
font-weight: 600;
color: #000000;
line-height: 25px;
}
.btn {
background: linear-gradient(90deg, #ff552d 0%, #ff812d 100%);
border-radius: 6px;
height: 40px;
font-size: 16px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 22px;
width: 100%;
}
import { Button, Col, Divider, message, Modal, Row } from "antd";
import { useContext, useEffect, useState } from "react";
import { UserContext } from "~/lib/userProvider";
import api, { OrderDetailResp, UserWalletResp } from "./api";
import styles from "./index.module.scss";
function formatNumber(num: number) {
return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
type Props = {
open?: boolean;
onOk?: () => void;
onCancel?: () => void;
orderNo?: string;
};
export default function RefundModal(props: Props) {
const [data, setData] = useState<OrderDetailResp | null>(null);
const { userInfo } = useContext(UserContext);
const [wallet, setWallet] = useState<UserWalletResp | null>(null); //钱包
const [loading, setLoading] = useState(false); //付款按钮loading
useEffect(() => {
if (props.open) {
api.userWallet().then((res) => {
setWallet(res.result || null);
});
}
}, [props.open]);
useEffect(() => {
if (props.orderNo) {
api.orderDetail({ orderNo: props.orderNo }).then((res) => {
setData(res.result || null);
});
} else {
setData(null);
}
}, [props.orderNo]);
function onPay() {
if (props.orderNo) {
setLoading(true);
api
.orderPayment({
orderNo: props.orderNo,
})
.then((res) => {
if (res.code == "200") {
message.success("付款成功");
setTimeout(() => {
props.onCancel && props.onCancel();
setLoading(false);
}, 1000);
} else {
res.message && message.error(res.message);
setLoading(false);
}
})
.catch((err) => {
setLoading(false);
});
}
}
return (
<>
<Modal
width={420}
open={props.open}
onOk={props.onOk}
onCancel={props.onCancel}
title={
<>
<div style={{ textAlign: "center" }} className={styles.font5}>
租赁付款
</div>
</>
}
footer={
<Button
type="primary"
className={styles.btn}
style={{ marginTop: 43 }}
onClick={onPay}
loading={loading}
>
立即付款
</Button>
}
>
<div
style={{ marginTop: 16, marginBottom: 34, textAlign: "center" }}
className={styles.font1}
>
{formatNumber(data?.shouldPay || 0)}{" "}
<span
className={styles.font2}
style={{ transform: "translateY(-3px)", display: "inline-block" }}
>
</span>
</div>
<Row gutter={[0, 16]}>
<Col span={6} className={styles.font3}>
云仓账号
</Col>
<Col span={18} className={styles.font4}>
UID{userInfo?.uid}
</Col>
<Col span={6} className={styles.font3}>
付款方式
</Col>
<Col span={18} className={styles.font4}>
充值余额(可用:¥{wallet?.cashAmt}
</Col>
</Row>
</Modal>
</>
);
}
@import "~/styles/mixins.scss";
.font1 {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #9b9b9b;
line-height: 19px;
}
.font2 {
font-size: 12px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #626262;
line-height: 14px;
}
.font3 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6c6c6c;
line-height: 20px;
}
.font4 {
font-size: 14px;
font-family: ArialMT;
color: #141414;
line-height: 16px;
}
.font5 {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
.font6 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #070707;
line-height: 20px;
}
.font7 {
font-size: 13px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #070707;
line-height: 16px;
}
.btn1 {
border-radius: 16px;
border: 1px solid #ff552d;
padding: 6px 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff552d;
line-height: 20px;
}
.btn2 {
border-radius: 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 20px;
padding: 6px 16px;
}
import {
TabsProps,
Tabs,
Row,
Col,
Image,
Space,
Button,
Pagination,
Empty,
Spin,
} from "antd";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import errImg from "~/assets/errImg";
import LayoutView from "~/components/layout";
import Sider from "../components/sider";
import styles from "./index.module.scss";
import api, { LeasingList, ListTranStatusResp } from "./api";
import moment from "moment";
import PayModal from "./components/payModal";
import RefundModal from "./components/refundModal";
import Moment from 'moment';
const items: TabsProps["items"] = [
{
key: "",
label: `全部`,
},
{
key: "100",
label: `待付款`,
},
{
key: "200",
label: `待发货`,
},
{
key: "400",
label: `租赁中`,
},
{
key: "500",
label: `归还中`,
},
{
key: "600",
label: `已完成`,
},
{
key: "700",
label: `退款/售后`,
},
{
key: "999",
label: `已关闭`,
},
];
export default function LeasingOrders() {
const router = useRouter();
const [pageParams, setPageParams] = useState({
pageNo: 1,
pageSize: 5,
}); //分页器对象
const [total, setTotal] = useState(0); //总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断对你
const [tabKey, setTabKey] = useState("");
const [orderList, setOrderList] = useState<LeasingList[]>([]);
const [loading, setLoading] = useState(false);
const [tranStatusMap, setTranStatusMap] = useState<ListTranStatusResp[]>([]); //订单状态字典
const [openPayModal, setOpenPayModal] = useState(false); //支付弹窗
const [openRefundModal, setOpenRefundModal] = useState(false); //退款弹窗
const [orderNo, setOrderNo] = useState<string | undefined>();
//获取订单状态字典
useEffect(() => {
api.listTranStatus().then((res) => {
setTranStatusMap(res.result || []);
});
}, []);
useEffect(() => {
//中断前一次列表请求
abort?.abort();
setAbort(new AbortController());
}, [pageParams]);
//商品列表请求
useEffect(() => {
if (!abort) {
return;
}
setLoading(true);
api
.listPageWechatOrder(
{
...pageParams,
tranStatus: tabKey,
},
{
signal: abort?.signal,
}
)
.then((res) => {
setOrderList(res.result?.list || []);
setTotal(res.result?.totalCount || 0);
setLoading(false);
});
}, [abort]);
const onPageChange = (page: number, pageSize: number) => {
setPageParams({
...pageParams,
pageNo: page,
});
};
const onTabsChange = (key: string) => {
setTabKey(key);
setPageParams({
...pageParams,
pageNo: 1,
});
setTotal(0);
};
// 交易状态对应的按钮渲染
const statusBtn = function (item: LeasingList) {
switch (item.tranStatus) {
case "100":
return (
<Button
className={styles.btn2}
type="primary"
onClick={() => {
setOrderNo(item.orderNo);
setOpenPayModal(true);
}}
>
立即付款
</Button>
);
case "200":
return (
<Button
className={styles.btn1}
onClick={() => {
setOrderNo(item.orderNo);
setOpenRefundModal(true);
}}
>
申请退款
</Button>
);
case "300":
return (
<Space size={0} direction="vertical" align="center">
<Button className={styles.btn2} type="primary">
确认收货
</Button>
<Button type="link" style={{ fontSize: 10 }}>
查看物流
</Button>
</Space>
);
case "400":
return (
<Space size={0} direction="vertical" align="center">
<Button className={styles.btn2} type="primary">
商品归还
</Button>
<Button type="link" style={{ fontSize: 10 }}>
查看物流
</Button>
</Space>
);
case "500":
<Button type="link" style={{ marginTop: 10 }}>
查看物流
</Button>;
case "600":
return <Button className={styles.btn1}>再来一单</Button>;
}
};
return (
<>
<LayoutView
layoutStyle={{ backgroundColor: "#fff" }}
contentStyle={{ width: 1000, marginLeft: 526 }}
headerStyle={{ borderBottom: "1px solid #e2e2e2" }}
>
<Sider
style={{
position: "absolute",
left: -37,
top: 15,
transform: "translateX(-100%)",
}}
selectedKeys={[router.pathname]}
></Sider>
<div style={{ paddingTop: 19 }}>
<div className={styles.font1}>租赁订单</div>
<Tabs activeKey={tabKey} items={items} onChange={onTabsChange} />
<Spin spinning={loading} delay={500}>
<ul className={styles.orderList} style={{ minHeight: 650 }}>
{orderList.map((item) => {
return (
<li key={item.id} className={styles.orderItem}>
<Row
justify="space-between"
align="middle"
style={{
height: 30,
padding: "0 26px 0 16px",
background: "#EBF8FF",
}}
>
<div className={styles.font2}>
<Space size={10}>
<div>
{Moment(item.startDate).format("YYYY-MM-DD")}{" "}
{Moment(item.endDate).format("YYYY-MM-DD")}
</div>
<div>订单编号: {item.orderNo}</div>
</Space>{" "}
</div>
<div className={styles.font3}>
{
tranStatusMap.find(
(sItem) => sItem.status === item.tranStatus
)?.waiting
}
</div>
</Row>
<Row
style={{ minHeight: 100, border: "1px solid #D0EAF5" }}
>
<Col style={{ width: 380 }}>
<Row>
<div style={{ margin: "10px 10px 0 16px" }}>
<Image
width={80}
height={80}
preview={false}
fallback={errImg}
src={item.wareImg}
></Image>
</div>
<div style={{ marginTop: 12 }}>
<div className={`ellipsis1 ${styles.font4}`}>
{item.wareTitle}
</div>
<div
className={`${styles.font5} ${styles.ellipse2}`}
style={{ marginTop: 5 }}
>
{item.wareDescription}
</div>
</div>
</Row>
</Col>
<Col
style={{
width: 270,
borderLeft: "1px solid #D0EAF5",
borderRight: "1px solid #D0EAF5",
}}
>
<Row
justify={"center"}
align="middle"
style={{ height: "100%" }}
>
<div style={{ textAlign: "center" }}>
<div
className={styles.font7}
style={{ marginBottom: 7 }}
>
¥{item.shouldPay}
</div>
<div className={styles.font6}>
租期:{" "}
{moment(item.endDate).diff(
item.startDate,
"days"
)}
</div>
<div className={styles.font6}>
数量: {item.wareNum}
</div>
</div>
</Row>
</Col>
<Col flex={"auto"} style={{}}>
<Space
size={7}
style={{
float: "right",
marginTop: 20,
marginRight: 24,
}}
>
{statusBtn(item)}
</Space>
</Col>
</Row>
</li>
);
})}
{orderList.length === 0 && (
<Empty
style={{
paddingTop: 20,
width: "100%",
textAlign: "center",
}}
></Empty>
)}
</ul>
</Spin>
<Pagination
current={pageParams.pageNo}
showSizeChanger={false}
showQuickJumper
total={total}
pageSize={pageParams.pageSize}
onChange={onPageChange}
hideOnSinglePage={true}
style={{ marginTop: 20 }}
></Pagination>
</div>
</LayoutView>
<PayModal
open={openPayModal}
onCancel={() => setOpenPayModal(false)}
orderNo={orderNo}
></PayModal>
<RefundModal
open={openRefundModal}
onCancel={() => setOpenRefundModal(false)}
orderNo={orderNo}
></RefundModal>
</>
);
}
import request, { Response } from "~/api/request"
export interface ListPageParams {
keyword?: string,
showType: number,
pageNo: number;
pageSize: number;
}
export interface ListPageResp {
pageNo: number;
pageSize: number;
list: OrderList[];
totalCount: number;
totalPage: number;
}
export interface OrderList {
id: number;
orderNo: string;
orderMainImg: string;
orderName: string;
totalBuyNum: number;
orderAmount: number;
statusCode: number;
signStatus?: any;
operationName?: any;
operationId?: any;
deliveryTime?: any;
contractNo?: any;
userAccountId: number;
uid?: any;
userName?: any;
phoneNum?: any;
payMethod: number;
contractSignedWay?: any;
createTime: string;
recMallUserName?: any;
ogSkuSpecDTOList: OgSkuSpecDTOList[];
remark: string;
creditPeriod?: any;
entName?: any;
saleId?: any;
saleName?: any;
tagName?: any;
realNameAuth?: any;
realPayAmount?: any;
subAmount?: any;
shareId?: any;
shareStatus: number;
deductAmount?: any;
discountAmount?: any;
realityAmount?: any;
shutReason?: any;
mallOrderProdListDTOList: MallOrderProdListDTOList[];
mremark?: any;
}
interface MallOrderProdListDTOList {
id: number;
goodsInfoId: number;
productName: string;
model?: any;
prodSkuSpecName: string;
prodSkuSpecImage: string;
partNo: string;
versionDesc: string;
buyNum: number;
unitPrice: number;
skuSpecAmount: number;
}
interface OgSkuSpecDTOList {
id: number;
directoryId: number;
shopCarId?: any;
skuSpecName: string;
}
export interface ListStatusResp {
status: string;
code: number;
nextCode: number;
}
export default {
//v1.0.0订单列表-查询
listPage(params: ListPageParams, options: any): Promise<Response<ListPageResp>> {
return request('/oms/app-order/listPage', 'get', params, options)
},
//订单状态-字典
listStatus(): Promise<Response<ListStatusResp[]>> {
return request('/oms/mallorder/listStatus', 'get');
}
}
\ No newline at end of file
@import "~/styles/mixins.scss";
.font1 {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #9b9b9b;
line-height: 19px;
}
.font2 {
font-size: 12px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #626262;
line-height: 14px;
}
.font3 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6c6c6c;
line-height: 20px;
}
.font4 {
font-size: 14px;
font-family: ArialMT;
color: #141414;
line-height: 16px;
}
.font5 {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
.btn1 {
border-radius: 16px;
border: 1px solid #ff552d;
padding: 6px 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff552d;
line-height: 20px;
}
.btn2 {
border-radius: 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 20px;
padding: 6px 16px;
}
import {
TabsProps,
Tabs,
Row,
Col,
Image,
Space,
Button,
Spin,
Pagination,
Empty,
} from "antd";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import errImg from "~/assets/errImg";
import Right from "~/components/contentBox/right";
import LayoutView from "~/components/layout";
import Sider from "../components/sider";
import api, { OrderList, ListStatusResp } from "./api";
import styles from "./index.module.scss";
const items: TabsProps["items"] = [
{
key: "",
label: `全部`,
},
{
key: "0",
label: `意向沟通`,
},
{
key: "1",
label: `签约付款`,
},
{
key: "2",
label: `待发货`,
},
{
key: "3",
label: `待收货`,
},
];
export default function LeasingOrder() {
const router = useRouter();
const [pageParams, setPageParams] = useState({
pageNo: 1,
pageSize: 5,
}); //分页器对象
const [total, setTotal] = useState(0); //总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断对你
const [tabKey, setTabKey] = useState("");
const [orderList, setOrderList] = useState<OrderList[]>([]);
const [loading, setLoading] = useState(false);
const [orderNo, setOrderNo] = useState<string | undefined>();
const [tranStatusMap, setTranStatusMap] = useState<ListStatusResp[]>([]); //订单状态字典
//获取订单状态字典
useEffect(() => {
api.listStatus().then((res) => {
setTranStatusMap(res.result || []);
});
}, []);
useEffect(() => {
//中断前一次列表请求
abort?.abort();
setAbort(new AbortController());
}, [pageParams]);
//商品列表请求
useEffect(() => {
if (!abort) {
return;
}
setLoading(true);
api
.listPage(
{
...pageParams,
showType: Number(tabKey),
},
{
signal: abort?.signal,
}
)
.then((res) => {
setOrderList(res.result?.list || []);
setTotal(res.result?.totalCount || 0);
setLoading(false);
});
}, [abort]);
const onPageChange = (page: number, pageSize: number) => {
setPageParams({
...pageParams,
pageNo: page,
});
};
const onTabsChange = (key: string) => {
setTabKey(key);
setPageParams({
...pageParams,
pageNo: 1,
});
setTotal(0);
};
return (
<>
<LayoutView
layoutStyle={{ backgroundColor: "#fff" }}
contentStyle={{ width: 1000, marginLeft: 526 }}
headerStyle={{ borderBottom: "1px solid #e2e2e2" }}
>
<Sider
style={{
position: "absolute",
left: -37,
top: 15,
transform: "translateX(-100%)",
}}
selectedKeys={[router.pathname]}
></Sider>
<div style={{ paddingTop: 19 }}>
<div className={styles.font1}>商城订单</div>
<Tabs activeKey={tabKey} items={items} onChange={onTabsChange} />
<Spin spinning={loading} delay={500}>
<ul className={styles.orderList} style={{ minHeight: 650 }}>
{orderList.map((item) => {
return (
<li key={item.id} className={styles.orderItem}>
<Row
justify="space-between"
align="middle"
style={{
height: 30,
padding: "0 26px 0 16px",
background: "#EBF8FF",
}}
>
<div className={styles.font2}>
<Space size={10}>
<div>{item.createTime}</div>
<div>订单编号: {item.orderNo}</div>
</Space>
</div>
<div className={styles.font3}>
{
tranStatusMap.find(
(status) => status.code === item.statusCode
)?.status
}
</div>
</Row>
<Row
style={{ minHeight: 100, border: "1px solid #D0EAF5" }}
>
<Col style={{ width: 380 }}>
<Row>
<div style={{ margin: "10px 10px 0 16px" }}>
<Image
width={80}
height={80}
preview={false}
fallback={errImg}
src={item.orderMainImg}
></Image>
</div>
<div style={{ marginTop: 12 }}>
<div className={`ellipsis1 ${styles.font4}`}>
{item.orderName}
</div>
{item.mallOrderProdListDTOList.map((spec) => {
return (
<div
key={spec.id}
className={styles.font5}
style={{ marginTop: 5 }}
>
{spec.prodSkuSpecName}: {spec.productName}
</div>
);
})}
</div>
</Row>
</Col>
<Col
style={{
width: 270,
borderLeft: "1px solid #D0EAF5",
borderRight: "1px solid #D0EAF5",
}}
>
<Row
justify={"center"}
align="middle"
style={{ height: "100%" }}
>
数量: {item.totalBuyNum}
</Row>
</Col>
<Col flex={"auto"} style={{}}>
<Space
size={7}
style={{
float: "right",
marginTop: 20,
marginRight: 24,
}}
>
<Button className={styles.btn1}>取消订单</Button>
<Button className={styles.btn2} type="primary">
查看合同
</Button>
</Space>
</Col>
</Row>
</li>
);
})}
{orderList.length === 0 && (
<Empty
style={{
paddingTop: 20,
width: "100%",
textAlign: "center",
}}
></Empty>
)}
</ul>
</Spin>
<Pagination
current={pageParams.pageNo}
showSizeChanger={false}
showQuickJumper
total={total}
pageSize={pageParams.pageSize}
onChange={onPageChange}
hideOnSinglePage={true}
style={{ marginTop: 20 }}
></Pagination>
</div>
</LayoutView>
</>
);
}
import request, { Response } from "~/api/request"
export interface QueryOrderTaskListParams {
orderStatus?: number;
pageNo: number;
pageSize: number;
}
export interface QueryOrderTaskListResp {
pageNo: number;
pageSize: number;
list: OrderList[];
totalCount: number;
totalPage: number;
}
export interface OrderList {
id: number;
address: string;
city: string;
endTime: string;
images: any[];
inspectionId: number;
lat: number;
lon: number;
orderAmt: number;
orderName: string;
orderStatus: number,
orderNo: string;
province: string;
startTime: string;
taskDescription: string;
coverPlan: string;
}
export interface GetServiceOrderStatusResp {
id: number;
orderStatus: number;
userPort: string;
flyerPort: string;
managePort: string;
}
export default {
//查询服务订单列表
queryOrderTaskList(params: QueryOrderTaskListParams, options: any): Promise<Response<QueryOrderTaskListResp>> {
return request('/oms/serviceOrderTask/queryOrderTaskList', 'post', params, options)
},
//订单状态-字典
getServiceOrderStatus(): Promise<Response<GetServiceOrderStatusResp[]>> {
return request('/oms/serviceOrderTask/getServiceOrderStatus', 'POST');
}
}
\ No newline at end of file
@import "~/styles/mixins.scss";
.font1 {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #9b9b9b;
line-height: 19px;
}
.font2 {
font-size: 12px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #626262;
line-height: 14px;
}
.font3 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6c6c6c;
line-height: 20px;
}
.font4 {
font-size: 14px;
font-family: ArialMT;
color: #141414;
line-height: 16px;
}
.font5 {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
.font6 {
font-size: 13px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #070707;
line-height: 16px;
}
.btn1 {
border-radius: 16px;
border: 1px solid #ff552d;
padding: 6px 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff552d;
line-height: 20px;
}
.btn2 {
border-radius: 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 20px;
padding: 6px 16px;
}
import {
TabsProps,
Tabs,
Row,
Col,
Image,
Space,
Button,
Spin,
Pagination,
Empty,
} from "antd";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import errImg from "~/assets/errImg";
import Right from "~/components/contentBox/right";
import LayoutView from "~/components/layout";
import Sider from "../components/sider";
import api, { OrderList, GetServiceOrderStatusResp } from "./api";
import styles from "./index.module.scss";
import Moment from "moment";
const items: TabsProps["items"] = [
{
key: "",
label: `全部`,
},
{
key: "200",
label: `待付款`,
},
{
key: "575",
label: `待验收`,
},
{
key: "700",
label: `已完成`,
},
{
key: "900",
label: `已取消`,
},
];
export default function ServicesOrder() {
const router = useRouter();
const [pageParams, setPageParams] = useState({
pageNo: 1,
pageSize: 5,
}); //分页器对象
const [total, setTotal] = useState(0); //总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断对你
const [tabKey, setTabKey] = useState("");
const [orderList, setOrderList] = useState<OrderList[]>([]);
const [loading, setLoading] = useState(false);
const [orderNo, setOrderNo] = useState<string | undefined>();
const [tranStatusMap, setTranStatusMap] = useState<
GetServiceOrderStatusResp[]
>([]); //订单状态字典
//获取订单状态字典
useEffect(() => {
api.getServiceOrderStatus().then((res) => {
setTranStatusMap(res.result || []);
});
}, []);
useEffect(() => {
//中断前一次列表请求
abort?.abort();
setAbort(new AbortController());
}, [pageParams]);
//商品列表请求
useEffect(() => {
if (!abort) {
return;
}
setLoading(true);
api
.queryOrderTaskList(
{
...pageParams,
orderStatus: Number(tabKey),
},
{
signal: abort?.signal,
}
)
.then((res) => {
console.log(", res.result?.list", res.result?.list);
setOrderList(res.result?.list || []);
setTotal(res.result?.totalCount || 0);
setLoading(false);
});
}, [abort]);
const onPageChange = (page: number, pageSize: number) => {
setPageParams({
...pageParams,
pageNo: page,
});
};
const onTabsChange = (key: string) => {
setTabKey(key);
setPageParams({
...pageParams,
pageNo: 1,
});
setTotal(0);
};
return (
<>
<LayoutView
layoutStyle={{ backgroundColor: "#fff" }}
contentStyle={{ width: 1000, marginLeft: 526 }}
headerStyle={{ borderBottom: "1px solid #e2e2e2" }}
>
<Sider
style={{
position: "absolute",
left: -37,
top: 15,
transform: "translateX(-100%)",
}}
selectedKeys={[router.pathname]}
></Sider>
<div style={{ paddingTop: 19 }}>
<div className={styles.font1}>服务订单</div>
<Tabs activeKey={tabKey} items={items} onChange={onTabsChange} />
<Spin spinning={loading} delay={500}>
<ul className={styles.orderList} style={{ minHeight: 650 }}>
{orderList.map((item) => {
return (
<li key={item.id} className={styles.orderItem}>
<Row
justify="space-between"
align="middle"
style={{
height: 30,
padding: "0 26px 0 16px",
background: "#EBF8FF",
}}
>
<div className={styles.font2}>
<Space size={10}>
<div>
{Moment(item.startTime).format("YYYY-MM-DD")}{" "}
{Moment(item.endTime).format("YYYY-MM-DD")}
</div>
<div>订单编号: {item.orderNo}</div>
</Space>
</div>
<div className={styles.font3}>
{
tranStatusMap.find(
(status) => status.orderStatus === item.orderStatus
)?.userPort
}
</div>
</Row>
<Row
style={{ minHeight: 100, border: "1px solid #D0EAF5" }}
>
<Col style={{ width: 380 }}>
<Row>
<div style={{ margin: "10px 10px 0 16px" }}>
<Image
width={80}
height={80}
preview={false}
fallback={errImg}
src={item.coverPlan}
></Image>
</div>
<div style={{ marginTop: 12 }}>
<div className={`ellipsis1 ${styles.font4}`}>
{item.orderName}
</div>
</div>
</Row>
</Col>
<Col
style={{
width: 270,
borderLeft: "1px solid #D0EAF5",
borderRight: "1px solid #D0EAF5",
}}
>
<Row
justify={"center"}
align="middle"
style={{ height: "100%" }}
>
预付金额:{" "}
<span className={styles.font6}>¥{item.orderAmt}</span>
</Row>
</Col>
<Col flex={"auto"} style={{}}>
<Space
size={7}
style={{
float: "right",
marginTop: 20,
marginRight: 24,
}}
>
<Space direction="vertical" size={0} align="center">
<Button className={styles.btn2} type="primary">
预付款
</Button>
<Button type="text">取消订单</Button>
</Space>
</Space>
</Col>
</Row>
</li>
);
})}
{orderList.length === 0 && (
<Empty
style={{
paddingTop: 20,
width: "100%",
textAlign: "center",
}}
></Empty>
)}
</ul>
</Spin>
<Pagination
current={pageParams.pageNo}
showSizeChanger={false}
showQuickJumper
total={total}
pageSize={pageParams.pageSize}
onChange={onPageChange}
hideOnSinglePage={true}
style={{ marginTop: 20 }}
></Pagination>
</div>
</LayoutView>
</>
);
}
import request, { Response } from "~/api/request"
export interface ListPageParams {
keyword?: string,
showType: number,
pageNo: number;
pageSize: number;
}
export interface ListPageResp {
pageNo: number;
pageSize: number;
list: OrderList[];
totalCount: number;
totalPage: number;
}
export interface OrderList {
id: number;
orderNo: string;
orderMainImg: string;
orderName: string;
totalBuyNum: number;
orderAmount: number;
statusCode: number;
signStatus?: any;
operationName?: any;
operationId?: any;
deliveryTime?: any;
contractNo?: any;
userAccountId: number;
uid?: any;
userName?: any;
phoneNum?: any;
payMethod: number;
contractSignedWay?: any;
createTime: string;
recMallUserName?: any;
ogSkuSpecDTOList: OgSkuSpecDTOList[];
remark: string;
creditPeriod?: any;
entName?: any;
saleId?: any;
saleName?: any;
tagName?: any;
realNameAuth?: any;
realPayAmount?: any;
subAmount?: any;
shareId?: any;
shareStatus: number;
deductAmount?: any;
discountAmount?: any;
realityAmount?: any;
shutReason?: any;
mallOrderProdListDTOList: MallOrderProdListDTOList[];
mremark?: any;
}
interface MallOrderProdListDTOList {
id: number;
goodsInfoId: number;
productName: string;
model?: any;
prodSkuSpecName: string;
prodSkuSpecImage: string;
partNo: string;
versionDesc: string;
buyNum: number;
unitPrice: number;
skuSpecAmount: number;
}
interface OgSkuSpecDTOList {
id: number;
directoryId: number;
shopCarId?: any;
skuSpecName: string;
}
export interface ListStatusResp {
status: string;
code: number;
nextCode: number;
}
export default {
//v1.0.0订单列表-查询
listPage(params: ListPageParams, options: any): Promise<Response<ListPageResp>> {
return request('/oms/app-order/listPage', 'get', params, options)
},
//订单状态-字典
listStatus(): Promise<Response<ListStatusResp[]>> {
return request('/oms/mallorder/listStatus', 'get');
}
}
\ No newline at end of file
@import "~/styles/mixins.scss";
.font1 {
font-size: 14px;
font-family: MicrosoftYaHei;
color: #9b9b9b;
line-height: 19px;
}
.font2 {
font-size: 12px;
font-family: Arial-BoldMT, Arial;
font-weight: normal;
color: #626262;
line-height: 14px;
}
.font3 {
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #6c6c6c;
line-height: 20px;
}
.font4 {
font-size: 14px;
font-family: ArialMT;
color: #141414;
line-height: 16px;
}
.font5 {
font-size: 12px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #929295;
line-height: 17px;
}
.font6 {
font-size: 13px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold;
color: #070707;
line-height: 16px;
}
.btn1 {
border-radius: 16px;
border: 1px solid #ff552d;
padding: 6px 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ff552d;
line-height: 20px;
}
.btn2 {
border-radius: 16px;
font-size: 14px;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 20px;
padding: 6px 16px;
}
import {
TabsProps,
Tabs,
Row,
Col,
Image,
Space,
Button,
Spin,
Pagination,
Empty,
} from "antd";
import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import errImg from "~/assets/errImg";
import Right from "~/components/contentBox/right";
import LayoutView from "~/components/layout";
import Sider from "../components/sider";
import api, { OrderList, ListStatusResp } from "./api";
import styles from "./index.module.scss";
const items: TabsProps["items"] = [
{
key: "",
label: `全部`,
},
{
key: "0",
label: `待付款`,
},
{
key: "1",
label: `待验收`,
},
{
key: "2",
label: `已完成`,
},
{
key: "3",
label: `已取消`,
},
];
export default function TrainOrder() {
const router = useRouter();
const [pageParams, setPageParams] = useState({
pageNo: 1,
pageSize: 5,
}); //分页器对象
const [total, setTotal] = useState(0); //总数
const [abort, setAbort] = useState<AbortController | null>(null); //请求中断对你
const [tabKey, setTabKey] = useState("");
const [orderList, setOrderList] = useState<OrderList[]>([]);
const [loading, setLoading] = useState(false);
const [orderNo, setOrderNo] = useState<string | undefined>();
const [tranStatusMap, setTranStatusMap] = useState<ListStatusResp[]>([]); //订单状态字典
//获取订单状态字典
useEffect(() => {
api.listStatus().then((res) => {
setTranStatusMap(res.result || []);
});
}, []);
useEffect(() => {
//中断前一次列表请求
abort?.abort();
setAbort(new AbortController());
}, [pageParams]);
//商品列表请求
useEffect(() => {
if (!abort) {
return;
}
setLoading(true);
api
.listPage(
{
...pageParams,
showType: Number(tabKey),
},
{
signal: abort?.signal,
}
)
.then((res) => {
setOrderList(res.result?.list || []);
setTotal(res.result?.totalCount || 0);
setLoading(false);
});
}, [abort]);
const onPageChange = (page: number, pageSize: number) => {
setPageParams({
...pageParams,
pageNo: page,
});
};
const onTabsChange = (key: string) => {
setTabKey(key);
setPageParams({
...pageParams,
pageNo: 1,
});
setTotal(0);
};
return (
<>
<LayoutView
layoutStyle={{ backgroundColor: "#fff" }}
contentStyle={{ width: 1000, marginLeft: 526 }}
headerStyle={{ borderBottom: "1px solid #e2e2e2" }}
>
<Sider
style={{
position: "absolute",
left: -37,
top: 15,
transform: "translateX(-100%)",
}}
selectedKeys={[router.pathname]}
></Sider>
<div style={{ paddingTop: 19 }}>
<div className={styles.font1}>培训订单</div>
<Tabs activeKey={tabKey} items={items} onChange={onTabsChange} />
<Spin spinning={loading} delay={500}>
<ul className={styles.orderList} style={{ minHeight: 650 }}>
{orderList.map((item) => {
return (
<li key={item.id} className={styles.orderItem}>
<Row
justify="space-between"
align="middle"
style={{
height: 30,
padding: "0 26px 0 16px",
background: "#EBF8FF",
}}
>
<div className={styles.font2}>{item.createTime}</div>
<div className={styles.font3}>
{
tranStatusMap.find(
(status) => status.code === item.statusCode
)?.status
}
</div>
</Row>
<Row
style={{ minHeight: 100, border: "1px solid #D0EAF5" }}
>
<Col style={{ width: 380 }}>
<Row>
<div style={{ margin: "10px 10px 0 16px" }}>
<Image
width={80}
height={80}
preview={false}
fallback={errImg}
src={item.orderMainImg}
></Image>
</div>
<div style={{ marginTop: 12 }}>
<div className={`ellipsis1 ${styles.font4}`}>
{item.orderName}
</div>
</div>
</Row>
</Col>
<Col
style={{
width: 270,
borderLeft: "1px solid #D0EAF5",
borderRight: "1px solid #D0EAF5",
}}
>
<Row
justify={"center"}
align="middle"
style={{ height: "100%" }}
>
预付金额:{" "}
<span className={styles.font6}>
¥{item.totalBuyNum}
</span>
</Row>
</Col>
<Col flex={"auto"} style={{}}>
<Space
size={7}
style={{
float: "right",
marginTop: 20,
marginRight: 24,
}}
>
<Button className={styles.btn1}>取消订单</Button>
<Button className={styles.btn2} type="primary">
查看合同
</Button>
</Space>
</Col>
</Row>
</li>
);
})}
{orderList.length === 0 && (
<Empty
style={{
paddingTop: 20,
width: "100%",
textAlign: "center",
}}
></Empty>
)}
</ul>
</Spin>
<Pagination
current={pageParams.pageNo}
showSizeChanger={false}
showQuickJumper
total={total}
pageSize={pageParams.pageSize}
onChange={onPageChange}
hideOnSinglePage={true}
style={{ marginTop: 20 }}
></Pagination>
</div>
</LayoutView>
</>
);
}
...@@ -101,7 +101,7 @@ export default function Bids(props: Props) { ...@@ -101,7 +101,7 @@ export default function Bids(props: Props) {
<Button type="primary" className={styles.btn}> <Button type="primary" className={styles.btn}>
<div className={styles.text1}>{item.tenderPrice}</div> <div className={styles.text1}>{item.tenderPrice}</div>
<div className={styles.text2} onClick={() => onApply(item)}> <div className={styles.text2} onClick={() => onApply(item)}>
申请合作 商务合作
</div> </div>
</Button> </Button>
)} )}
......
...@@ -86,7 +86,7 @@ export default function Cases(props: Props) { ...@@ -86,7 +86,7 @@ export default function Cases(props: Props) {
Router.push("/projectInfo/caseArticle/" + item.id) Router.push("/projectInfo/caseArticle/" + item.id)
} }
> >
申请合作 联系品牌厂家
</Button> </Button>
</div> </div>
); );
......
...@@ -2,10 +2,11 @@ import { RightOutlined } from "@ant-design/icons"; ...@@ -2,10 +2,11 @@ import { RightOutlined } from "@ant-design/icons";
import { Button, Col, Empty, Pagination, Row, Spin } from "antd"; import { Button, Col, Empty, Pagination, Row, Spin } from "antd";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import Image from "next/image"; import Image from "next/image";
import { useState, useEffect } from "react"; import { useState, useEffect, useContext } from "react";
import api, { Item } from "./api"; import api, { Item } from "./api";
import { useRouter } from "next/router"; import Router from "next/router";
import Moment from "moment"; import Moment from "moment";
import { UserContext } from "~/lib/userProvider";
type Props = { type Props = {
params?: { params?: {
...@@ -25,7 +26,7 @@ export default function News(props: Props) { ...@@ -25,7 +26,7 @@ export default function News(props: Props) {
}); });
const [count, setCount] = useState(0); const [count, setCount] = useState(0);
const [abort, setAbort] = useState<AbortController | null>(null); const [abort, setAbort] = useState<AbortController | null>(null);
const router = useRouter(); const { userInfo, setNeedLogin } = useContext(UserContext);
useEffect(() => { useEffect(() => {
//中断前一次请求 //中断前一次请求
...@@ -62,6 +63,19 @@ export default function News(props: Props) { ...@@ -62,6 +63,19 @@ export default function News(props: Props) {
}); });
}; };
//获取产品信息事件
const onGetInfo = () => {
if(userInfo){
if(userInfo.companyAuthStatus){
}else{
Router.push("/certification?type=back");
}
}else{
setNeedLogin(true);
}
}
return ( return (
<Spin spinning={loading} delay={500}> <Spin spinning={loading} delay={500}>
<Row justify="space-between" style={{ height: 606 }}> <Row justify="space-between" style={{ height: 606 }}>
...@@ -86,11 +100,9 @@ export default function News(props: Props) { ...@@ -86,11 +100,9 @@ export default function News(props: Props) {
<Button <Button
type="primary" type="primary"
style={{ width: 120, height: 40, flexShrink: 0 }} style={{ width: 120, height: 40, flexShrink: 0 }}
onClick={() => onClick={onGetInfo}
router.push("/projectInfo/newsArticle/" + item.id)
}
> >
申请合作 获取产品资料
</Button> </Button>
</div> </div>
); );
......
...@@ -23,7 +23,7 @@ export interface Params { ...@@ -23,7 +23,7 @@ export interface Params {
} }
const items = (params: any) => const items = (params: any) =>
["项目需求", "招投标项目", "业务案例", "行业新闻"].map((value) => { [/* "项目需求", */ "招投标项目", "项目案例", "行业新闻"].map((value) => {
let children: JSX.Element | string = <></>; let children: JSX.Element | string = <></>;
switch (value) { switch (value) {
...@@ -35,7 +35,7 @@ const items = (params: any) => ...@@ -35,7 +35,7 @@ const items = (params: any) =>
children = <Bids params={params}></Bids>; children = <Bids params={params}></Bids>;
break; break;
case "业务案例": case "项目案例":
children = <Cases params={params}></Cases>; children = <Cases params={params}></Cases>;
break; break;
...@@ -120,7 +120,7 @@ export default function ProjectInfo() { ...@@ -120,7 +120,7 @@ export default function ProjectInfo() {
fieldNames={{ fieldNames={{
label: "name", label: "name",
value: "id", value: "id",
children: "childInfo", // children: "childInfo",
}} }}
changeOnSelect changeOnSelect
/> />
......
No preview for this file type
<?xml version="1.0" encoding="UTF-8"?>
<svg width="1000px" height="1000px" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>编组 23</title>
<defs>
<linearGradient x1="89.4147753%" y1="100%" x2="64.5402719%" y2="5.55111512e-15%" id="linearGradient-1">
<stop stop-color="#FF8C34" offset="0%"></stop>
<stop stop-color="#FF552D" offset="50.7965867%"></stop>
<stop stop-color="#FFB901" offset="100%"></stop>
</linearGradient>
<rect id="path-2" x="0" y="0" width="1000" height="1000"></rect>
<path d="M346.945354,0 C386.719769,0 424.111509,15.4918955 452.243311,43.6191849 L452.243311,43.6191849 L668.850064,260.225938 L669.378577,260.759024 C685.499975,277.165176 693.679438,298.905285 693.755328,320.632146 L693.755328,320.632146 L693.755328,321.259403 L693.749893,321.968758 C693.503246,343.01181 685.65584,363.934192 670.054939,379.887631 L670.054939,379.887631 L669.208947,380.745878 C641.197349,408.940964 603.918354,424.546483 564.22449,424.720716 L564.22449,424.720716 L562.848135,424.720716 L562.536762,424.71846 L562.536762,424.71846 L562.22539,424.716203 L561.151236,424.702813 C525.720382,424.127444 491.914522,410.350076 465.167514,387.328975 L465.167514,387.328975 L522.762347,329.734142 L523.561943,330.330355 C550.060988,349.786544 587.60227,347.578297 611.507939,323.569875 L611.507939,323.569875 L611.65903,323.409559 C613.117482,321.77607 613.003516,319.25317 611.435737,317.685392 L611.435737,317.685392 L605.962112,312.212485 C604.081727,310.332275 601.913507,308.16421 599.487729,305.738569 L593.18685,299.437987 C590.932053,297.183279 588.527921,294.779225 585.989953,292.241326 L582.084563,288.336033 C579.416635,285.668167 576.622623,282.874207 573.718028,279.969657 L569.280136,275.531828 C568.52731,274.779011 567.768058,274.019768 567.00262,273.254339 L555.08747,261.339293 C553.445009,259.696842 551.782652,258.034494 550.102338,256.354188 L526.503749,232.755656 C524.701055,230.952963 522.889123,229.141032 521.06989,227.3218 L510.082391,216.334302 C507.321366,213.573277 504.552634,210.804545 501.782735,208.034647 L496.24332,202.495233 C494.397621,200.649535 492.553341,198.805257 490.712419,196.964336 L431.47928,137.731678 C428.464352,134.716815 425.551983,131.80452 422.757675,129.010295 L407.532556,113.785804 C404.707478,110.960885 402.11531,108.368895 399.786328,106.040113 L397.119817,103.373852 L397.119817,103.373852 L395.884942,102.139109 L395.396582,101.654979 C383.462415,89.9310903 367.835648,82.3510579 351.128572,81.3538863 L351.128572,81.3538863 L350.474754,81.3176927 C331.089139,80.3348518 312.694862,87.4364746 299.079774,101.051563 L299.079774,101.051563 L82.4685085,317.662828 L82.3102468,317.829667 C80.7826169,319.528117 80.9032045,322.108071 82.5452234,323.741355 L82.5452234,323.741355 L83.0084174,324.198689 C96.3385297,337.237535 114.117369,344.130503 132.892756,343.443545 L132.892756,343.443545 L133.621979,343.412939 C147.222113,342.762603 160.140238,337.694678 171.015544,329.621326 L171.015544,329.621326 L228.727706,387.333488 L227.916248,388.028387 C201.067045,410.866015 167.196496,424.381095 131.769108,424.711691 L131.769108,424.711691 L130.646618,424.718138 C93.6249819,424.795304 58.653995,411.454726 31.2725999,386.999552 L31.2725999,386.999552 L30.705499,386.489199 C12.0584465,369.581573 0.0893502856,346.158485 0,320.975107 L0,320.975107 L0,320.392976 L0.00529311546,319.668015 C0.261972172,297.20897 9.12417541,276.133428 25.0361305,260.225938 L25.0361305,260.225938 L241.642883,43.6191849 L242.489476,42.7791597 C270.518336,15.1836068 307.564215,0 346.945354,0 Z M346.940841,169.797131 L347.451262,169.800734 C356.468282,169.928032 365.450607,173.428804 372.328958,180.311584 L372.328958,180.311584 L458.7009,266.679014 L458.0109,266.633924 C457.091332,266.572696 456.172919,266.512046 455.24873,266.512046 L455.24873,266.512046 L454.601521,266.515806 C440.376087,266.681183 427.031996,272.296511 416.958974,282.373978 L416.958974,282.373978 L388.236016,311.092424 L314.892067,237.748474 L314.47565,237.325256 C300.872694,223.273967 301.0115,200.857321 314.892067,186.976754 L314.892067,186.976754 L321.557237,180.311584 C328.565368,173.29894 337.753105,169.797131 346.940841,169.797131 L346.940841,169.797131 Z" id="path-4"></path>
</defs>
<g id="第一版" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="编组-23">
<g id="编组-14">
<mask id="mask-3" fill="white">
<use xlink:href="#path-2"></use>
</mask>
<use id="矩形" fill="url(#linearGradient-1)" xlink:href="#path-2"></use>
</g>
<g id="Group-10" transform="translate(152.777778, 250.000000)">
<g id="Clip-6">
<mask id="mask-5" fill="white">
<use xlink:href="#path-4"></use>
</mask>
<use id="Clip-7" fill="#FFFFFF" xlink:href="#path-4"></use>
</g>
<path d="M426.525772,291.945289 L394.806421,323.669153 C368.416498,350.063588 325.469697,350.063588 299.079774,323.669153 L299.079774,323.669153 L267.35591,291.945289 C251.498491,276.08787 225.780951,276.08787 209.919019,291.945289 L209.919019,291.945289 L181.200574,320.663734 L239.792701,379.251348 C268.195261,407.653909 306.494043,424.648514 346.661057,424.720716 L346.661057,424.720716 L347.107809,424.720716 C386.823559,424.67559 424.156636,409.192719 452.243311,381.106044 L452.243311,381.106044 L512.685621,320.663734 L483.967176,291.945289 C476.033953,284.016579 465.641342,280.049968 455.244218,280.049968 L455.244218,280.049968 C444.851606,280.049968 434.458995,284.016579 426.525772,291.945289" id="Fill-7" fill="#FFFFFF"></path>
</g>
</g>
</g>
</svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" width="40" height="31" fill="none"><g opacity=".9"><path fill="url(#a)" d="M13 .4v29.3H7V6.3h-.2L0 10.5V5L7.2.4H13Z"/><path fill="url(#b)" d="M28.8 30.1c-2.2 0-4-.3-5.7-1-1.7-.8-3-1.8-4-3.1a7.7 7.7 0 0 1-1.4-4.6h6.2c0 .8.3 1.4.7 2 .4.5 1 .9 1.7 1.2.7.3 1.6.4 2.5.4 1 0 1.7-.2 2.5-.5.7-.3 1.3-.8 1.7-1.4.4-.6.6-1.2.6-2s-.2-1.5-.7-2.1c-.4-.6-1-1-1.8-1.4-.8-.4-1.8-.5-2.9-.5h-2.7v-4.6h2.7a6 6 0 0 0 2.5-.5 4 4 0 0 0 1.7-1.3c.4-.6.6-1.3.6-2a3.5 3.5 0 0 0-2-3.3 5.6 5.6 0 0 0-4.5 0 4 4 0 0 0-1.7 1.2c-.4.6-.6 1.2-.6 2h-6c0-1.7.6-3.2 1.5-4.5 1-1.3 2.2-2.3 3.8-3C25 .4 26.8 0 28.8 0s3.8.4 5.3 1.1c1.5.7 2.7 1.7 3.6 3a7.2 7.2 0 0 1 1.2 4.2c0 1.6-.5 3-1.5 4a7 7 0 0 1-4 2.2v.2c2.2.3 3.8 1 5 2.2a6.4 6.4 0 0 1 1.6 4.6c0 1.7-.5 3.1-1.4 4.4a9.7 9.7 0 0 1-4 3.1c-1.7.8-3.7 1.1-5.8 1.1Z"/></g><defs><linearGradient id="a" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient><linearGradient id="b" x1="20" x2="20" y1="0" y2="30.1" gradientUnits="userSpaceOnUse"><stop/><stop offset="1" stop-color="#3D3D3D"/></linearGradient></defs></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 283 64"><path fill="black" d="M141 16c-11 0-19 7-19 18s9 18 20 18c7 0 13-3 16-7l-7-5c-2 3-6 4-9 4-5 0-9-3-10-7h28v-3c0-11-8-18-19-18zm-9 15c1-4 4-7 9-7s8 3 9 7h-18zm117-15c-11 0-19 7-19 18s9 18 20 18c6 0 12-3 16-7l-8-5c-2 3-5 4-8 4-5 0-9-3-11-7h28l1-3c0-11-8-18-19-18zm-10 15c2-4 5-7 10-7s8 3 9 7h-19zm-39 3c0 6 4 10 10 10 4 0 7-2 9-5l8 5c-3 5-9 8-17 8-11 0-19-7-19-18s8-18 19-18c8 0 14 3 17 8l-8 5c-2-3-5-5-9-5-6 0-10 4-10 10zm83-29v46h-9V5h9zM37 0l37 64H0L37 0zm92 5-27 48L74 5h10l18 30 17-30h10zm59 12v10l-3-1c-6 0-10 4-10 10v15h-9V17h9v9c0-5 6-9 13-9z"/></svg>
\ No newline at end of file
@import "./reset.scss"; @import "./reset.scss";
@import "./mixins.scss";
body { body {
background-color: rgb(248, 248, 248) background-color: rgb(248, 248, 248)
...@@ -75,3 +76,19 @@ body { ...@@ -75,3 +76,19 @@ body {
.ant-tag-close-icon { .ant-tag-close-icon {
font-size: 10px !important; font-size: 10px !important;
} }
.ellipsis1{
@include ellipsis(1);
}
.ellipsis2{
@include ellipsis(2);
}
.ellipsis3{
@include ellipsis(3);
}
.ellipsis4{
@include ellipsis(4);
}
\ No newline at end of file
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
"paths": { "paths": {
"~/*": ["./*"] "~/*": ["./*"]
}, },
"typeRoots": ["./typings"] "typeRoots": ["./typings"],
"noEmitOnError": false
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"] "exclude": ["node_modules"]
......
...@@ -5,6 +5,9 @@ declare global { ...@@ -5,6 +5,9 @@ declare global {
messageApi: MessageInstance; //全局消息提示api messageApi: MessageInstance; //全局消息提示api
WxLogin: any; //微信登录对象 WxLogin: any; //微信登录对象
_AMapSecurityConfig: { securityJsCode: string }; //高德地图api密钥配置 _AMapSecurityConfig: { securityJsCode: string }; //高德地图api密钥配置
AMap:any AMap: any;
setUserInfo: Dispatch<SetStateAction<UserInfoResp | null | undefined>>; //设置userInfo
setNeedLogin: Dispatch<SetStateAction<Boolean>>; //需要登录操作
logout: () => void; //退出登录
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论