提交 8f686d00 作者: ZhangLingKun

Merge branch 'review' into develop

流水线 #7899 已失败 于阶段
in 40 秒
......@@ -4,7 +4,8 @@ ENV PROFILES_ACTIVE=$PROFILES_ACTIVE
# Install dependencies only when needed
FROM base AS deps
# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
RUN sed -i 's/https/http/' /etc/apk/repositories
# RUN sed -i 's/https/http/' /etc/apk/repositories
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add --no-cache libc6-compat
WORKDIR /app
......
module.exports = {
presets: ['next/babel'],
plugins: [['styled-components', { ssr: true }]],
};
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",{ "ssr":true }
]
]
}
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
- ../../base
namespace: prod
#namePrefix: prod-
commonLabels:
......@@ -9,9 +9,9 @@ commonLabels:
commonAnnotations:
note: This is prod!
patches:
- path: ./increase_replicas.yaml
- path: ./configMap.yaml
- path: ./increase_replicas.yaml
- path: ./configMap.yaml
images:
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly/web
newTag: 7110f0af1a0657f441ec58e77895eda43be109c5
- name: REGISTRY/NAMESPACE/IMAGE:TAG
newName: mmc-registry.cn-shenzhen.cr.aliyuncs.com/sharefly/web
newTag: d9b1c885abb0c96b542bfcdff0335bb230ed2ebf
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
compilerOptions: {
types: ['@types/styled-components'],
styledComponents: true,
},
styledComponents: {
fileName: false,
ssr: true,
// compilerOptions: {
// types: ['@types/styled-components'],
// styledComponents: true,
// },
// styledComponents: {
// fileName: false,
// ssr: true,
// },
compiler: {
// see https://styled-components.com/docs/tooling#babel-plugin for more info on the options.
styledComponents: {
ssr: true,
fileName: false,
},
},
redirects() {
return [
......
......@@ -30,7 +30,7 @@
"env-cmd": "^10.1.0",
"js-base64": "^3.7.5",
"js-cookie": "^3.0.5",
"next": "14.0.1",
"next": "^14.0.4",
"next-redux-wrapper": "^8.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
......@@ -54,7 +54,7 @@
"eslint": "^8",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-next": "14.0.1",
"eslint-config-next": "^14.0.4",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-unused-imports": "^3.0.0",
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -89,3 +89,19 @@ export type GetAccountInfo = InterFunction<
createTime: string;
}
>;
// 测试-手机号登录
export type TestPhoneLogin = InterFunction<
{
phone: string;
},
{
authStatus: null;
nickName: string;
phoneNum: string;
portType: number;
sessionKey: null;
token: string;
uid: string;
userAccountId: number;
}
>;
// 商城订单-列表
import { InterFunction, InterListFunction } from '@/api/interface';
// 商城订单-列表(新)
export type MallOrderListType = InterListFunction<
{ keyword?: string; statusCode?: number },
OrderDetail
>;
// 订单详情
type OrderDetail = {
companyName: string;
confirmReceiptTime: string;
createTime: string;
deliveryTime: string;
id: number;
kdnExpDTO: {
logisticCode: string;
shipperCode: string;
stateEx: string;
traces: Array<{
acceptStation: string;
acceptTime: string;
action: string;
location: string;
}>;
};
orderNo: string;
orderTotalAmount: number;
orderType: number;
otherAmount: number;
payDTOList: Array<{
checkStatus: number;
createTime: string;
id: number;
payAmount: number;
payImgList: string;
payRemark: string;
payType: number;
refuseReason: string;
uavOrderId: number;
}>;
payTime: string;
payType: string;
remarkStatus: number;
salaryAmount: number;
sellerRemark: string;
shareAmount: number;
skuDTOList: Array<{
createTime: string;
id: number;
mallGoodsId: number;
orderNum: number;
priceStockId: number;
productSpec: string;
skuImage: string;
skuNo: string;
tradeName: string;
uavOrderId: number;
unitPrice: number;
}>;
statusCode: number;
thirdBackUserAccountId: number;
uavOrderExpressDTO: {
id: number;
receive: number;
receiveTime: string;
sendExpCode: string;
sendExpNo: string;
sendTime: string;
takeAddress: string;
takeName: string;
takePhone: string;
takeRegion: string;
uavOrderId: number;
};
updateTime: string;
userAccountId: number;
userAddressId: number;
userRemark: string;
version: number;
contractInfoDTO: {
archiveDate: null;
aremark: null;
atransactionId: null;
bremark: null;
btransactionId: null;
contractNo: string;
contractTitle: string;
createTime: string;
id: number;
orderNo: string;
signStatus: number;
singerTime: null;
unionId: string;
updateTime: null;
};
};
// 订单流程字典
export type UavOrderStatusListType = InterFunction<
{},
{
code: number;
id: number;
nextCode: number;
status: string;
}[]
>;
// 订单详情
export type UavOrderDetailType = InterFunction<
{
id: number;
},
OrderDetail
>;
......@@ -2,6 +2,7 @@ import {
GetAccountInfo,
GetAppletQRCode,
GetLoginInfo,
TestPhoneLogin,
} from '@/api/interface/common';
import request from '../request';
......@@ -25,4 +26,8 @@ export class CommonAPI {
// 获取用户信息
static getAccountInfo: GetAccountInfo = (params) =>
request.get('/userapp/user-account/info', { params });
// 测试-手机号登录
static testPhoneLogin: TestPhoneLogin = (params) =>
request.get('/userapp/auth/testPhoneLogin', { params });
}
import {
MallOrderListType,
UavOrderDetailType,
UavOrderStatusListType,
} from '@/api/interface/order';
import request from '@/api/request';
export class OrderAPI {
// 商城订单-列表(新)
static getMallOrderList: MallOrderListType = (data) =>
request.post('/oms/uav-order/listByUid', data);
// 订单流程字典
static uavOrderStatusList: UavOrderStatusListType = (params) =>
request.get('/oms/uav-order/statusList', params);
// 订单详情
static uavOrderDetail: UavOrderDetailType = (params) =>
request.get('/oms/uav-order/detail', { params });
}
......@@ -56,14 +56,15 @@ service.interceptors.response.use(
const isServer = typeof window === 'undefined';
if (isServer) {
// 如果是服务端
return Promise.reject(data);
// eslint-disable-next-line no-alert
window.confirm(data.message || '啊呀,出错了');
// window.confirm(data.message || '啊呀,出错了');
// eslint-disable-next-line no-restricted-globals
history.back();
} else {
// 如果还有其他报错那么就弹出报错信息(不需要对每个接口的报错做单独判断)
message.error(data.message || '啊呀,出错了').then();
// history.back();
}
// 如果还有其他报错那么就弹出报错信息(不需要对每个接口的报错做单独判断)
message.error(data.message || '啊呀,出错了').then();
return Promise.reject(data);
}
// 网络错误或链接超时
......
import React, { useEffect, useState } from 'react';
import { Button, Modal } from 'antd';
import { useRouter } from 'next/router';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { ListBannerImgType } from '@/api/interface/home';
import { RootState } from '@/store';
import { GlobalDataState, setGlobalData } from '@/store/module/globalData';
type AgreeType = InterDataType<ListBannerImgType>;
const AgreeModalView: React.FC<{
open: boolean;
}> = ({ open }) => {
// store
const dispatch = useDispatch();
// 路由钩子
const router = useRouter();
// system
const globalData = useSelector(
(state: RootState) => state.globalData,
) as GlobalDataState;
// 协议内容
const [agreementData, setAgreementData] = useState<AgreeType>();
// 关闭弹窗
const handleClose = () => {
dispatch(setGlobalData({ agreeModalVisible: false }));
// 如果需要返回
if (globalData.toastModalBack) router.back();
};
// 获取协议
const getAgreementData = async () => {
const res = await HomeAPI.listBannerImg({
moduleCode: 'SHAREFLY_ABOUT',
});
if (res && res.code === '200') {
setAgreementData(res.result);
}
};
useEffect(() => {
if (!open) return;
getAgreementData().then();
}, [open]);
return (
<Modal
open={open}
title={
globalData?.agreeModalType === 1 ? '云享飞隐私协议' : '云享飞用户协议'
}
onCancel={handleClose}
width={720}
footer={null}
>
<AgreeModalWrap>
<div className={'content'}>
{agreementData?.[globalData?.agreeModalType]?.textContent && (
<div
className="w-full"
dangerouslySetInnerHTML={{
__html:
agreementData?.[globalData?.agreeModalType]?.textContent,
}}
/>
)}
</div>
<Button type="primary" onClick={handleClose}>
同意并继续
</Button>
</AgreeModalWrap>
</Modal>
);
};
export default AgreeModalView;
// 样式
const AgreeModalWrap = styled.div`
position: relative;
width: 100%;
height: 26.8rem;
display: flex;
justify-content: flex-start;
align-items: center;
flex-direction: column;
box-sizing: border-box;
.content {
position: relative;
width: 100%;
height: 24.8rem;
margin-bottom: 1rem;
overflow-y: scroll;
box-sizing: border-box;
&::-webkit-scrollbar {
background-color: transparent;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
width: 7px;
height: 7px;
}
&::-webkit-scrollbar-thumb {
background: #d9d9d9;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
}
}
`;
......@@ -35,32 +35,55 @@ const BreadcrumbView: React.FC = () => {
const router = useRouter();
// 路由对应列表
const routerList = [
{ name: '云享商城', path: 'mall' },
{ name: '行业服务', path: 'service' },
{
name: '云享商城',
path: 'mall',
children: [{ name: '商品详情', path: 'product' }],
},
{
name: '行业服务',
path: 'service',
children: [{ name: '服务详情', path: 'detail' }],
},
{
name: '购物车',
path: 'cart',
children: [{ name: '提交订单', path: 'submit' }],
},
{
name: '我的订单',
path: 'order',
children: [
{ name: '提交成功', path: 'success' },
{ name: '订单详情', path: 'product' },
],
},
{ name: '设备租赁', path: 'rent' },
{ name: '执照培训', path: 'train' },
{ name: '飞手约单', path: 'flyer' },
{ name: '商品详情', path: 'product' },
{ name: '购物车', path: 'cart' },
{ name: '提交订单', path: 'submit' },
{ name: '服务详情', path: 'detail' },
];
// 转换路由
const getCurrentRouter = () => {
const arr = router?.pathname
?.split('/')
// 首先分割所有的路由
const route = router?.pathname?.split('/').filter((i) => i);
// 找到一级路由的元素
const item = routerList?.find((v) => v.path === route[0]);
// 拍平一级元素的路由地址
const arr = [item, ...(item?.children || [])];
// 转换路由数据
const brr = route
?.map((i, j) => {
const title = arr?.find((n) => n?.path === i)?.name;
const href = `/${router?.pathname
.split('/')
.slice(1, j + 1)
.slice(1, j + 2)
.join('/')}`;
const title = routerList?.find((n) => n.path === i)?.name;
return { title, href };
})
?.filter((i) => i.title); // 过滤掉没有title的项
// 最后一项不跳转
arr[arr.length - 1] = { title: arr[arr.length - 1]?.title, href: '' };
return arr;
brr[brr.length - 1] = { title: brr[brr.length - 1]?.title, href: '' };
return brr;
};
return (
<BreadcrumbWrap>
......
import React from 'react';
import { PhoneOutlined, ShopOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import { FooterWrap } from '@/components/layout/footer/styled';
import QrcodePopover from '@/components/qrcodePopover';
......@@ -110,30 +111,51 @@ const FooterView = () => {
</div>
</div>
<div className="footer-end">
<QrcodePopover path={'page-mine/help-center/index'}>
<Button type={'link'} className="end-item">
常见问题
</Button>
</QrcodePopover>
<QrcodePopover path={'page-mine/help-center/index'}>
<Button type={'link'} className="end-item">
意见反馈
</Button>
</QrcodePopover>
<QrcodePopover path={'page-mine/sharefly-about/index'}>
<Button type={'link'} className="end-item">
免责声明
<div className="flex w-full items-center">
<QrcodePopover path={'page-mine/help-center/index'}>
<Button type={'link'} className="end-item">
常见问题
</Button>
</QrcodePopover>
<QrcodePopover path={'page-mine/help-center/index'}>
<Button type={'link'} className="end-item">
意见反馈
</Button>
</QrcodePopover>
<QrcodePopover path={'page-mine/sharefly-about/index'}>
<Button type={'link'} className="end-item">
免责声明
</Button>
</QrcodePopover>
</div>
<div className="flex w-full items-center">
<div className="mr-4 text-999">
Copyright © 2021 - 2024 云享飞 版权所有
</div>
<Button
type={'link'}
className="p-0 text-999"
onClick={() => {
window.location.href = 'https://beian.miit.gov.cn';
}}
>
浙ICP备2023014395号
</Button>
</QrcodePopover>
<Button
type={'link'}
className="end-item"
onClick={() => {
window.location.href = 'https://beian.miit.gov.cn';
}}
>
浙ICP备2023014395号
</Button>
</div>
<div className="absolute right-0 top-4">
<div className="mb-1">
<ShopOutlined className="mr-2 text-999" />
<span className="text-999">
浙江省杭州市富阳区春江街道富春湾大道2723号17幢283号
</span>
</div>
<div>
<PhoneOutlined className="mr-2 -scale-x-100 text-999" />
<span className="text-999">
联系电话:0571-87199598/17706710318
</span>
</div>
</div>
</div>
</div>
</FooterWrap>
......
......@@ -7,7 +7,7 @@ export const FooterWrap = styled.div`
.footer-wrap {
position: relative;
max-width: 1190px;
height: 19.13rem;
min-height: 19.13rem;
box-sizing: border-box;
margin: 0 auto;
border-radius: 0;
......@@ -15,25 +15,27 @@ export const FooterWrap = styled.div`
//padding: 0 12rem;
display: flex;
align-items: center;
justify-content: flex-end;
justify-content: flex-start;
flex-direction: column;
}
&::after {
position: absolute;
content: '';
bottom: 5rem;
left: 12rem;
width: calc(100% - 24rem);
left: calc((100% - 1190px) / 2);
width: 1190px;
height: 0.02rem;
background: #bfbfbf;
}
.footer-end {
position: relative;
width: 100%;
height: 5rem;
display: flex;
align-items: center;
justify-content: center;
min-height: 5rem;
padding: 1rem 0;
box-sizing: border-box;
//display: flex;
//align-items: center;
//justify-content: center;
.end-item {
font-size: 12px;
font-weight: 400;
......@@ -64,7 +66,7 @@ export const FooterWrap = styled.div`
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
padding-top: 2.5rem;
padding: 2.5rem 0;
.start-item {
position: relative;
min-width: 8.6rem;
......
......@@ -7,6 +7,7 @@ import {
import { Button, Dropdown, MenuProps, Modal } from 'antd';
import dayjs from 'dayjs';
import Cookies from 'js-cookie';
import { useRouter } from 'next/router';
import { useDispatch, useSelector } from 'react-redux';
import { CommonAPI } from '@/api';
import { HeaderWrap } from '@/components/layout/header/styled';
......@@ -23,7 +24,7 @@ const HeaderView: React.FC<{
}> = ({ placeholder }) => {
const token = Cookies.get('SHAREFLY-WEB-TOKEN');
// 当前的路由数据
// const router = useRouter();
const router = useRouter();
// store
const dispatch = useDispatch();
// system
......@@ -60,6 +61,10 @@ const HeaderView: React.FC<{
dispatch(setAddress(res));
});
};
// 跳转详情
const handleDetail = async (item: { label: string; value: string }) => {
await router.push(item.value);
};
// 组件挂载
useEffect(() => {
if (!address?.city) {
......@@ -77,12 +82,12 @@ const HeaderView: React.FC<{
}
}, []);
// 顶部Tab列表
const tabList = [
{ label: '个人中心', value: 'pages/mine/index' },
{ label: '购物车', value: 'page-cart/cart-list/index' },
{ label: '我的订单', value: 'pages/order/index' },
{ label: '消息', value: 'pages/message/index' },
{ label: '联系客服', value: 'page-mine/help-center/index' },
const tabList: { label: string; value: string; isQrcode?: boolean }[] = [
{ label: '个人中心', value: 'pages/mine/index', isQrcode: true },
{ label: '购物车', value: 'page-cart/cart-list/index', isQrcode: true },
{ label: '我的订单', value: '/order', isQrcode: false },
{ label: '消息', value: 'pages/message/index', isQrcode: true },
{ label: '联系客服', value: 'page-mine/help-center/index', isQrcode: true },
];
// 右上角按钮
const items: MenuProps['items'] = [
......@@ -148,16 +153,37 @@ const HeaderView: React.FC<{
onClick={() => handleReload()}
></Button>
<div className="location-hello">Hi,欢迎来到云享飞</div>
{router?.pathname !== '/' && (
<Button
type={'link'}
className="text-[#fff]"
title="返回首页"
onClick={() => router.push('/')}
>
首页
</Button>
)}
</div>
<div className="header-nav">
<div className="nav-tab">
{tabList?.map((i, j) => (
<QrcodePopover path={i.value} key={j}>
<Button type={'link'} className="tab-item">
{tabList?.map((i, j) =>
!i.isQrcode ? (
<Button
type={'link'}
className="tab-item"
key={j}
onClick={() => handleDetail(i)}
>
{i.label}
</Button>
</QrcodePopover>
))}
) : (
<QrcodePopover path={i.value} key={j}>
<Button type={'link'} className="tab-item">
{i.label}
</Button>
</QrcodePopover>
),
)}
</div>
{!!userInfo?.id && (
<div className="nav-user">
......
......@@ -36,7 +36,7 @@ export const HeaderWrap = styled.div`
color: #ffffff;
}
.location-hello {
width: 8rem;
//width: 8rem;
}
.location-address {
margin: 0 0.25rem 0 0 !important;
......
import React from 'react';
import { useDispatch, useSelector } from 'react-redux';
import AgreeModalView from '@/components/agreeModal/index';
import ContentView from '@/components/layout/content';
import FooterView from '@/components/layout/footer';
import HeaderView from '@/components/layout/header';
......@@ -60,6 +61,8 @@ const LayoutView: React.FC<{
open={globalData?.toastModalVisible}
onCancel={handleModalClose}
/>
{/* 协议弹窗 */}
<AgreeModalView open={globalData?.agreeModalVisible} />
</LayoutWrap>
);
};
......
import React, { useEffect, useState } from 'react';
import { ReloadOutlined } from '@ant-design/icons';
import { message, Modal } from 'antd';
import Cookies from 'js-cookie';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import { CommonAPI } from '@/api';
import { RootState } from '@/store';
import { GlobalDataState } from '@/store/module/globalData';
import { setSystem } from '@/store/module/system';
import { setUserInfo } from '@/store/module/userInfo';
export const LoginModalWrap = styled.div`
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
box-sizing: border-box;
padding: 0.68rem 0;
.qrcode {
position: relative;
width: 10.68rem;
height: 10.68rem;
margin: 1.5rem 0 1rem 0;
//background-image: url('https://file.iuav.com/file/sharefly-qrcode-wx.jpg');
//background-size: 100% 100%;
//background-size: cover;
//background-position: center;
.image {
width: 100%;
height: 100%;
object-fit: cover;
}
.shadow {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
flex-direction: column;
background: rgba(0, 0, 0, 0.68);
.refresh {
position: relative;
width: 3rem;
height: 3rem;
border-radius: 50%;
background: #fff;
margin-bottom: 1rem;
&:active {
filter: brightness(0.9);
transform: rotate(360deg);
transition: all 0.3s ease-in-out;
}
}
.text {
color: #fff;
}
}
}
.title {
color: #222;
font-size: 16px;
font-weight: bold;
}
.text {
color: #333;
font-size: 12px;
line-height: 20px;
text-align: center;
}
.action {
color: #999;
font-size: 12px;
line-height: 20px;
text-align: center;
margin: 1rem 0;
text-decoration: underline;
cursor: pointer;
&:hover,
&:active {
color: #ff552d;
}
}
`;
// 定时器暂存
let timer: NodeJS.Timer;
const LoginModalView = ({
open,
onCancel,
}: {
open: boolean;
onCancel: () => void;
}) => {
// system
const globalData = useSelector(
(state: RootState) => state.globalData,
) as GlobalDataState;
// store
const dispatch = useDispatch();
// 获取小程序二维码唯一标识
const [randomLoginCode, setRandomLoginCode] = useState<string>(
`${parseInt(String(Math.random() * 10001), 10)}`,
);
// 二维码是否过期
const [qrCodeExpired, setQrCodeExpired] = useState<boolean>(false);
// 登录二维码的地址
const [qrCodeData, setQrCodeData] = useState<string>();
// 获取登录二维码
const getQrcodeLogin = async () => {
// 获取二维码
const res = await CommonAPI.getAppletQRCode({
page: 'page-identity/identity-empower/index',
scene: `randomLoginCode=${randomLoginCode}&port=0`,
});
if (res && res.code === '200') {
if (!res.result) {
message.warning('获取登录二维码失败');
return;
}
// 设置当前登录的二维码
setQrCodeData(`data:image/png;base64,${res.result}`);
// 设置二维码倒计时
setQrCodeExpiredTimer();
}
};
// 跳转管理平台
const handleBackEnd = () => {
window.open('https://admin.iuav.com');
};
// 刷新二维码
const handleRefresh = () => {
setRandomLoginCode(`${parseInt(String(Math.random() * 10001), 10)}`);
getQrcodeLogin().then(() => {
setQrCodeExpired(false);
});
};
// 定时器设置二维码过期
const setQrCodeExpiredTimer = () => {
setTimeout(
() => {
setQrCodeExpired(true);
// 关闭定时器
if (timer) clearInterval(timer);
},
1000 * 60 * 5,
);
};
// 获取登录信息
const getLoginInfo = async () => {
if (!randomLoginCode) return;
const res = await CommonAPI.getLoginInfo({
randomLoginCode,
});
// console.log('获取登录信息 --->', res);
if (res && res.code === '200') {
// 关闭定时器
if (timer) clearInterval(timer);
// 刷新二维码
setQrCodeExpired(true);
// 关闭弹窗
onCancel?.();
// 设置用户信息
dispatch(setUserInfo(res.result));
// 设置token
dispatch(setSystem({ token: res.result.token }));
// 设置token
Cookies.set('SHAREFLY-WEB-TOKEN', res.result.token);
message.success('登录成功');
// 刷新当前页面
window.location.reload();
}
};
// 设置定时器轮询获取信息
const setLoginInfoTimer = () => {
timer = setInterval(async () => {
await getLoginInfo();
}, 2500);
};
// 关闭弹窗
const handleClose = () => {
onCancel?.();
// 关闭定时器
if (timer) clearInterval(timer);
};
// 组件挂载
useEffect(() => {
if (!open) {
// 关闭定时器
if (timer) clearInterval(timer);
return;
}
// 获取二维码
getQrcodeLogin().then(() => {
setQrCodeExpired(false);
setLoginInfoTimer();
});
}, [open]);
return (
<Modal open={open} footer={null} onCancel={handleClose}>
<LoginModalWrap>
<div className="title">
{globalData?.loginModalTitle || `微信扫码登录`}
</div>
<div className="qrcode">
{qrCodeData && (
<img src={qrCodeData} alt="登录二维码" className="image" />
)}
{qrCodeExpired && (
<div className="flex-center animate__animated animate__fast animate__fadeIn shadow">
<div className="refresh flex-center" onClick={handleRefresh}>
<ReloadOutlined style={{ fontSize: '20px' }} />
</div>
<div className="text">二维码已过期,请重新扫描</div>
</div>
)}
</div>
<div className="text">微信扫一扫,打开小程序</div>
<div className="text">即可登录/注册</div>
<div
className="action"
onClick={handleBackEnd}
style={{ visibility: 'hidden' }}
>
管理平台登录 {'>'}
</div>
<div className="text">「云享飞,让天空为世界所用」</div>
</LoginModalWrap>
</Modal>
);
};
export default LoginModalView;
import React from 'react';
import styled from 'styled-components';
const TableItem: React.FC<{
td?: React.ReactNode;
tr?: React.ReactNode;
}> = ({ td, tr }) => {
return (
<OrderTableItem>
<div className="item-td">{td}</div>
<div className="item-tr">{tr}</div>
</OrderTableItem>
);
};
export default TableItem;
// 样式
const OrderTableItem = styled.div`
.item-td {
position: absolute;
top: 0;
left: 0;
height: 36px;
width: 100%;
background: rgba(22, 119, 255, 0.1);
line-height: 36px;
}
.item-tr {
//min-height: 50px;
width: 100%;
margin-top: 28px;
}
`;
......@@ -124,9 +124,12 @@ const PaymentCheckout: React.FC<{ cost: number }> = ({ cost }) => {
useEffect(() => {
if (!system?.token) return;
getUserPayWalletInfo().then();
}, [cost]);
// 钱包金额副作用
useEffect(() => {
if (!cost) return;
setDefaultSelect();
}, [cost]);
}, [walletInfo]);
return (
<PaymentCheckoutWrap>
<Checkbox.Group value={paymentTypeValue} onChange={setPaymentTypeValue}>
......
import React from 'react';
import { Input, Modal } from 'antd';
import { Input, message, Modal } from 'antd';
import Big from 'big.js';
import { GetServerSidePropsContext } from 'next';
import { useRouter } from 'next/router';
......@@ -79,14 +79,12 @@ const MallCartSubmitView: React.FC<{
content: `确认提交订单?`,
onOk: () => {
dispatch(setGlobalData({ loadingSpinnerVisible: true }));
setTimeout(() => {
dispatch(
setGlobalData({
toastModalVisible: true,
toastModalBack: true,
loadingSpinnerVisible: false,
}),
);
setTimeout(async () => {
dispatch(setGlobalData({ loadingSpinnerVisible: false }));
await Promise.all([
message.success('订单提交成功'),
router.push('/order/success/236'),
]);
}, 1000);
},
});
......@@ -169,10 +167,11 @@ const MallCartSubmitWrap = styled.div`
.submit-remark {
position: relative;
width: 100%;
min-height: 4.5rem;
min-height: 4rem;
background: #f2f7ff;
border: 0.04rem solid #d0eaf5;
padding: 0.67rem;
padding: 0.67rem 0.67rem 1.3rem 0.67rem;
box-sizing: border-box;
margin-bottom: 1rem;
.remark-view {
position: relative;
......
......@@ -27,6 +27,6 @@ export async function getServerSideProps() {
}
const MallSecondView: React.FC<{
categoryList: CategoryListType;
}> = (props) => MallView(props);
}> = (props) => <MallView {...props} />;
export default MallSecondView;
......@@ -27,6 +27,6 @@ export async function getServerSideProps() {
}
const MallMainView: React.FC<{
categoryList: CategoryListType;
}> = (props) => MallView(props);
}> = (props) => <MallView {...props} />;
export default MallMainView;
import React, { useEffect, useState } from 'react';
import { Button, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import { useRouter } from 'next/router';
import { useDispatch, useSelector } from 'react-redux';
import { InterDataType, InterListType, PaginationProps } from '@/api/interface';
import {
MallOrderListType,
UavOrderStatusListType,
} from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
import TableItem from '@/components/orderTableItem';
import { RootState } from '@/store';
import { setGlobalData } from '@/store/module/globalData';
import { SystemState } from '@/store/module/system';
// 列表类型
type ListType = InterListType<MallOrderListType>;
// 状态列表
type StatusType = InterDataType<UavOrderStatusListType>;
const MallOrderListTable: React.FC = () => {
// store
const dispatch = useDispatch();
// system
const system = useSelector((state: RootState) => state.system) as SystemState;
// 路由钩子
const router = useRouter();
// 订单状态列表
const [statusList, setStatusList] = useState<StatusType>();
// 订单列表
const [tableData, setTableData] = useState<ListType>();
// 表格分页配置
const [pagination, setPagination] = useState<
PaginationProps & { totalCount: number }
>({
pageSize: 10,
pageNo: 1,
totalCount: 0,
});
// 获取商城订单
const getGoodsOrderList = async () => {
const res = await OrderAPI.getMallOrderList({
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
});
if (res && res.code === '200') {
const { list, pageNo, pageSize, totalCount } = res.result; // 解构
setPagination({
...pagination,
pageNo,
pageSize,
totalCount,
});
setTableData(list || []);
// console.log('商城订单 --->', list);
}
};
// 翻页
const paginationChange = (pageNo: number, pageSize: number) => {
pagination.pageNo = pageNo;
pagination.pageSize = pageSize;
getGoodsOrderList().then();
};
// 获取订单状态字典
const getMallOrderStatusList = async () => {
const res = await OrderAPI.uavOrderStatusList();
if (res && res.code === '200') {
setStatusList(res.result);
}
};
// 获取订单价格
const getOrderPrice = (item: ListType[0]) => {
const total = item?.skuDTOList?.reduce(
(sum, value) => sum + Number(value.orderNum) * Number(value.unitPrice),
0,
);
// 求和
return `¥${total?.toLocaleString()}`;
};
// 跳转商品详情
const handleProduct = async (item: ListType[0]['skuDTOList'][0]) => {
await router.push(`/mall/product/${item?.mallGoodsId}`);
};
// 跳转订单详情
const handleDetail = async (item: ListType[0]) => {
await router.push(`/order/product/${item?.id}`);
};
// 页面挂载
useEffect(() => {
if (!system?.token) {
dispatch(
setGlobalData({
loginModalVisible: true,
loginModalBack: true,
}),
);
} else {
getMallOrderStatusList().then();
getGoodsOrderList().then();
}
}, [system]);
const tableColumns: ColumnsType<ListType[0]> = [
{
title: '商品',
dataIndex: 'id',
align: 'center',
width: 200,
render: (_text, record) => (
<TableItem
td={<>订单编号:{record?.orderNo}</>}
tr={
<>
{record.skuDTOList?.map((i, j) => (
<div className="flex items-start pt-2" key={j}>
<img
className="h-12 w-12"
src={i.skuImage}
alt={i.tradeName}
/>
<div className="ml-2 flex flex-col items-start">
<Button
className="h-auto w-48 text-ellipsis p-0 text-left"
type="link"
onClick={() => handleProduct(i)}
>
{i.tradeName}
</Button>
<div>
{Object.entries(JSON.parse(i.productSpec)).map(
(v, index) => (
<span key={index} className="mr-2 last:mr-0">
{v.join(':')}
</span>
),
)}
</div>
</div>
</div>
))}
</>
}
/>
),
},
{
title: '数量',
dataIndex: 'id',
align: 'center',
render: (_text, record) => (
<TableItem
tr={
<>
{record.skuDTOList?.reduce(
(sum, value) => sum + Number(value?.orderNum),
0,
)}
</>
}
/>
),
},
{
title: '价格',
dataIndex: 'id',
align: 'center',
render: (_text, record) => (
<TableItem
td={<>下单时间:{record?.createTime}</>}
tr={<>{getOrderPrice(record)}</>}
/>
),
},
{
title: '订单状态',
dataIndex: 'statusCode',
align: 'center',
width: 150,
render: (text) => (
<TableItem
tr={<>{statusList?.find((i) => i.code === text)?.status || text}</>}
/>
),
},
{
title: '操作',
dataIndex: 'id',
align: 'center',
width: 150,
render: (_text, record) => (
<TableItem
tr={
<>
<Button type={'link'} onClick={() => handleDetail(record)}>
订单详情
</Button>
</>
}
/>
),
},
];
return (
<>
<Table
rowKey={'id'}
bordered={false}
dataSource={tableData}
columns={tableColumns}
pagination={{
total: pagination.totalCount,
pageSize: pagination.pageSize,
current: pagination.pageNo,
showSizeChanger: true,
showQuickJumper: true,
onChange: (page: number, pageSize: number) =>
paginationChange(page, pageSize),
showTotal: (total, range) =>
`当前 ${range[0]}-${range[1]} 条记录 / ${total} 条数据`,
}}
/>
</>
);
};
export default MallOrderListTable;
import React, { useEffect, useState } from 'react';
import { Image, Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { UavOrderDetailType } from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
// 接口返回的类型
type DataType = InterDataType<UavOrderDetailType>;
// 参数类型
type PropsType = {
detail: DataType | undefined;
};
const MallOrderSpecView: React.FC<PropsType> = (props) => {
const { detail } = props;
// 表格结构
const columns: ColumnsType<DataType['skuDTOList'][0]> = [
{
title: '商品',
align: 'center',
width: '20%',
render: (_text, record) => (
<div className="mall-sku-item">
<Image src={record.skuImage} className="sku-img" />
<div className="sku-info">
<div className="info-name">{record.tradeName}</div>
<div className="info-spec">
{Object.entries(JSON.parse(record.productSpec)).map(
(v, index) => (
<span key={index}>{v.join(':')}</span>
),
)}
</div>
</div>
</div>
),
},
{
title: '单价(元)',
dataIndex: 'unitPrice',
align: 'center',
render: (text) => `¥${text?.toLocaleString()}`,
},
{
title: '数量',
dataIndex: 'orderNum',
align: 'center',
},
{
title: '订单状态',
align: 'center',
render: () =>
orderStatusList.find((v) => v.value === detail?.statusCode)?.label,
},
{
title: '订单金额(元)',
align: 'center',
render: () => `${detail?.orderTotalAmount}`,
},
];
// 订单状态
const [orderStatusList, setOrderStatusList] = useState<
{ value: number; label: string }[]
>([]);
// 获取订单状态
const getOrderStatus = () => {
OrderAPI.uavOrderStatusList().then(({ result }) => {
if (result) {
const list = result.map((item) => ({
value: item.code,
label: item.status,
}));
setOrderStatusList(list);
}
});
};
useEffect(() => {
getOrderStatus();
}, []);
return (
<DetailInfoWrap>
<div className="detail-title">订单明细</div>
<Table
size="small"
dataSource={detail?.skuDTOList || []}
columns={columns}
rowKey="id"
bordered
pagination={false}
// rowSelection={{ selectedRowKeys, onChange: onSelectChange }}
/>
</DetailInfoWrap>
);
};
export default MallOrderSpecView;
// 样式
const DetailInfoWrap = styled.div`
.detail-title {
font-weight: bold;
margin: 1rem 0 0.5rem 0;
}
.mall-sku-item {
display: flex;
align-items: center;
margin-bottom: 10px;
.sku-img {
width: 48px;
height: 48px;
}
.sku-info {
margin-left: 10px;
line-height: 16px;
text-align: left;
.info-name {
color: #1677ff;
}
.info-spec {
margin-top: 10px;
span:not(:last-child) {
&:after {
content: ';';
}
}
}
}
}
`;
import React from 'react';
import { ShopOutlined, UnorderedListOutlined } from '@ant-design/icons';
import { Menu, MenuProps } from 'antd';
import styled from 'styled-components';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import MallOrderListTable from '@/pages/order/comp/mallOrderLsit/_index';
type MenuItem = Required<MenuProps>['items'];
const OrderListView = () => {
// 菜单栏点击事件
const handleMenuClick = (e: { key: string; keyPath: string[] }) => {
console.log(e);
};
// 菜单栏数据
const menuList: MenuItem = [
{
key: '1',
label: '全部订单',
icon: <UnorderedListOutlined />,
children: [
{
key: '11',
label: '商城订单',
icon: <ShopOutlined />,
},
],
},
];
return (
<LayoutView>
<OrderListWrap>
<BreadcrumbView />
<div className="flex w-full items-start justify-start pb-8 pt-2">
<div className="select">
<Menu
mode="inline"
items={menuList}
defaultOpenKeys={['1']}
defaultSelectedKeys={['11']}
onClick={handleMenuClick}
/>
</div>
<div className="list">
<MallOrderListTable />
</div>
</div>
</OrderListWrap>
</LayoutView>
);
};
export default OrderListView;
// 样式
const OrderListWrap = styled.div`
position: relative;
max-width: 1190px;
box-sizing: border-box;
padding: 2rem 0 0 0;
margin: 0 auto;
.select {
position: relative;
width: 15%;
}
.list {
position: relative;
width: 85%;
}
`;
import React, { useEffect, useState } from 'react';
import { Descriptions, DescriptionsProps, Result } from 'antd';
import { useRouter } from 'next/router';
import styled from 'styled-components';
import { InterDataType } from '@/api/interface';
import { UavOrderDetailType } from '@/api/interface/order';
import { OrderAPI } from '@/api/modules/order';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import MallOrderSpecView from '@/pages/order/comp/mallOrderSpec';
// 详情类型
type DetailType = InterDataType<UavOrderDetailType>;
const OrderProductDetail = () => {
// 路由钩子
const router = useRouter();
// 订单详情
const [orderDetail, setOrderDetail] = useState<DetailType>();
// 获取订单详情
const getOrderDetail = async () => {
const res = await OrderAPI.uavOrderDetail({
id: Number(router.query?.id),
});
if (res && res.code === '200') {
// console.log(res.result);
setOrderDetail(res.result);
}
};
useEffect(() => {
if (router.query?.id) getOrderDetail().then();
}, [router.query]);
// 订单信息
const items: DescriptionsProps['items'] = [
{
key: '1',
label: '收货人',
children: (
<>
{orderDetail?.uavOrderExpressDTO?.takeName}{' '}
{orderDetail?.uavOrderExpressDTO?.takePhone}
</>
),
},
{
key: '2',
label: '收货地址',
children: (
<>
{orderDetail?.uavOrderExpressDTO?.takeRegion?.replaceAll('/', ' ')}{' '}
{orderDetail?.uavOrderExpressDTO?.takeAddress}
</>
),
},
{
key: '3',
label: '订单编号',
children: <>{orderDetail?.orderNo}</>,
},
{
key: '4',
label: '下单时间',
children: <>{orderDetail?.createTime}</>,
},
{
key: '5',
label: '付款时间',
children: <>{orderDetail?.createTime}</>,
},
{
key: '6',
label: '订单备注',
children: <>{orderDetail?.userRemark}</>,
},
];
return (
<LayoutView>
<OrderProductWrap>
<BreadcrumbView />
<div className="order-detail">
<div className="detail-content">
<Descriptions title="订单信息" items={items} column={1} />
</div>
<div className="detail-result">
<Result title="订单状态:意向提交成功!请等待专员联系您,根据实际需求报价~" />
</div>
</div>
<MallOrderSpecView detail={orderDetail} />
</OrderProductWrap>
</LayoutView>
);
};
export default OrderProductDetail;
// 样式
const OrderProductWrap = styled.div`
position: relative;
max-width: 1190px;
box-sizing: border-box;
padding: 2rem 0 0 0;
margin: 0 auto;
.order-detail {
position: relative;
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: nowrap;
margin-top: 1rem;
border: 0.02rem solid #e3e3e3;
border-radius: 0.5rem;
overflow: hidden;
.detail-content {
position: relative;
width: 30%;
background: #f7f8fa;
box-sizing: border-box;
padding: 0.5rem 1rem;
}
.detail-result {
position: relative;
width: 70%;
min-height: 14rem;
display: flex;
justify-content: center;
align-items: center;
}
}
`;
import React, { useEffect, useState } from 'react';
import { CheckCircleFilled } from '@ant-design/icons';
import { Button } from 'antd';
import { useRouter } from 'next/router';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { RecommendGoodsType } from '@/api/interface/home';
import BreadcrumbView from '@/components/breadcrumb';
import LayoutView from '@/components/layout';
import ProductItemView from '@/components/productItem';
// 列表类型
type ListType = InterDataType<RecommendGoodsType>;
const OrderSuccessView = () => {
// 路由钩子
const router = useRouter();
// 推荐商品列表
const [recommendGoodsList, setRecommendGoodsList] = useState<
ListType[0]['mallGoodsList']
>([]);
// 获取推荐商品
const getRecommendGoodsList = async () => {
const res = await HomeAPI.getRecommendGoods();
if (res && res.code === '200') {
const list = res.result || [];
setRecommendGoodsList(
list
?.map((i) => i.mallGoodsList)
?.flat()
?.slice(0, 10),
);
}
};
// 跳转订单详情
const handleDetail = async () => {
await router.push(`/order/product/${router.query?.id}`);
};
// 页面加载
useEffect(() => {
getRecommendGoodsList().then();
}, []);
return (
<LayoutView>
<OrderSuccessWrap>
<BreadcrumbView />
<div className="order-success">
<div className="success-title">
<CheckCircleFilled className="text-3xl text-[#54A536]" />
<div className="title">您已成功付款</div>
</div>
<div className="success-content">
<div className="content-item mb-2 flex">
<div className="item-label">收货地址:</div>
<div className="item-value">
浙江省杭州市富阳区银湖街道富闲路15号浙大网新银湖科技园25幢{' '}
吴彦祖 18888888888
</div>
</div>
<div className="content-item mb-2 flex">
<div className="item-label">实付款:</div>
<div className="item-value price">¥19.9</div>
</div>
<Button type="link" className="mb-2 px-0" onClick={handleDetail}>
查看订单
</Button>
</div>
</div>
<div className="order-product">
{recommendGoodsList?.map((i, j) => (
<ProductItemView key={j} detail={i as any} />
))}
</div>
</OrderSuccessWrap>
</LayoutView>
);
};
export default OrderSuccessView;
// 样式
const OrderSuccessWrap = styled.div`
position: relative;
max-width: 1190px;
box-sizing: border-box;
padding: 2rem 0 0 0;
margin: 0 auto;
.order-success {
position: relative;
width: 100%;
box-sizing: border-box;
min-height: 8.25rem;
border: 0.02rem solid #e3e3e3;
margin-bottom: 1rem;
.success-title {
position: relative;
width: 100%;
height: 3.5rem;
background: #ecffdc;
display: flex;
justify-content: flex-start;
align-items: center;
box-sizing: border-box;
padding: 0 5rem;
margin-bottom: 1rem;
.title {
font-size: 16px;
font-weight: bold;
margin-left: 1rem;
}
}
.success-content {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0 5rem;
color: #999999;
.price {
color: #ea0000;
font-weight: bold;
}
}
}
.order-product {
position: relative;
width: 100%;
box-sizing: border-box;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
margin-bottom: 1rem;
}
`;
import React, { useEffect, useState } from 'react';
import { Button, Checkbox, Col, Form, Input, message, Row } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import styled from 'styled-components';
import LayoutView from '@/components/layout';
import { RootState } from '@/store';
import { setGlobalData } from '@/store/module/globalData';
import { SystemState } from '@/store/module/system';
const UserSignupView = () => {
// store
const dispatch = useDispatch();
// system
const system = useSelector((state: RootState) => state.system) as SystemState;
// 表单钩子
const [formRef] = Form.useForm<{
password: string;
username: string;
code: string;
}>();
// 是否选择协议
const [checkValue, setCheckValue] = useState<boolean>(false);
// 提交数据
const handleSubmit = async () => {
if (!checkValue) {
await message.warning('请先阅读并接受用户协议和隐私协议');
return;
}
const values = await formRef.validateFields().catch((err) => {
Promise.all(
err?.errorFields?.map((i: { errors: string[] }) =>
message.warning(i?.errors[0]),
),
);
});
if (!values) return;
message.loading('注册中...');
};
// 跳转回登录
const handleLogin = () => {
dispatch(setGlobalData({ loginModalVisible: true }));
};
// 获取二维码
const handleGetCode = async () => {
await message.loading('获取中...');
};
// 打开协议弹窗
const handleAgree = (type: number) => {
dispatch(setGlobalData({ agreeModalVisible: true, agreeModalType: type }));
};
// 页面挂载
useEffect(() => {
if (!system?.token) return;
// 如果有token则跳转回首页
window.location.href = '/';
}, [system]);
return (
<LayoutView placeholder={false}>
<UserSignupBg />
<UserSignupWrap>
<div className="login-title"></div>
<div className="login-box">
<div className="title">欢迎注册</div>
<div className="already mb-14">
<span>已有账号?</span>
<span className="bold cursor-pointer" onClick={handleLogin}>
登录
</span>
</div>
<Form
name="signForm"
form={formRef}
autoComplete="off"
className="w-full"
size="large"
labelAlign="left"
labelCol={{ span: 4 }}
>
<Form.Item
label="手机号"
name="username"
required={false}
rules={[{ required: true, message: '请输入登录的账号' }]}
>
<Input placeholder="请输入手机号" maxLength={11} allowClear />
</Form.Item>
<Form.Item
label="密码"
name="password"
required={false}
rules={[{ required: true, message: '请输入密码' }]}
>
<Input
placeholder="请输入密码"
type="password"
maxLength={20}
allowClear
autoComplete="new-password"
/>
</Form.Item>
<Form.Item label="验证码">
<Row gutter={8}>
<Col span={15}>
<Form.Item
name="code"
noStyle
rules={[
{
required: true,
message: '请输入验证码',
},
]}
>
<Input
placeholder="请输入验证码"
maxLength={8}
allowClear
/>
</Form.Item>
</Col>
<Col span={8}>
<Button onClick={handleGetCode}>获取验证码</Button>
</Col>
</Row>
</Form.Item>
</Form>
<div
className={`submit mt-14 cursor-pointer ${checkValue && 'active'}`}
onClick={handleSubmit}
>
立即注册
</div>
<div className="checkbox mt-4">
<Checkbox
checked={checkValue}
onChange={(e) => setCheckValue(e.target?.checked)}
>
<span>阅读并接受</span>
<span
className="bold cursor-pointer"
onClick={() => handleAgree(2)}
>
云享飞用户协议
</span>
<span></span>
<span
className="bold cursor-pointer"
onClick={() => handleAgree(1)}
>
隐私协议
</span>
</Checkbox>
</div>
</div>
</UserSignupWrap>
</LayoutView>
);
};
export default UserSignupView;
// 样式
const UserSignupWrap = styled.div`
position: relative;
height: 99.8vh;
max-width: 1190px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: flex-end;
box-sizing: border-box;
padding: 0 5% 0 0;
.login-title {
position: absolute;
top: 15%;
left: 0;
width: 9.25rem;
height: 2.08rem;
background-image: url('https://file.iuav.com/file/sharefly-signup-title.png');
background-size: cover;
}
.login-box {
position: relative;
width: 23.29rem;
height: 28.5rem;
background: rgba(255, 255, 255, 0.86);
border-radius: 0.58rem;
box-sizing: border-box;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
padding: 1.83rem 1.83rem 0;
.title {
position: relative;
width: 100%;
font-size: 20px;
font-weight: bold;
color: #333333;
letter-spacing: 1px;
margin-bottom: 0.2rem;
}
.already {
position: relative;
width: 100%;
color: #999999;
.bold {
color: #fd562c;
}
}
.submit {
position: relative;
box-sizing: border-box;
width: 19.38rem;
height: 2.5rem;
background: #ffab95;
border-radius: 1.29rem;
text-align: center;
line-height: 2.25rem;
color: #ffffff;
}
.active {
background: #fd562c;
}
.checkbox {
.bold {
color: #fd562c;
margin: 0 0.25rem;
}
}
}
@media screen and (max-width: 1200px) {
padding: 0;
justify-content: center;
}
@media screen and (min-width: 1550px) {
padding: 0;
}
`;
// 图片
const UserSignupBg = styled.div`
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 99.8vh;
background-image: url('https://file.iuav.com/file/sharefly-signup-bg.png');
background-size: cover;
`;
......@@ -9,6 +9,7 @@ export type GlobalDataState = {
loadingSpinnerVisible: boolean;
loginModalVisible: boolean;
loginModalTitle?: string;
loginModalBack: boolean;
qrcodeModalVisible: boolean;
qrcodeModalPath?: string;
qrcodeModalScene?: string;
......@@ -18,14 +19,19 @@ export type GlobalDataState = {
priceUnitList?: InterDataType<ListInspectionPriceUnit>;
toastModalVisible: boolean;
toastModalBack: boolean;
agreeModalVisible: boolean;
agreeModalType: number;
};
const initialState: GlobalDataState = {
loadingSpinnerVisible: false,
loginModalVisible: false,
loginModalBack: false,
qrcodeModalVisible: false,
toastModalVisible: false,
toastModalBack: false,
agreeModalVisible: false,
agreeModalType: 1,
};
const globalDataSlice = createSlice({
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论