提交 ad36d9c6 作者: 18928357778

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

...@@ -83,7 +83,12 @@ export default function request(url: string, method: String = 'get', data?: any, ...@@ -83,7 +83,12 @@ export default function request(url: string, method: String = 'get', data?: any,
} }
if (data.code !== '200') { if (data.code !== '200') {
errMsg(data.message || '请求出错'); //未登录判断
if(data.code === '5008'){
errMsg('请先登录');
}else{
errMsg(data.message || '请求出错');
}
} }
return data; return data;
......
...@@ -4,7 +4,6 @@ import type { TabsProps } from "antd"; ...@@ -4,7 +4,6 @@ import type { TabsProps } from "antd";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import LoginModal from "~/components/loginModal"; import LoginModal from "~/components/loginModal";
import { useUser } from "~/lib/hooks";
import PublishModal from "./publishModal"; import PublishModal from "./publishModal";
import JoinModal from "./joinModal"; import JoinModal from "./joinModal";
import { UserContext } from "~/lib/userProvider"; import { UserContext } from "~/lib/userProvider";
...@@ -43,7 +42,8 @@ const items: TabsProps["items"] = [ ...@@ -43,7 +42,8 @@ const items: TabsProps["items"] = [
export default function NavHeader() { export default function NavHeader() {
const router = useRouter(); const router = useRouter();
const [currentPath, setCurrentPath] = useState(""); const [currentPath, setCurrentPath] = useState("");
const { userInfo, testLogin, logout } = useContext(UserContext); const { userInfo, testLogin, logout, setNeedLogin, needLogin } =
useContext(UserContext);
useEffect(() => { useEffect(() => {
const routerTo = items?.filter(item=>router.route.includes(item.key))[0] const routerTo = items?.filter(item=>router.route.includes(item.key))[0]
...@@ -97,6 +97,13 @@ export default function NavHeader() { ...@@ -97,6 +97,13 @@ export default function NavHeader() {
} }
} }
//从其它组件通知需要登录
useEffect(() => {
if (needLogin) {
setOpenLoginModal(true);
}
}, [needLogin]);
return ( return (
<div className={styles.navHeader}> <div className={styles.navHeader}>
<div className={styles.nav}> <div className={styles.nav}>
...@@ -134,7 +141,7 @@ export default function NavHeader() { ...@@ -134,7 +141,7 @@ export default function NavHeader() {
) : ( ) : (
<Button <Button
type="text" type="text"
onClick={() => testLogin()} onClick={() => setOpenLoginModal(true)}
style={{ fontWeight: "bold", fontSize: 16 }} style={{ fontWeight: "bold", fontSize: 16 }}
> >
登录 登录
...@@ -143,7 +150,10 @@ export default function NavHeader() { ...@@ -143,7 +150,10 @@ export default function NavHeader() {
</div> </div>
<LoginModal <LoginModal
open={openLoginModal} open={openLoginModal}
onCancel={() => setOpenLoginModal(false)} onCancel={() => {
setOpenLoginModal(false);
setNeedLogin(false);
}}
></LoginModal> ></LoginModal>
<PublishModal <PublishModal
open={openPublishModal} open={openPublishModal}
......
.identityBtn { .identityBtn {
box-sizing: border-box; box-sizing: border-box;
padding: 0 5px; padding: 0 5px;
position: absolute;
bottom: 0;
left: 50%;
transform:translate(-50%, 0);
min-width: 100%; min-width: 100%;
height: 24px;
background: #e26329;
border-radius: 6px; border-radius: 6px;
opacity: 0.95; text-align: center;
display: flex; font-size: 14px;
justify-content: center; font-family: PingFangSC-Regular, PingFang SC;
align-items: center; font-weight: 400;
font-size: 12px; color: #000000;
font-family: PingFangSC-Medium, PingFang SC; flex-wrap: nowrap;
font-weight: 500;
color: #fff;
white-space: nowrap;
} }
.modal { .modal {
:global .ant-modal-content { :global .ant-modal-content {
border-radius: 6px; border-radius: 6px;
.ant-modal-title{ .ant-modal-title {
text-align: center; text-align: center;
} }
} }
......
...@@ -6,6 +6,18 @@ import { useEffect, useState } from "react"; ...@@ -6,6 +6,18 @@ import { useEffect, useState } from "react";
import api, { ListTagResp } from "./api"; import api, { ListTagResp } from "./api";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
const imgs = [
require("./assets/生产制造商.png"),
require("./assets/品牌企业.png"),
require("./assets/商务公关机构.png"),
require("./assets/无人机自媒体.png"),
require("./assets/投资机构.png"),
require("./assets/飞手团队.png"),
require("./assets/二手服务商.png"),
require("./assets/飞手培训机构.png"),
require("./assets/推广合作商.png"),
];
type Props = { type Props = {
open?: boolean; open?: boolean;
onOk?: () => void; onOk?: () => void;
...@@ -16,10 +28,10 @@ export default function JoinModal(props: Props) { ...@@ -16,10 +28,10 @@ export default function JoinModal(props: Props) {
const [tagList, setTagList] = useState<ListTagResp[]>([]); const [tagList, setTagList] = useState<ListTagResp[]>([]);
useEffect(() => { useEffect(() => {
api.listTag().then(res => { api.listTag().then((res) => {
setTagList(res.result || []); setTagList(res.result || []);
}) });
}, []) }, []);
const onClickTag = (item: ListTagResp) => { const onClickTag = (item: ListTagResp) => {
router.replace("/JoinPolicy?tagId=" + item.id); router.replace("/JoinPolicy?tagId=" + item.id);
...@@ -35,15 +47,20 @@ export default function JoinModal(props: Props) { ...@@ -35,15 +47,20 @@ export default function JoinModal(props: Props) {
width={460} width={460}
footer={null} footer={null}
> >
<Row style={{ padding: "22px 16px 20px 16px", gap: "16px 40px" }}> <Row style={{rowGap: 29, paddingTop: 21, paddingBottom: 21}}>
{tagList.map((item) => { {tagList.map((item, i) => {
return ( return (
<Col <Col
key={item.id} key={item.id}
style={{ cursor: "pointer", height: 100, padding: 0 }} span={8}
style={{
cursor: "pointer",
padding: 0,
textAlign: "center",
}}
onClick={() => onClickTag(item)} onClick={() => onClickTag(item)}
> >
<Image src={img} width={100} height={100} alt=""></Image> <Image src={imgs[i]} width={64} height={64} alt=""></Image>
<div className={styles.identityBtn}> <div className={styles.identityBtn}>
{item.tagName} {item.tagName}
{">"} {">"}
......
...@@ -6,11 +6,11 @@ export interface TypeResp { ...@@ -6,11 +6,11 @@ export interface TypeResp {
} }
export interface PublishParams { export interface PublishParams {
userAccountId: number; //账号id
publishPhone: number; //手机号 publishPhone: number; //手机号
publishName: string; //发布名称 publishName: string; //发布名称
requirementTypeId: number; //需求类型 requirementTypeId: number; //需求类型
requireDescription: string; //需求描述 requireDescription: string; //需求描述
provinceCode?: string; //省编码
} }
export default { export default {
......
import { Button, Form, Input, Modal, Select } from "antd"; import { Button, Form, Input, Modal, Select } from "antd";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useGeolocation } from "~/lib/hooks";
import api, { PublishParams, TypeResp } from "./api"; import api, { PublishParams, TypeResp } from "./api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
...@@ -11,14 +12,14 @@ type Props = { ...@@ -11,14 +12,14 @@ type Props = {
export default function PublishModal(props: Props) { export default function PublishModal(props: Props) {
const [types, setTypes] = useState<Array<TypeResp>>([]); //需求类型 const [types, setTypes] = useState<Array<TypeResp>>([]); //需求类型
const [params, setParams] = useState<PublishParams>({ const [params, setParams] = useState<PublishParams>({
userAccountId: -1,
publishName: "", publishName: "",
publishPhone: -1, publishPhone: -1,
requireDescription: "", requireDescription: "",
requirementTypeId: -1, requirementTypeId: -1,
}); });
const [form] = Form.useForm(); const [form] = Form.useForm();
console.log("form", form); const position = useGeolocation();
console.log("position", position);
useEffect(() => { useEffect(() => {
api.listType().then((res) => { api.listType().then((res) => {
...@@ -33,10 +34,12 @@ export default function PublishModal(props: Props) { ...@@ -33,10 +34,12 @@ export default function PublishModal(props: Props) {
.publish({ .publish({
...params, ...params,
...values, ...values,
provinceCode: position?.address?.addressComponent?.adcode
}) })
.then((res) => { .then((res) => {
if (res.code !== "-1") { if (res.code === "200") {
props.onCancel && props.onCancel(); props.onCancel && props.onCancel();
window.messageApi.success("发布成功");
setTimeout(() => { setTimeout(() => {
form.resetFields(); form.resetFields();
}, 500); }, 500);
......
...@@ -33,20 +33,24 @@ export default function LoginModal(props: Props) { ...@@ -33,20 +33,24 @@ export default function LoginModal(props: Props) {
} }
setRandomLoginCode(String(Date.now())); setRandomLoginCode(String(Date.now()));
api
.getAppletQRCode({
randomLoginCode,
})
.then((res) => {
if (res.code == "200") {
setQrCode("data:image/png;base64," + res.result || "");
} else {
window.messageApi.error("获取登录二维码失败");
}
});
}, [props.open]); }, [props.open]);
useEffect(() => { useEffect(() => {
if (randomLoginCode) {
//获取登录码
api
.getAppletQRCode({
randomLoginCode,
})
.then((res) => {
if (res.code == "200") {
setQrCode("data:image/png;base64," + res.result || "");
} else {
window.messageApi.error("获取登录二维码失败");
}
});
}
if (randomLoginCode && !userInfo) { if (randomLoginCode && !userInfo) {
if (timeHandle) { if (timeHandle) {
clearTimeout(timeHandle); clearTimeout(timeHandle);
...@@ -58,14 +62,15 @@ export default function LoginModal(props: Props) { ...@@ -58,14 +62,15 @@ export default function LoginModal(props: Props) {
}) })
.then((res) => { .then((res) => {
if (res.code === "200") { if (res.code === "200") {
setUserInfo({
...res.result,
id: res.result?.userAccountId,
});
window.messageApi.success("登录成功");
clearInterval(handle); clearInterval(handle);
setTimeHandle(null); setTimeHandle(null);
props.onCancel();
window.localStorage.setItem("token", res.result.token);
api.userInfo().then((res) => {
setUserInfo(res.result || "");
window.messageApi.success("登录成功");
props.onCancel();
});
} }
}); });
}, 1000); }, 1000);
......
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import api, { UserInfoResp } from "~/api";
/*
const fetcher = (url) =>
fetch(url)
.then((r) => r.json())
.then((data) => {
return { user: data?.user || null };
}); */
export function useUser() {
const [user, setUser] = useState<UserInfoResp | null>(null);
const [userAccountId, setUserAccountId] = useState<number | "">('');
useEffect(() => {
setUserAccountId(Number(window.localStorage.getItem('userId')));
try {
let userInfo = JSON.parse(window.localStorage.getItem('userInfo') || '') || null;
setUser(userInfo);
} catch (e) { }
}, [])
useEffect(() => {
if (!user) {
api
.userInfo()
.then((res) => {
if(res.code == '200'){
setUser(res.result || null);
}else{
setUserAccountId('');
}
window.localStorage.setItem('userInfo', JSON.stringify(res.result || ''));
});
}
//退出登录
if(userAccountId === ''){
setUser(null);
window.localStorage.setItem('userInfo', '');
}
}, [userAccountId]);
return user;
}
export function useGeolocation() { export function useGeolocation() {
const [position, setPosition] = useState<{ const [position, setPosition] = useState<{
......
import React, { createContext, Dispatch, SetStateAction, useEffect, useState } from "react"; import React, {
createContext,
Dispatch,
SetStateAction,
useEffect,
useState,
} from "react";
import api, { UserInfoResp } from "~/api"; import api, { UserInfoResp } from "~/api";
export const UserContext = createContext<{ export const UserContext = createContext<{
testLogin: () => void; testLogin: () => void;
logout: () => void; logout: () => void;
userInfo: UserInfoResp | null; userInfo: UserInfoResp | null | "";
setUserInfo: Dispatch<SetStateAction<UserInfoResp | null>>; setUserInfo: Dispatch<SetStateAction<UserInfoResp | null | "">>;
needLogin: Boolean;
setNeedLogin: Dispatch<SetStateAction<Boolean>>;
}>({ }>({
testLogin() {}, testLogin() {},
logout() {}, logout() {},
userInfo: null, userInfo: null,
setUserInfo() {}, setUserInfo() {},
needLogin: false,
setNeedLogin() {},
}); });
type Props = { type Props = {
children: React.ReactNode; children: React.ReactNode;
}; };
const UserProvider = ({ children }: Props) => { const UserProvider = ({ children }: Props) => {
const [userInfo, setUserInfo] = useState<UserInfoResp | null>(null); const [userInfo, setUserInfo] = useState<UserInfoResp | null | ''>(null);
const [needLogin, setNeedLogin] = useState<Boolean>(false); //用于通知登录modal需要打开
useEffect(() => { useEffect(() => {
try { try {
...@@ -26,7 +37,9 @@ const UserProvider = ({ children }: Props) => { ...@@ -26,7 +37,9 @@ const UserProvider = ({ children }: Props) => {
}, []); }, []);
useEffect(() => { useEffect(() => {
localStorage.setItem("userInfo", JSON.stringify(userInfo || "")); if (userInfo !== null) {
localStorage.setItem("userInfo", JSON.stringify(userInfo || ""));
}
}, [userInfo]); }, [userInfo]);
//测试登录 //测试登录
...@@ -35,7 +48,7 @@ const UserProvider = ({ children }: Props) => { ...@@ -35,7 +48,7 @@ const UserProvider = ({ children }: Props) => {
if (res.code == "200") { if (res.code == "200") {
window.localStorage.setItem("token", res.result?.token || ""); window.localStorage.setItem("token", res.result?.token || "");
api.userInfo().then((res) => { api.userInfo().then((res) => {
setUserInfo(res.result || null); setUserInfo(res.result || '');
}); });
} }
}); });
...@@ -44,11 +57,20 @@ const UserProvider = ({ children }: Props) => { ...@@ -44,11 +57,20 @@ const UserProvider = ({ children }: Props) => {
//登出 //登出
function logout() { function logout() {
localStorage.setItem("token", ""); localStorage.setItem("token", "");
setUserInfo(null); setUserInfo('');
} }
return ( return (
<UserContext.Provider value={{ userInfo, setUserInfo, testLogin, logout }}> <UserContext.Provider
value={{
userInfo,
setUserInfo,
testLogin,
logout,
needLogin,
setNeedLogin,
}}
>
{children} {children}
</UserContext.Provider> </UserContext.Provider>
); );
......
...@@ -6,11 +6,23 @@ export interface CooperationApplyParams { ...@@ -6,11 +6,23 @@ export interface CooperationApplyParams {
remark?: string, remark?: string,
userAccountId: number, userAccountId: number,
cooperationTagId: number cooperationTagId: number
} }
export interface GetTagIdResp {
id: number,
tagName: string,
tagImg: string,
tagDescription: string,
createTime: string
}
export default { export default {
//请加盟 //请加盟
cooperationApply(params: CooperationApplyParams):Promise<Response<string>>{ cooperationApply(params: CooperationApplyParams): Promise<Response<string>> {
return request('/userapp/cooperation/apply', 'post', params) return request('/userapp/cooperation/apply', 'post', params)
},
//加盟标签相关内容
getTagById(params: { id: number }): Promise<Response<GetTagIdResp>> {
return request('/userapp/cooperation/getTagById', 'get', params)
} }
} }
\ No newline at end of file
import { Button, Col, Divider, Form, Input, Row } from "antd"; import { Button, Col, Divider, Form, Input, Row } from "antd";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { useEffect, useState } from "react";
import LayoutView from "~/components/layout"; import LayoutView from "~/components/layout";
import api from "./api"; import api from "./api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
export default function JoinPolicy() { export default function JoinPolicy() {
const router = useRouter(); const router = useRouter();
const [content, setContent] = useState(""); //福利内容
const tagId = Number(router.query.tagId);
useEffect(() => {
if (tagId) {
api
.getTagById({
id: tagId,
})
.then((res) => {
setContent(res.result?.tagDescription.replace("\n", "<br/>") || "");
});
}
}, []);
//提交 //提交
const onFinish = (values: any) => { const onFinish = (values: any) => {
console.log(values); console.log(values);
api api
.cooperationApply({ .cooperationApply({
...values, ...values,
userAccountId: 1, cooperationTagId: tagId,
cooperationTagId: router.query.tagId,
}) })
.then((res) => { .then((res) => {
console.log("提交结果", res); console.log("提交结果", res);
if (res.result === "已通过") { if (res.code === "200") {
window.messageApi.success(res.result); window.messageApi.success('提交成功');
setTimeout(() => { setTimeout(() => {
router.push("/"); router.push("/");
}, 1500); }, 1500);
} else {
window.messageApi.error(res.message);
} }
}); });
}; };
...@@ -50,24 +62,8 @@ export default function JoinPolicy() { ...@@ -50,24 +62,8 @@ export default function JoinPolicy() {
<div <div
className={styles.font2} className={styles.font2}
style={{ paddingLeft: 50, paddingRight: 50 }} style={{ paddingLeft: 50, paddingRight: 50 }}
> dangerouslySetInnerHTML={{ __html: content }}
1.每月自动获取一张高额度优惠券 ></div>
<br /> 2.流量扶持和店铺曝光度
<br />
3成为科比特指定官方生态合作伙伴
<br /> 4.享受不低于1亿制造采购补贴
<br /> 5.无人机产业链资源共享
<br /> 6.享受价值5亿产业链订单
<br /> 7.享受一对一代运营服务
<br /> 8.享受无人机生态圈资源
<br /> 9.成为科比特指定官方生态
<br />
10.享受无人机生态圈资源合作伙伴
<br />
11.受价值5亿产业链订单
<br />
12.成为科比特指定官方生态合作伙伴
</div>
<Divider /> <Divider />
<div <div
className={styles.font1} className={styles.font1}
......
...@@ -2,13 +2,14 @@ import { LoadingOutlined, PlusOutlined } from "@ant-design/icons"; ...@@ -2,13 +2,14 @@ import { LoadingOutlined, PlusOutlined } from "@ant-design/icons";
import { Col, Form, Input, Row, Upload, message, Button, Image } from "antd"; import { Col, Form, Input, Row, Upload, message, Button, Image } 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 { useState } from "react"; import { useContext, useState } from "react";
import config from "~/api/config"; import config from "~/api/config";
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";
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";
...@@ -34,6 +35,7 @@ const normFile = (e: any) => { ...@@ -34,6 +35,7 @@ const normFile = (e: any) => {
export default function Certification() { export default function Certification() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [imageUrl, setImageUrl] = useState<string>(); const [imageUrl, setImageUrl] = useState<string>();
const { userInfo, setUserInfo } = useContext(UserContext);
//上传change事件 //上传change事件
const handleChange: UploadProps["onChange"] = ( const handleChange: UploadProps["onChange"] = (
...@@ -60,12 +62,18 @@ export default function Certification() { ...@@ -60,12 +62,18 @@ export default function Certification() {
licenseImg: imageUrl, licenseImg: imageUrl,
}) })
.then((res) => { .then((res) => {
console.log('提交结果', res); console.log("提交结果", res);
if(res.code === '200'){ if (res.code === "200") {
window.messageApi.success(res.result); window.messageApi.success("提交成功,请等待审核");
if (userInfo) {
setUserInfo({
...userInfo,
companyAuthStatus: 1,
});
}
setTimeout(() => { setTimeout(() => {
Router.push('/'); Router.push("/");
}, 1000) }, 1000);
} }
}); });
}; };
......
...@@ -21,6 +21,11 @@ export interface Dynamic { ...@@ -21,6 +21,11 @@ export interface Dynamic {
likesCount: number; likesCount: number;
commentCount: number; commentCount: number;
likes: boolean; likes: boolean;
userBaseInfo: {
id: number,
nickName: string,
userImg: string
}
} }
export interface DynamicListResp { export interface DynamicListResp {
......
...@@ -2,11 +2,12 @@ import { PlusOutlined } from "@ant-design/icons"; ...@@ -2,11 +2,12 @@ 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 { useState } from "react"; import { useContext, 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, useUser } from "~/lib/hooks"; import { useGeolocation } from "~/lib/hooks";
import { UserContext } from "~/lib/userProvider";
type Props = { type Props = {
open: boolean; open: boolean;
...@@ -30,7 +31,7 @@ export default function PublishMessage(props: Props) { ...@@ -30,7 +31,7 @@ export default function PublishMessage(props: Props) {
const [fileList, setFileList] = useState<UploadFile[]>([]); const [fileList, setFileList] = useState<UploadFile[]>([]);
const [showLoading, setShowLoad] = useState(false); const [showLoading, setShowLoad] = useState(false);
const [form] = Form.useForm(); const [form] = Form.useForm();
const user = useUser(); const { userInfo, setNeedLogin } = useContext(UserContext);
const position = useGeolocation(); const position = useGeolocation();
//预览关闭 //预览关闭
...@@ -84,33 +85,38 @@ export default function PublishMessage(props: Props) { ...@@ -84,33 +85,38 @@ export default function PublishMessage(props: Props) {
const onFinish = (values: any) => { const onFinish = (values: any) => {
console.log(values); console.log(values);
setShowLoad(true); setShowLoad(true);
api
.publish({
lat: position?.position?.lat, //纬度
lon: position?.position?.lng, //经度
title: '', //标题
description: values.description, //描述
userId: user!.id, //用户id
mediaVO: {
//发布图片
//@ts-ignore
picture: fileList.filter((item) => item.url).map((item) => item.url),
},
})
.then((res) => {
console.log("提交结果", res);
setShowLoad(false);
if (res.code === "200") {
window.messageApi.success("发布成功");
props.onCancel();
props.onOk && props.onOk();
setTimeout(() => { if (userInfo) {
form.resetFields(["title", "description"]); api
setFileList([]); .publish({
}, 500); lat: position?.position?.lat, //纬度
} lon: position?.position?.lng, //经度
}); title: "", //标题
description: values.description, //描述
userId: userInfo.id, //用户id
mediaVO: {
//发布图片
//@ts-ignore
picture: fileList
.filter((item) => item.url)
.map((item) => item.url),
},
})
.then((res) => {
console.log("提交结果", res);
setShowLoad(false);
if (res.code === "200") {
window.messageApi.success("发布成功");
props.onCancel();
props.onOk && props.onOk();
setTimeout(() => {
form.resetFields(["title", "description"]);
setFileList([]);
}, 500);
}
});
}
}; };
return ( return (
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
font-family: MicrosoftYaHei; font-family: MicrosoftYaHei;
color: #000000; color: #000000;
margin-bottom: 16px; margin-bottom: 16px;
padding-right: 10px;
} }
} }
......
...@@ -13,11 +13,11 @@ import Layout from "~/components/layout"; ...@@ -13,11 +13,11 @@ import Layout from "~/components/layout";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import errImg from "~/assets/errImg"; import errImg from "~/assets/errImg";
import { RightOutlined } from "@ant-design/icons"; import { RightOutlined } from "@ant-design/icons";
import { useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import PublishMessage from "./components/publishMessage"; import PublishMessage from "./components/publishMessage";
import api, { ByDynamicParams, Dynamic } from "./api"; import api, { ByDynamicParams, Dynamic } from "./api";
import InfiniteScroll from "react-infinite-scroll-component"; import InfiniteScroll from "react-infinite-scroll-component";
import { useUser } from "~/lib/hooks"; import { UserContext } from "~/lib/userProvider";
interface Item extends Dynamic { interface Item extends Dynamic {
openComment?: boolean; //是否开启评论 openComment?: boolean; //是否开启评论
...@@ -32,8 +32,8 @@ export default function Forum() { ...@@ -32,8 +32,8 @@ export default function Forum() {
pageNo: 1, pageNo: 1,
pageSize: 16, pageSize: 16,
}); });
const [count, setCount] = useState(0); //动态总数 const [count, setCount] = useState(0); //动态总数
const userInfo = useUser(); //获取信息 const { userInfo, setNeedLogin } = useContext(UserContext);
useEffect(() => { useEffect(() => {
api api
...@@ -56,7 +56,11 @@ export default function Forum() { ...@@ -56,7 +56,11 @@ export default function Forum() {
* 展示发布模态框 * 展示发布模态框
*/ */
const showModal = () => { const showModal = () => {
setIsModalOpen(true); if (userInfo) {
setIsModalOpen(true);
} else {
setNeedLogin(true);
}
}; };
/** /**
...@@ -78,15 +82,22 @@ export default function Forum() { ...@@ -78,15 +82,22 @@ export default function Forum() {
//评论内容 //评论内容
const onComment = (values: any, id: number, i: number) => { const onComment = (values: any, id: number, i: number) => {
api.comment({
content: values.content,
dynamicId: id,
userId: userInfo!.id,
}).then(res => {
if(res.code === '200'){
} if (userInfo) {
}); api
.comment({
content: values.content,
dynamicId: id,
userId: userInfo.id,
})
.then((res) => {
if (res.code === "200") {
window.messageApi.success("评论成功");
}
});
} else {
setNeedLogin(true);
}
}; };
return ( return (
<Layout> <Layout>
...@@ -112,9 +123,15 @@ export default function Forum() { ...@@ -112,9 +123,15 @@ export default function Forum() {
return ( return (
<div key={item.id} className={styles.item}> <div key={item.id} className={styles.item}>
<Space size={10} align="start"> <Space size={10} align="start">
<Image alt="" className={styles.headImg}></Image> <Image
alt=""
className={styles.headImg}
src={item.userBaseInfo.userImg}
></Image>
<div className={styles.info}> <div className={styles.info}>
<div className={styles.name}>给**的</div> <div className={styles.name}>
{item.userBaseInfo.nickName}
</div>
<div className={styles.desc}>{item.description}</div> <div className={styles.desc}>{item.description}</div>
<div className={styles.imgs}> <div className={styles.imgs}>
<Image.PreviewGroup <Image.PreviewGroup
...@@ -165,8 +182,17 @@ export default function Forum() { ...@@ -165,8 +182,17 @@ export default function Forum() {
</Space> </Space>
{item.openComment && ( {item.openComment && (
<div className={styles.commentWrap}> <div className={styles.commentWrap}>
<Form onFinish={(values) => {onComment(values, item.id, i)}}> <Form
<Form.Item name="content" rules={[{ required: true }]} help="" style={{marginBottom: 0}}> onFinish={(values) => {
onComment(values, item.id, i);
}}
>
<Form.Item
name="content"
rules={[{ required: true }]}
help=""
style={{ marginBottom: 0 }}
>
<div className={styles.draftWrap}> <div className={styles.draftWrap}>
<div className={styles.commentHeadImg}>自已</div> <div className={styles.commentHeadImg}>自已</div>
<Input <Input
...@@ -176,7 +202,11 @@ export default function Forum() { ...@@ -176,7 +202,11 @@ export default function Forum() {
</div> </div>
</Form.Item> </Form.Item>
<div className={styles.btnCommentWrap}> <div className={styles.btnCommentWrap}>
<Button type="primary" htmlType="submit" className="btnComment"> <Button
type="primary"
htmlType="submit"
className="btnComment"
>
评论 评论
</Button> </Button>
</div> </div>
......
import styles from "./index.module.scss"; import styles from "./index.module.scss";
import Layout from "~/components/layout"; import Layout from "~/components/layout";
import { Space, Image as AImage, Row, Col, Button, Divider, Badge } from "antd"; import { Space, Image as AImage, Row, Col, Button, Divider, Badge } from "antd";
import { useEffect, useState } from "react"; import { useContext, useEffect, useState } from "react";
import { DownOutlined, RightOutlined } from "@ant-design/icons"; import { DownOutlined, RightOutlined } from "@ant-design/icons";
import Image from "next/image"; import Image from "next/image";
import errImg from "~/assets/errImg"; import errImg from "~/assets/errImg";
...@@ -15,16 +15,28 @@ import "swiper/css"; ...@@ -15,16 +15,28 @@ import "swiper/css";
import "swiper/css/navigation"; import "swiper/css/navigation";
import api, { GetAppGoodsInfoDetailResult } from "./api"; import api, { GetAppGoodsInfoDetailResult } from "./api";
import IntentionModal from "./components/intentionModal"; import IntentionModal from "./components/intentionModal";
import { UserContext } from "~/lib/userProvider";
export default function MallDetail() { export default function MallDetail() {
const [visible, setVisible] = useState(false); const { userInfo, setNeedLogin } = useContext(UserContext);
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<GetAppGoodsInfoDetailResult | null>(
null null
); //详情数据 ); //详情数据
const [intentionModalOpen, setIntentionModalOpen] = useState(false); //意向弹窗 const [intentionModalOpen, setIntentionModalOpen] = useState(false); //意向弹窗
//打开意向modal
const openIntentionModal = () => {
if (userInfo) {
setIntentionModalOpen(true);
} else {
setNeedLogin(true);
}
};
//提交意向
const handleIntentionOk = () => { const handleIntentionOk = () => {
setIntentionModalOpen(false); setIntentionModalOpen(false);
}; };
...@@ -52,7 +64,12 @@ export default function MallDetail() { ...@@ -52,7 +64,12 @@ export default function MallDetail() {
return ( return (
<Layout> <Layout>
{/* 意向弹窗 */} {/* 意向弹窗 */}
<IntentionModal open={intentionModalOpen} onOk={handleIntentionOk} onCancel={handleIntentionCancel}></IntentionModal> <IntentionModal
open={intentionModalOpen}
detail={detail}
onOk={handleIntentionOk}
onCancel={handleIntentionCancel}
></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
...@@ -134,7 +151,9 @@ export default function MallDetail() { ...@@ -134,7 +151,9 @@ export default function MallDetail() {
</Col> </Col>
<Col> <Col>
<Row align="middle" style={{ cursor: "pointer" }}> <Row align="middle" style={{ cursor: "pointer" }}>
<Col className={styles.font4} onClick={() => setIntentionModalOpen(true)}>共3种可选</Col> <Col className={styles.font4} onClick={openIntentionModal}>
共3种可选
</Col>
<Col style={{ marginLeft: 9 }}> <Col style={{ marginLeft: 9 }}>
<DownOutlined <DownOutlined
style={{ style={{
...@@ -169,8 +188,14 @@ export default function MallDetail() { ...@@ -169,8 +188,14 @@ export default function MallDetail() {
</Row> </Row>
</Space> </Space>
<Space size={12} style={{ marginTop: 123 }}> <Space size={12} style={{ marginTop: 123 }}>
<Button className={styles.btn1}>加入购物车</Button> <Button className={styles.btn1} onClick={openIntentionModal}>
<Button className={styles.btn2} type="primary" onClick={() => setIntentionModalOpen(true)}> 加入购物车
</Button>
<Button
className={styles.btn2}
type="primary"
onClick={openIntentionModal}
>
提交意向 提交意向
</Button> </Button>
<Space size={20} style={{ marginLeft: 19 }}> <Space size={20} style={{ marginLeft: 19 }}>
......
...@@ -46,7 +46,7 @@ export interface GoodsSpec { ...@@ -46,7 +46,7 @@ export interface GoodsSpec {
skuId: number; skuId: number;
brandInfoId: number; brandInfoId: number;
skuName: string; skuName: string;
productSpecList: ProductSpecList[]; productSpecList: ProductSpec[];
industrySpecList?: any; industrySpecList?: any;
chooseType: number; chooseType: number;
skuUnitId: number; skuUnitId: number;
...@@ -55,7 +55,7 @@ export interface GoodsSpec { ...@@ -55,7 +55,7 @@ export interface GoodsSpec {
flag?: any; flag?: any;
} }
export interface ProductSpecList { export interface ProductSpec {
id: number; id: number;
productSpec: number; productSpec: number;
productSkuId: number; productSkuId: number;
......
import { Button, Col, Image, Modal, Row, Space } from "antd"; import { Button, Col, Image, Modal, Row, Space } from "antd";
import { useState } from "react"; import { useState } from "react";
import errImg from "~/assets/errImg"; import errImg from "~/assets/errImg";
import { GetAppGoodsInfoDetailResult } from "../../api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
type Props = { type Props = {
open?: boolean; open?: boolean;
onOk?: (e: React.MouseEvent<HTMLButtonElement>) => void; onOk?: (e: React.MouseEvent<HTMLButtonElement>) => void;
onCancel?: (e: React.MouseEvent<HTMLButtonElement>) => void; onCancel: (e: React.MouseEvent<HTMLButtonElement>) => void;
detail: GetAppGoodsInfoDetailResult | null;
}; };
export default function IntentionModal(props: Props) { export default function IntentionModal(props: Props) {
const list = [1, 1, 1, 1, 1, 1, 1, 1, 1]; const [checkedMap, setCheckedMap] = useState<{ string?: boolean }>({}); //通过索引记录选中的产品规格 例: {'1,1': true|false}
//添加规格到购物车
function addProductSpec(goodsSpecIndex: number, productSpecIndex: number) {
let temp = {};
//@ts-ignore
temp[`${goodsSpecIndex},${productSpecIndex}`] =
//@ts-ignore
!checkedMap[`${goodsSpecIndex},${productSpecIndex}`];
setCheckedMap({
...checkedMap,
...temp,
});
}
return ( return (
<Modal <Modal
...@@ -21,7 +37,13 @@ export default function IntentionModal(props: Props) { ...@@ -21,7 +37,13 @@ export default function IntentionModal(props: Props) {
className={styles.model} className={styles.model}
footer={ footer={
<div style={{ padding: "13px 36px" }}> <div style={{ padding: "13px 36px" }}>
<Button type="primary" className={styles.font5} style={{width: '100%', height: 44}}>提交意向</Button> <Button
type="primary"
className={styles.font5}
style={{ width: "100%", height: 44 }}
>
提交意向
</Button>
</div> </div>
} }
> >
...@@ -32,6 +54,7 @@ export default function IntentionModal(props: Props) { ...@@ -32,6 +54,7 @@ export default function IntentionModal(props: Props) {
height={100} height={100}
fallback={errImg} fallback={errImg}
style={{ borderRadius: 8 }} style={{ borderRadius: 8 }}
src={props.detail?.images?.[0]?.imgUrl}
></Image> ></Image>
</Col> </Col>
<Col flex="auto" style={{ marginLeft: 13, width: 230 }}> <Col flex="auto" style={{ marginLeft: 13, width: 230 }}>
...@@ -39,13 +62,13 @@ export default function IntentionModal(props: Props) { ...@@ -39,13 +62,13 @@ export default function IntentionModal(props: Props) {
className={`${styles.font1} ${styles.ellipsis1}`} className={`${styles.font1} ${styles.ellipsis1}`}
style={{ marginTop: 28 }} style={{ marginTop: 28 }}
> >
垂直起降固定翼 插翅虎M9 {props.detail?.goodsName}
</div> </div>
<div <div
className={`${styles.font2} ${styles.ellipsis2}`} className={`${styles.font2} ${styles.ellipsis2}`}
style={{ marginTop: 7 }} style={{ marginTop: 7 }}
> >
已选:入云龙【机壳喷绘】+金眼彪Z40【222222222222222222222222233333555555555555555 已选:
</div> </div>
</Col> </Col>
</Row> </Row>
...@@ -54,40 +77,59 @@ export default function IntentionModal(props: Props) { ...@@ -54,40 +77,59 @@ export default function IntentionModal(props: Props) {
<div className={styles.font3} style={{}}> <div className={styles.font3} style={{}}>
无人机 无人机
</div> </div>
<div> {props.detail?.goodsSpec?.map((item, goodsSpecIndex) => {
<div return (
className={styles.font2} <div key={item.id}>
style={{ marginBottom: 5, marginTop: 11 }} <div
> className={styles.font2}
入云龙 style={{ marginBottom: 5, marginTop: 11 }}
</div> >
<Space size={10} direction="vertical" style={{ width: "100%" }}> {item.goodsSpecName}
{list.map((item, i) => { </div>
return ( <Space size={10} direction="vertical" style={{ width: "100%" }}>
<Row {item.productSpecList?.map((product, productSpecIndex) => {
key={i} return (
align="middle" <Row
wrap={false} key={product.id}
style={{ align="middle"
borderRadius: 5, wrap={false}
border: "1px solid #d6d6d6", style={{
height: 50, borderRadius: 5,
}} //@ts-ignore
> border: checkedMap[
<Col style={{ marginLeft: 7 }}> `${goodsSpecIndex},${productSpecIndex}`
<Image width={52} height={36} src="" fallback={errImg} preview={false}></Image> ]
</Col> ? "1px solid #FF552D"
<Col : "1px solid #d6d6d6",
className={`${styles.ellipsis1} ${styles.font4}`} height: 50,
style={{ width: 238, marginLeft: 18 }} cursor: "pointer",
> }}
入云龙1-机壳喷绘 onClick={() =>
</Col> addProductSpec(goodsSpecIndex, productSpecIndex)
</Row> }
); >
})} <Col style={{ marginLeft: 7 }}>
</Space> <Image
</div> width={52}
height={36}
src={product.specImage}
fallback={errImg}
preview={false}
></Image>
</Col>
<Col
className={`${styles.ellipsis1} ${styles.font4}`}
style={{ width: 238, marginLeft: 18 }}
>
{product.specName}
</Col>
</Row>
);
})}
</Space>
</div>
);
})}
</div> </div>
</div> </div>
</Modal> </Modal>
......
...@@ -27,6 +27,11 @@ export interface Item { ...@@ -27,6 +27,11 @@ export interface Item {
apply: 0 | 1; apply: 0 | 1;
} }
export interface ApplyParams {
tenderInfoId?: number; //招标详情id
tenderNewsId?: number; //招标id
}
export default { export default {
/** /**
...@@ -36,5 +41,9 @@ export default { ...@@ -36,5 +41,9 @@ export default {
*/ */
listNewTenderInfo(params: ListNewTenderInfoParams, options = {}): Promise<Response<ListNewTenderInfoResp>> { listNewTenderInfo(params: ListNewTenderInfoParams, options = {}): Promise<Response<ListNewTenderInfoResp>> {
return request('/release/tender/listNewTenderInfo', 'post', params, options); return request('/release/tender/listNewTenderInfo', 'post', params, options);
},
//合作申请提交
apply(params: ApplyParams){
return request('/release/tender/apply', 'post', params);
} }
} }
\ No newline at end of file
import { Button, Empty, Pagination, Spin } from "antd"; import { Button, Empty, Pagination, Spin } from "antd";
import { useState, useEffect } from "react"; import { useState, useEffect, useContext } from "react";
import { UserContext } from "~/lib/userProvider";
import api, { Item } from "./api"; import api, { Item } from "./api";
import styles from "./index.module.scss"; import styles from "./index.module.scss";
...@@ -21,6 +22,7 @@ export default function Bids(props: Props) { ...@@ -21,6 +22,7 @@ export default function Bids(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 [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const {userInfo, setNeedLogin} = useContext(UserContext);
useEffect(() => { useEffect(() => {
//中断前一次请求 //中断前一次请求
...@@ -57,6 +59,24 @@ export default function Bids(props: Props) { ...@@ -57,6 +59,24 @@ export default function Bids(props: Props) {
}); });
}; };
//申请合作
const onApply = (item: Item) => {
if (userInfo) {
api
.apply({
tenderNewsId: item.tenderNewsId,
tenderInfoId: item.id,
})
.then((res) => {
if (res.code === "200") {
window.messageApi.success("申请成功");
}
});
} else {
setNeedLogin(true);
}
};
return ( return (
<Spin spinning={loading} delay={500}> <Spin spinning={loading} delay={500}>
<div className={styles.bids} style={{ height: 610 }}> <div className={styles.bids} style={{ height: 610 }}>
...@@ -64,9 +84,7 @@ export default function Bids(props: Props) { ...@@ -64,9 +84,7 @@ export default function Bids(props: Props) {
return ( return (
<div className={styles.item} key={item.id}> <div className={styles.item} key={item.id}>
<div className={styles.info}> <div className={styles.info}>
<div className={styles.title}> <div className={styles.title}>{item.tenderContent}</div>
{item.tenderContent}
</div>
</div> </div>
{item.apply ? ( {item.apply ? (
<Button <Button
...@@ -80,7 +98,9 @@ export default function Bids(props: Props) { ...@@ -80,7 +98,9 @@ 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}>申请合作</div> <div className={styles.text2} onClick={() => onApply(item)}>
申请合作
</div>
</Button> </Button>
)} )}
</div> </div>
......
...@@ -67,15 +67,19 @@ export default function Cases(props: Props) { ...@@ -67,15 +67,19 @@ export default function Cases(props: Props) {
return ( return (
<div className={styles.item} key={item.id}> <div className={styles.item} key={item.id}>
<div className={styles.info}> <div className={styles.info}>
<div className={styles.title}>{item.caseTitle}</div> <div className={styles.title}>
<Button
type="link"
style={{ padding: "0 0" }}
onClick={() =>
Router.push("/projectInfo/caseArticle/" + item.id)
}
>
{item.caseTitle}
</Button>
</div>
</div> </div>
<Button <Button type="primary" className={styles.btn}>
type="primary"
className={styles.btn}
onClick={() =>
Router.push("/projectInfo/caseArticle/" + item.id)
}
>
申请合作 申请合作
</Button> </Button>
</div> </div>
......
...@@ -23,9 +23,6 @@ ...@@ -23,9 +23,6 @@
flex: auto; flex: auto;
.title { .title {
white-space: nowrap; /* 防止换行 */
overflow: hidden; /* 隐藏溢出部分 */
text-overflow: ellipsis; /* 使用省略号代替溢出部分 */
font-size: 16px; font-size: 16px;
font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI; font-family: MicrosoftYaHeiUI-Bold, MicrosoftYaHeiUI;
font-weight: bold; font-weight: bold;
...@@ -35,9 +32,6 @@ ...@@ -35,9 +32,6 @@
} }
.desc { .desc {
white-space: nowrap; /* 防止换行 */
overflow: hidden; /* 隐藏溢出部分 */
text-overflow: ellipsis; /* 使用省略号代替溢出部分 */
font-size: 14px; font-size: 14px;
font-family: MicrosoftYaHei; font-family: MicrosoftYaHei;
color: RGBA(135, 135, 135, 0.4); color: RGBA(135, 135, 135, 0.4);
......
...@@ -66,20 +66,20 @@ export default function Requirements(props: Props) { ...@@ -66,20 +66,20 @@ export default function Requirements(props: Props) {
/** /**
* 确认解决 * 确认解决
* @param e * @param e
*/ */
const confirmSolved = ( const confirmSolved = (item: Item) => {
item: Item api
) => { .solveRequire({
api.solveRequire({ requirementsInfoId: item.id,
requirementsInfoId: item.id, userAccountId: userId,
userAccountId: userId })
}).then(res => { .then((res) => {
if(res.code === '200'){ if (res.code === "200") {
window.messageApi.success('提交完成'); window.messageApi.success("提交完成");
setReload(!reload); setReload(!reload);
} }
}) });
}; };
return ( return (
...@@ -94,13 +94,14 @@ export default function Requirements(props: Props) { ...@@ -94,13 +94,14 @@ export default function Requirements(props: Props) {
<div className={styles.logo}></div> <div className={styles.logo}></div>
<div className={styles.info}> <div className={styles.info}>
<div className={styles.title}> <div className={styles.title}>
项目需求:电力巡检需要5名飞手 项目需求:{item.requireDescription}
</div> </div>
{/*
<div className={styles.desc}> <div className={styles.desc}>
具体需求:{item.requireDescription} 具体需求:{item.requireDescription}
</div> </div> */}
</div> </div>
{item.userAccountId === userId && ( {item.userAccountId === userId ? (
<Popconfirm <Popconfirm
title="提示" title="提示"
description="确认该需求已经解决了吗?" description="确认该需求已经解决了吗?"
...@@ -117,6 +118,8 @@ export default function Requirements(props: Props) { ...@@ -117,6 +118,8 @@ export default function Requirements(props: Props) {
已解决 已解决
</Button> </Button>
</Popconfirm> </Popconfirm>
) : (
<div style={{ width: 120, flexShrink: 0 }}></div>
)} )}
</div> </div>
); );
......
...@@ -20,6 +20,8 @@ const withTheme = (node: JSX.Element) => ( ...@@ -20,6 +20,8 @@ const withTheme = (node: JSX.Element) => (
theme={{ theme={{
token: { token: {
borderRadius: 6, borderRadius: 6,
colorLink: "#333",
colorLinkHover: "#ff552d",
}, },
}} }}
> >
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论