提交 24167655 作者: ZhangLingKun

测试:测试推送部署

上级 bc8b8fa0
流水线 #7167 已失败 于阶段
in 18 秒
.DS_Store
.next
node_modules
build
Dockerfile
#请求接口地址
#正式服
#NEXT_PUBLIC_BASE_URL='https://www.iuav.com'
#测试服
NEXT_PUBLIC_BASE_URL='https://test.iuav.com'
#版本
NODE_ENV='development'
#请求接口地址
NEXT_PUBLIC_BASE_URL='https://www.iuav.com'
#版本
NODE_ENV='production'
{
"env": {
"es6": true,
"node": true
},
"plugins": ["prettier"],
"extends": [
"airbnb-base",
"next/core-web-vitals",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:jsx-a11y/recommended",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true
}
]
},
"overrides": [
// Configuration for TypeScript files
{
"files": ["**/*.ts", "**/*.tsx"],
"plugins": ["@typescript-eslint", "unused-imports"],
"extends": [
"airbnb-typescript",
"next/core-web-vitals",
"plugin:prettier/recommended"
],
"parserOptions": {
"project": "./tsconfig.json"
},
"rules": {
"prettier/prettier": [
"error",
{
"singleQuote": true
}
],
"react/destructuring-assignment": "off", // Vscode doesn't support automatically destructuring, it's a pain to add a new variable
"jsx-a11y/anchor-is-valid": "off", // Next.js use his own internal link system
"react/require-default-props": "off", // Allow non-defined react props as undefined
"react/jsx-props-no-spreading": "off", // _app.tsx uses spread operator and also, react-hook-form
"@next/next/no-img-element": "off", // We currently not using next/image because it isn't supported with SSG mode
"import/order": [
"error",
{
"groups": ["builtin", "external", "internal"],
"pathGroups": [
{
"pattern": "react",
"group": "external",
"position": "before"
}
],
"pathGroupsExcludedImportTypes": ["react"],
"newlines-between": "never",
"alphabetize": {
"order": "asc",
"caseInsensitive": true
}
}
],
"@typescript-eslint/no-use-before-define": "warn",
"@typescript-eslint/comma-dangle": "off", // Avoid conflict rule between Eslint and Prettier
"import/prefer-default-export": "off", // Named export is easier to refactor automatically
"class-methods-use-this": "off", // _document.tsx use render method without `this` keyword
"@typescript-eslint/no-unused-vars": "off",
"unused-imports/no-unused-imports": "warn",
"unused-imports/no-unused-vars": [
"warn",
{ "argsIgnorePattern": "^_" }
],
"jsx-a11y/click-events-have-key-events": "off",
"jsx-a11y/no-static-element-interactions": "off",
"eqeqeq": "warn",
"no-unsafe-optional-chaining": "warn",
"no-param-reassign": "warn"
}
}
]
}
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
/dist
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
.idea
.vscode
.hbuilderx
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
#pnpm-lock.yaml*
yarn-lock.yaml*
package-lock.yaml*
package-lock.json*
yarn.lock*
tsconfig.tsbuildinfo*
stages:
- dockerbuild
- kustomize_tag_push
variables:
REGION_id: cn-shenzhen
REGISTRY: mmc-registry.cn-shenzhen.cr.aliyuncs.com
IMAGE: admin
TAG: $CI_COMMIT_SHA
ACR_EE_USERNAME: QD--KeBiTeHangKong@1354706964800968
ACR_EE_PASSWORD: MMC@2023&ACR
ACR_EE_REGISTRY: mmc-registry.cn-shenzhen.cr.aliyuncs.com
ACR_EE_INSTANCE_ID: cri-yhk5zgfc2v1sia6l
ACR_EE_IMAGE: web
ACR_EE_TAG: $CI_COMMIT_SHA
JAVA_VERSION: '8'
GITLAB_URL: https://oauth2:MjVJKxB7m4tCy7symBzn@git.mmcuav.cn/iuav/csf-web.git
docker_build_dev:
stage: dockerbuild
variables:
NAMESPACE: sharefly-dev
ACR_EE_NAMESPACE: sharefly-dev
PROFILES_ACTIVE: development
only:
- develop
script:
- echo "dev docker build"
- echo $ACR_EE_USERNAME
- echo $ACR_EE_REGISTRY
- docker login -u $ACR_EE_USERNAME -p 'MMC@2023&ACR' $ACR_EE_REGISTRY
- docker build --build-arg PROFILES_ACTIVE=$PROFILES_ACTIVE -t "$ACR_EE_REGISTRY/$ACR_EE_NAMESPACE/$ACR_EE_IMAGE:$TAG" .
- docker push "${ACR_EE_REGISTRY}/${ACR_EE_NAMESPACE}/${ACR_EE_IMAGE}:${TAG}"
- docker logout
docker_build_prod:
stage: dockerbuild
variables:
NAMESPACE: sharefly
ACR_EE_NAMESPACE: sharefly
PROFILES_ACTIVE: production
only:
- master
script:
- echo "prod docker build"
- echo $ACR_EE_USERNAME
- echo $ACR_EE_REGISTRY
- docker login -u $ACR_EE_USERNAME -p 'MMC@2023&ACR' $ACR_EE_REGISTRY
- docker build --build-arg PROFILES_ACTIVE=$PROFILES_ACTIVE -t "$ACR_EE_REGISTRY/$ACR_EE_NAMESPACE/$ACR_EE_IMAGE:$TAG" .
- docker push "${ACR_EE_REGISTRY}/${ACR_EE_NAMESPACE}/${ACR_EE_IMAGE}:${TAG}"
- docker logout
kustomize_set_image_dev:
stage: kustomize_tag_push
variables:
NAMESPACE: sharefly-dev
ACR_EE_NAMESPACE: sharefly-dev
only:
- develop
before_script:
- echo "dev set image"
- git config --global user.name "bax" #配置本地仓库用户名信息
- git config --global user.email "baoaxin1999@163.com" #配置本地仓库邮箱信息
script:
- git remote -v
- git checkout -B develop
- cd kustomization/overlays/dev
- kustomize edit set image REGISTRY/NAMESPACE/IMAGE:TAG=$REGISTRY/$NAMESPACE/$IMAGE:$TAG
- cat kustomization.yaml
- git remote set-url origin "$GITLAB_URL"
- git commit -am '[skip ci] DEV image update' #git 本地提交,注意“skip ci”为gitlab流水线文件内置关键字,作用为跳过ci流水线操作,未设置可能导致流水线进入死循环
- git push --set-upstream origin develop #重新提交修改镜像版本后的代码
kustomize_set_image_prod:
stage: kustomize_tag_push
variables:
NAMESPACE: sharefly
ACR_EE_NAMESPACE: sharefly
only:
- master
before_script:
- echo "prod set image"
- echo "master"
- git config --global user.name "bax" #配置本地仓库用户名信息
- git config --global user.email "baoaxin1999@163.com" #配置本地仓库邮箱信息
script:
- git remote -v
- git checkout -B master
- cd kustomization/overlays/prod
- kustomize edit set image REGISTRY/NAMESPACE/IMAGE:TAG=$REGISTRY/$NAMESPACE/$IMAGE:$TAG
- cat kustomization.yaml
- git remote set-url origin "$GITLAB_URL"
- git commit -am '[skip ci] DEV image update' #git 本地提交,注意“skip ci”为gitlab流水线文件内置关键字,作用为跳过ci流水线操作,未设置可能导致流水线进入死循环
- git push --set-upstream origin master #重新提交修改镜像版本后的代码
FROM node:18-alpine as builder
ARG PROFILES_ACTIVE
ENV PROFILES_ACTIVE=$PROFILES_ACTIVE
WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \
if [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i --frozen-lockfile; \
elif [ -f yarn.lock ]; then yarn --frozen-lockfile; \
elif [ -f package-lock.json ]; then npm ci; \
else echo "Lockfile not found." && exit 1; \
fi
COPY . .
RUN \
if [ "${PROFILES_ACTIVE}" = "development" ]; then echo "env PROFILES_ACTIVE=development. exec yarn run build:dev" && yarn run build:dev; \
else echo "env PROFILES_ACTIVE !=development. exec yarn run build" && yarn run build; \
fi
# nginx
FROM nginx:alpine as production
VOLUME ["/var/log/nginx/"]
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
ENV NODE_ENV production
# Set working directory to nginx asset directory
COPY --from=builder /app/dist /usr/share/nginx/html
#COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
# Containers run nginx with global directives and daemon off
ENTRYPOINT ["nginx", "-g", "daemon off;"]
\ No newline at end of file
{
"presets": ["next/babel"],
"plugins": [
[
"styled-components",{ "ssr":true }
]
]
}
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: false,
compilerOptions: {
types: ['@types/styled-components'],
styledComponents: true,
},
styledComponents: {
fileName: false,
ssr: true,
},
redirects() {
return [
{
source: '/home',
destination: '/',
permanent: true,
},
];
},
};
module.exports = nextConfig;
{
"name": "csf-web",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"build:dev": "cross-env NODE_ENV=development next build",
"build:prod": "next build",
"start": "next start",
"lint": "next lint",
"lint:fix": "npm run lint -- --fix",
"prettier": "npx prettier src --check",
"prettier:fix": "npm run prettier -- --write",
"format": "npm run prettier:fix && npm run lint:fix"
},
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
"@ant-design/cssinjs": "^1.17.2",
"@ant-design/icons": "^5.2.6",
"@types/styled-components": "^5.1.29",
"antd": "^5.11.0",
"axios": "^1.6.0",
"babel-plugin-styled-components": "^2.1.4",
"big.js": "^6.2.1",
"dayjs": "^1.11.10",
"js-base64": "^3.7.5",
"js-cookie": "^3.0.5",
"next": "14.0.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-infinite-scroll-component": "^6.1.0",
"styled-components": "^6.1.0"
},
"devDependencies": {
"@types/big.js": "^6.2.0",
"@types/js-cookie": "^3.0.5",
"@types/node": "^20",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"cross-env": "^7.0.3",
"eslint": "^8",
"eslint-config-airbnb-base": "^15.0.0",
"eslint-config-airbnb-typescript": "^17.1.0",
"eslint-config-next": "14.0.1",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.1",
"eslint-plugin-unused-imports": "^3.0.0",
"prettier": "^3.0.3",
"sass": "^1.69.5",
"typescript": "^5"
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
<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" 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 { CommonAPI } from './modules/common';
import { HomeAPI } from './modules/home';
export { CommonAPI, HomeAPI };
// 分页通用接口
export interface PaginationProps {
pageSize: number;
pageNo: number;
}
// 通用返回接口(分页)
export interface ResponseListType<D> {
code: string;
message: string;
result: {
pageNo: number;
pageSize: number;
totalCount: number;
totalPage: number;
list: Array<D>;
};
}
// 通用返回接口(分页了,但又没有分页)
export interface ResponseItemType<D> {
code: string;
message: string;
result: {
pageNo: number;
pageSize: number;
totalCount: number;
totalPage: number;
list: D;
};
}
// 通用返回接口
export interface ResponseType<D> {
code: string;
message: string;
result: D;
}
// 通用接口封装函数(分页) 建议用这个
export interface InterListFunction<D extends object, T> {
(req: D & Partial<PaginationProps>): Promise<ResponseListType<T>>;
}
// 通用接口封装函数(不分页) 建议用这个
export interface InterFunction<D extends object, T> {
(req?: D): Promise<ResponseType<T>>;
}
// 通用接口封装函数(分页了,但又没有分页) 建议用这个
export interface InterItemFunction<D extends object, T> {
(req: D & Partial<PaginationProps>): Promise<ResponseItemType<T>>;
}
// 返回类型封装
// eslint-disable-next-line no-unused-vars
export type InterDataType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: infer V }
? V
: never;
// 返回列表类型封装
// eslint-disable-next-line no-unused-vars
export type InterListType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: { list: infer V } }
? V
: never;
// 返回类型封装(分页了,但又没有分页)
// eslint-disable-next-line no-unused-vars
export type InterItemType<T extends (...args: any) => any> = (
ReturnType<T> extends Promise<infer U> ? U : never
) extends { result: infer V }
? V
: never;
// 获取参数类型封装
// eslint-disable-next-line no-unused-vars
export type InterReqType<T extends (...args: any) => any> = Parameters<T>[0];
// 获取参数类型封装(分页)
// eslint-disable-next-line no-unused-vars
export type InterReqListType<T extends (...args: any) => any> = Omit<
Parameters<T>[0],
'pageSize' | 'pageNo'
>;
import request from '../request';
export class CommonAPI {
// 测试接口
static getPageHomeCategories: any = (params: any) =>
request.get('/pms/product/mall/getPageHomeCategories', { params });
// 测试接口
static cooperationListTag: any = (params: any) =>
request.get('/userapp/cooperation/listTag', { params });
}
import {
AppCategoryInfoType,
AppListPilotType,
AppPublishListType,
GetAppGambitListType,
GetPageHomeCategoriesType,
IndustryListPagesType,
ListBannerImgType,
ListBrandInfoType,
ListCompanyInfoByCoopIdType,
ListNewsType,
ListTenderInfoType,
RecommendGoodsType,
RequirementsListType,
} from '@/api/interface/home';
import request from '@/api/request';
export class HomeAPI {
// 获取图片-小程序
static listBannerImg: ListBannerImgType = (params) =>
request.get('/release/module/listBannerImg', { params });
// 小程序分类信息--含一二级分类
static appCategoryInfo: AppCategoryInfoType = (params) =>
request.get('/pms/category/appCategoryInfo', { params });
// 一级行业列表
static IndustryListPages: IndustryListPagesType = (params) =>
request.post('/pms/industry/listPages', params);
// 小程序——列表————飞手执照及能力认证
static appListPilot: AppListPilotType = (params) =>
request.post('/userapp/pilot/appListPilot', params);
// 话题-列表(小程序)
static getAppGambitList: GetAppGambitListType = (data) =>
request.post('/release/dynamic/appGambitList', data);
// 小程序-列表——需求发布
static appPublishList: AppPublishListType = (params) =>
request.post('/release/requirements/appPublishList', params);
// 需求发布-需求类型
static getRequirementsListType: RequirementsListType = () =>
request.get('/release/requirements/listType');
// 合作商家列表-根据合作标签id获取
static listCompanyInfoByCoopId: ListCompanyInfoByCoopIdType = (params) =>
request.get('/userapp/cooperation/listCompanyInfoByCoopId', { params });
// 商品-推荐商品
static getRecommendGoods: RecommendGoodsType = (params) =>
request.get('/pms/app/goods/recommend', { params });
// 项目资讯-新闻列表
static getListNews: ListNewsType = (params) =>
request.post('/release/industry-news/listNewsPage', params);
// 项目资讯-招投标
static getListTenderInfo: ListTenderInfoType = (params) =>
request.post('/release/tender/listNewTenderInfo', params);
// 租赁-品牌-列表
static getListBrandInfo: ListBrandInfoType = (params) =>
request.get('/pms/brand/listBrandInfo', { params });
// web-首页分类数据-展示
static getPageHomeCategories: GetPageHomeCategoriesType = (params) =>
request.get('/pms/product/mall/getPageHomeCategories', { params });
}
import { message } from 'antd';
import axios, { AxiosResponse } from 'axios';
import { Base64 } from 'js-base64';
import Cookies from 'js-cookie';
// 接口地址
const { NEXT_PUBLIC_BASE_URL } = process.env;
// 创建服务
const service = axios.create({
baseURL: NEXT_PUBLIC_BASE_URL,
timeout: 3600000,
});
service.interceptors.request.use(
(config: any) => {
const token = Cookies.get('SHAREFLY-TOKEN');
// console.log('config --->', NEXT_PUBLIC_BASE_URL);
if (token) {
// eslint-disable-next-line no-param-reassign
config.headers.token = token;
}
return config;
},
(error) => {
return Promise.reject(error);
},
);
service.interceptors.response.use(
(response: AxiosResponse) => {
const { data, status } = response;
// 当接口返回正常时执行
if (status === 200) {
// 如果不报错就直接返回数据
if (['200', '7002'].includes(data.code)) {
return Promise.resolve(data);
}
// 重新登录?
if (
['605', '603', '602', '4004', '607', '2014', '2013', '5008'].includes(
data.code,
)
) {
message.error(data.message).then();
Cookies.remove('SHAREFLY-TOKEN');
localStorage.removeItem('roleId');
setTimeout(() => {
window.location.reload();
}, 1000);
// 阻止后续代码执行
return Promise.reject(data);
}
// 文件/base64导出判断
if (data instanceof Blob || Base64.isValid(data)) {
return Promise.resolve(data);
}
// 如果还有其他报错那么就弹出报错信息(不需要对每个接口的报错做单独判断)
message.error(data.message || '啊呀,出错了').then();
return Promise.reject(data);
}
// 网络错误或链接超时
message.error(data.message).then();
return Promise.reject(data);
},
(error) => {
if (error.response) {
message
.error(`${error.response.status},${error.response.statusText}`, 1)
.then();
}
return Promise.reject(error);
},
);
// 取消token
export const generateCancelToken = () => {
let cancel = null;
const cancelToken = new axios.CancelToken((c) => {
cancel = c;
});
return {
cancel,
cancelToken,
};
};
export default service;
import React from 'react';
import { ContentWrap } from '@/components/layout/content/styled';
const ContentView = ({ children }: { children?: React.ReactNode }) => {
return <ContentWrap>{!!children && children}</ContentWrap>;
};
export default ContentView;
import styled from 'styled-components';
export const ContentWrap = styled.div`
position: relative;
width: 100%;
min-height: 100vh;
box-sizing: border-box;
border-radius: 0;
opacity: 1;
`;
import React from 'react';
import { Button } from 'antd';
import { FooterWrap } from '@/components/layout/footer/styled';
const FooterView = () => {
// 关于列表
const aboutList = [
{
img: '/assets/image/about/xiaochengxu.png',
name: '云享飞小程序',
alt: '云享飞小程序',
},
{
img: '/assets/image/about/fuwuhao.png',
name: '云享飞服务号',
alt: '云享飞服务号',
},
{
img: '/assets/image/about/shequn.png',
name: '官方社群',
alt: '官方社群',
},
];
return (
<FooterWrap>
<div className="footer-wrap">
<div className="footer-start">
<div className="start-item">
<div className="item-title">了解我们</div>
<div className="item-content">
云享飞专注无人机领域12年,无人机一站式服务网站。,云享飞专注无人机领域12年,无人机一站式服务网站云享飞专注无人机领域12年,无人机一站式服务网站人机领域12年,无人机一站式服务网站
</div>
</div>
<div className="start-item">
<div className="item-title">集团公司</div>
<Button type={'link'} className="item-link">
浙江科比特
</Button>
<Button type={'link'} className="item-link">
深圳科比特
</Button>
<Button type={'link'} className="item-link">
更多集团公司
</Button>
</div>
<div className="start-item">
<div className="item-title">合作伙伴</div>
<Button type={'link'} className="item-link">
浙江科比特
</Button>
<Button type={'link'} className="item-link">
深圳科比特
</Button>
<Button type={'link'} className="item-link">
更多合作伙伴
</Button>
</div>
<div className="start-item">
<div className="item-title">商家入驻</div>
<Button type={'link'} className="item-link">
合作咨询
</Button>
<Button type={'link'} className="item-link">
加盟政策
</Button>
</div>
<div className="start-item">
<div className="item-title">关于我们</div>
<div className="item-about">
{aboutList?.map((i, j) => (
<div className="about-item" key={j}>
<img src={i.img} alt={i.alt} className="item-logo" />
<div className="item-name">{i.name}</div>
</div>
))}
</div>
</div>
</div>
<div className="footer-end">
<Button type={'link'} className="end-item">
常见问题
</Button>
<Button type={'link'} className="end-item">
意见反馈
</Button>
<Button type={'link'} className="end-item">
加盟入驻
</Button>
<Button
type={'link'}
className="end-item"
onClick={() => {
window.location.href = 'https://beian.miit.gov.cn';
}}
>
浙ICP备2023014395号
</Button>
</div>
</div>
</FooterWrap>
);
};
export default FooterView;
import styled from 'styled-components';
export const FooterWrap = styled.div`
position: relative;
width: 100%;
background: #2a2a2a;
.footer-wrap {
position: relative;
max-width: 1190px;
height: 19.13rem;
box-sizing: border-box;
margin: 0 auto;
border-radius: 0;
opacity: 1;
//padding: 0 12rem;
display: flex;
align-items: center;
justify-content: flex-end;
flex-direction: column;
}
&::after {
position: absolute;
content: '';
bottom: 5rem;
left: 12rem;
width: calc(100% - 24rem);
height: 0.02rem;
background: #bfbfbf;
}
.footer-end {
position: relative;
width: 100%;
height: 5rem;
display: flex;
align-items: center;
justify-content: center;
.end-item {
font-size: 12px;
font-weight: 400;
color: rgba(255, 255, 255, 0.68);
margin-right: 1rem;
&::after {
position: absolute;
content: '';
top: calc((100% - 0.58rem) / 2);
right: -0.5rem;
width: 0.04rem;
height: 0.58rem;
background: #979797;
}
}
.end-item:last-child {
margin-right: 0;
&::after {
display: none;
}
}
}
.footer-start {
position: relative;
width: 100%;
height: calc(100% - 5rem);
display: flex;
align-items: flex-start;
justify-content: space-between;
box-sizing: border-box;
padding-top: 2.5rem;
.start-item {
position: relative;
min-width: 8.6rem;
min-height: 8.6rem;
.item-title {
font-size: 1rem;
font-weight: 500;
color: #ffffff;
margin-bottom: 1.25rem;
}
.item-content {
width: 11.68rem;
font-size: 12px;
font-weight: 400;
color: rgba(255, 255, 255, 0.8);
}
.item-link {
padding-left: 0;
padding-right: 0;
padding-top: 0;
display: block;
color: rgba(255, 255, 255, 0.8);
&:active,
&:hover {
color: #ff552d;
}
}
.item-about {
position: relative;
display: flex;
align-items: flex-start;
justify-content: flex-start;
.about-item {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
margin-right: 1rem;
.item-logo {
width: 5rem;
height: 5rem;
margin-bottom: 1rem;
}
.item-name {
font-size: 12px;
font-weight: 400;
color: rgba(255, 255, 255, 0.8);
}
&:last-child {
margin-right: 0;
}
}
}
}
}
// 媒体查询
@media screen and (min-width: 1600px) {
padding: 0 20rem;
&::after {
left: 20rem;
width: calc(100% - 40rem);
}
}
`;
import React, { useEffect } from 'react';
import { EnvironmentFilled } from '@ant-design/icons';
import { Button } from 'antd';
import { useRouter } from 'next/router';
import { HeaderWrap } from '@/components/layout/header/styled';
const HeaderView: React.FC<{
placeholder?: boolean;
}> = ({ placeholder }) => {
HeaderView.defaultProps = {
placeholder: true,
};
// 当前的路由数据
const router = useRouter();
// 组件挂载
useEffect(() => {
console.log('HeaderView --->', router);
}, [router]);
return (
<HeaderWrap>
<div className="header-wrap">
<div className="header-location">
<div className="location-icon">
<EnvironmentFilled
style={{ color: '#FF552D', fontSize: '0.86rem' }}
/>
</div>
<Button type={'link'} className="location-address">
杭州
</Button>
<div className="location-hello">Hi,欢迎来云享飞</div>
</div>
<div className="header-nav">
<div className="nav-tab">
<Button type={'link'} className="tab-item">
个人中心
</Button>
<Button type={'link'} className="tab-item">
购物车
</Button>
<Button type={'link'} className="tab-item">
我的订单
</Button>
<Button type={'link'} className="tab-item">
消息
</Button>
<Button type={'link'} className="tab-item">
联系客服
</Button>
</div>
<div className="nav-action">
<Button type={'primary'} className="action-item">
登录
</Button>
<Button type={'primary'} className="action-item">
发布需求
</Button>
<Button type={'primary'} className="action-item">
加盟入住
</Button>
</div>
</div>
</div>
</HeaderWrap>
);
};
export default HeaderView;
import styled from 'styled-components';
export const HeaderWrap = styled.div`
position: fixed;
top: 0;
left: 0;
z-index: 100;
width: 100%;
height: 3rem;
-webkit-backdrop-filter: saturate(68%) blur(16px);
backdrop-filter: saturate(68%) blur(16px);
background: rgba(86, 86, 86, 0.25);
.header-wrap {
position: relative;
max-width: 1190px;
height: 100%;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
margin: 0 auto;
}
//padding: 0 12rem;
.header-location {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
.location-icon {
margin: 0 0 0.2rem 0;
}
.location-address,
.location-hello {
font-size: 12px;
font-weight: 400;
color: #ffffff;
}
.location-hello {
width: 8rem;
}
}
.header-nav {
display: flex;
align-items: center;
justify-content: flex-end;
.nav-action,
.nav-tab {
display: flex;
align-items: center;
justify-content: flex-end;
}
.nav-tab {
.tab-item {
//font-size: 0.67rem;
font-weight: 500;
color: #ffffff;
margin-left: 1rem;
}
.tab-item:active,
.tab-item:hover {
color: #ff552d;
}
}
.nav-action {
margin-left: 1rem;
.action-item {
margin-left: 0.33rem;
}
}
}
// 媒体查询
@media screen and (min-width: 1600px) {
padding: 0 20rem;
}
`;
import React, { useState } from 'react';
import ContentView from '@/components/layout/content';
import FooterView from '@/components/layout/footer';
import HeaderView from '@/components/layout/header';
import { LayoutWrap } from '@/components/layout/styled';
import QrcodeModalView from '@/components/qrcodeModal';
const LayoutView = ({ children }: { children?: React.ReactNode }) => {
// 打开二维码弹窗
const [qrcodeShow, setQrcodeShow] = useState<boolean>(false);
return (
<div className={'animate__animated animate__faster animate__fadeIn'}>
<LayoutWrap>
<div onClick={() => setQrcodeShow(!qrcodeShow)}>
<HeaderView></HeaderView>
<ContentView>{children}</ContentView>
<FooterView></FooterView>
</div>
<QrcodeModalView
open={qrcodeShow}
onCancel={() => setQrcodeShow(false)}
/>
</LayoutWrap>
</div>
);
};
export default LayoutView;
import styled from 'styled-components';
export const LayoutWrap = styled.div`
position: relative;
width: 100%;
min-width: 1200px;
min-height: 100vh;
box-sizing: border-box;
`;
import { FC, useEffect } from 'react';
const MapContainer: FC<{
list: { lat: number; lon: number; name: string }[];
}> = ({ list }) => {
// 地图实例
let map: any = null;
// 高德地图
let AmapRef: any = null;
// const [amapRef, setAmapRef] = useState<any>();
// 添加点数据 entry
const addMarkerEntry = ({
lon,
lat,
name,
}: {
lon: any;
lat: any;
name: string;
}) => {
if (!AmapRef) return;
const icons = new AmapRef.Icon({
size: new AmapRef.Size(60, 60), // 图标尺寸
image: '/assets/image/home/home-map-marker.png', // Icon的图像
imageSize: new AmapRef.Size(60, 60), // 根据所设置的大小拉伸或压缩图片
});
// eslint-disable-next-line consistent-return
return new AmapRef.Marker({
position: new AmapRef.LngLat(lon, lat),
offset: new AmapRef.Pixel(-10, -10),
icon: icons, // 添加 Icon 实例
title: name,
zoom: 13,
});
};
// 设置地图点事件
const handleMarkerSet = () => {
const markers = list.map((i) => addMarkerEntry(i));
map?.add(markers);
// 自适应显示多个点位
map?.setFitView();
};
// 组件挂载
useEffect(() => {
if (typeof window !== 'undefined') {
import('@amap/amap-jsapi-loader').then((AMapLoader) => {
AMapLoader.load({
key: '87b424e68754efc3ba9d11ae07475091', // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: [], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
}).then((AMap) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
AmapRef = AMap;
// setAmapRef(AMap);
// eslint-disable-next-line react-hooks/exhaustive-deps
map = new AMap.Map('container', {
// 设置地图容器id
viewMode: '3D', // 是否为3D地图模式
zoom: 10, // 初始化地图级别
center: [119.96043, 30.04885], // 初始化地图中心点位置
});
// 用户定位
map.plugin('AMap.Geolocation', () => {
const geolocation = new AMap.Geolocation({
enableHighAccuracy: true, // 是否使用高精度定位,默认:true
timeout: 10000, // 超过10秒后停止定位,默认:5s
position: 'RB', // 定位按钮的停靠位置
offset: [10, 55], // 定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, // 定位成功后是否自动调整地图视野到定位点
});
map.addControl(geolocation);
// geolocation.getCurrentPosition((status: string, result: any) => {
// console.log(result);
// if (status == 'complete') {
// onComplete(result);
// } else {
// onError(result);
// }
// });
});
// 如果列表没有数据则停止执行
if (!list.length) return;
// 设置地图点
handleMarkerSet();
});
});
}
return () => {
map?.destroy();
};
}, [list]);
return (
<div
id="container"
className={'container animate__animated animate__fast animate__fadeIn'}
style={{
height: '100%',
padding: 0,
margin: 0,
width: '100%',
zIndex: 1,
}}
></div>
);
};
export default MapContainer;
import React from 'react';
import { Modal } from 'antd';
import styled from 'styled-components';
export const QrcodeModalWrap = styled.div`
position: relative;
width: 100%;
min-height: 16.8rem;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
box-sizing: border-box;
padding-top: 1rem;
.qrcode {
width: 12.68rem;
height: 15.68rem;
background-image: url('https://share-fly.oss-cn-hangzhou.aliyuncs.com/file/sharefly-qrcode-wx.jpg');
//background-size: 100% 100%;
background-size: cover;
background-position: center;
}
.title {
color: #000;
font-size: 13px;
margin-top: 1rem;
font-weight: bold;
}
`;
const QrcodeModalView = ({
open,
onCancel,
}: {
open: boolean;
onCancel: () => void;
}) => {
return (
<Modal title="提示" open={open} footer={null} onCancel={onCancel}>
<QrcodeModalWrap>
<div className="qrcode"></div>
<div className="title">功能正在完善中</div>
<div className="title">请前往小程序以获得更好体验</div>
</QrcodeModalWrap>
</Modal>
);
};
export default QrcodeModalView;
import React from 'react';
import { ConfigProvider, theme } from 'antd';
// eslint-disable-next-line import/order
import type { AppProps } from 'next/app';
import '../styles/animate.css';
import '../styles/globals.css';
import themeConfig from '../theme/themeConfig';
const App = ({ Component, pageProps }: AppProps) => (
<ConfigProvider
theme={{
algorithm: theme.compactAlgorithm,
...themeConfig,
}}
>
<Component {...pageProps} />
</ConfigProvider>
);
export default App;
import React from 'react';
import { createCache, extractStyle, StyleProvider } from '@ant-design/cssinjs';
import Document, { Head, Html, Main, NextScript } from 'next/document';
import type { DocumentContext } from 'next/document';
import { ServerStyleSheet } from 'styled-components';
const MyDocument = () => (
<Html lang="zh-Hans">
<Head>
<meta charSet="UTF-8" />
<link
rel="icon"
type="image/svg+xml"
href="/assets/image/logo/logo.jpg"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
{/* eslint-disable-next-line */}
<title>【云享飞 iuav.com】无人机分类信息 - 让世界为天空所用</title>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
);
MyDocument.getInitialProps = async (ctx: DocumentContext) => {
const cache = createCache();
const originalRenderPage = ctx.renderPage;
const sheet = new ServerStyleSheet();
try {
ctx.renderPage = () =>
originalRenderPage({
enhanceApp: (App) => (props) => (
<StyleProvider cache={cache}>
<App {...props} />
</StyleProvider>
),
});
const initialProps = await Document.getInitialProps(ctx);
const style = extractStyle(cache, true);
return {
...initialProps,
styles: (
<>
{initialProps.styles}
{sheet.getStyleElement()}
<style dangerouslySetInnerHTML={{ __html: style }} />
</>
),
};
} finally {
sheet.seal();
}
};
export default MyDocument;
import React from 'react';
import {
CarryOutOutlined,
ShopOutlined,
TeamOutlined,
} from '@ant-design/icons';
import styled from 'styled-components';
const HomeBottomView = () => {
// 标签列表
const bottomList = [
{
title: '无人机垂直领域综合服务平台',
icon: <CarryOutOutlined style={{ fontSize: 32, color: '#333' }} />,
},
{
title: '10W+无人机爱好者的学习交流平台',
icon: <TeamOutlined style={{ fontSize: 32, color: '#333' }} />,
},
{
title: '汇聚众多无人机行业优质商家',
icon: <ShopOutlined style={{ fontSize: 32, color: '#333' }} />,
},
];
return (
<HomeBottomWrap>
{bottomList?.map((i, j) => (
<div className="bottom-item" key={j}>
{i?.icon}
<div className="item-text">{i?.title}</div>
</div>
))}
</HomeBottomWrap>
);
};
export const HomeBottomWrap = styled.div`
position: relative;
width: 100%;
height: 12.25rem;
display: flex;
justify-content: space-between;
align-items: center;
.bottom-item {
position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
.item-text {
font-size: 13px;
font-weight: 500;
color: #666666;
margin-top: 0.67rem;
}
}
`;
export default HomeBottomView;
import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterListType } from '@/api/interface';
import { ListCompanyInfoByCoopIdType } from '@/api/interface/home';
// 列表类型
type ListType = InterListType<ListCompanyInfoByCoopIdType>;
const HomeBrandView = () => {
// 店铺列表
const [companyList, setCompanyList] = useState<ListType>([]);
// 获取店铺列表
const getListCompanyInfo = async () => {
const res = await HomeAPI.listCompanyInfoByCoopId({
lat: 30.04885,
lon: 119.96043,
pageNo: 1,
pageSize: 999,
coopId: 1,
});
if (res && res.code === '200') {
const list = res.result?.list || [];
const kbt = list.filter((i) => i.companyName.includes('科比特'));
const other = list.filter((i) => !i.companyName.includes('科比特'));
setCompanyList([...kbt, ...other]?.slice(0, 10));
// console.log('获取网点数据 --->', companyList.value)
}
};
// 组件挂载
useEffect(() => {
getListCompanyInfo().then();
}, []);
return (
<HomeBrandWrap>
<div className="brand-item">
<div className="item-icon">
<img
src="/assets/image/home/home-brand-all.png"
alt="全部品牌"
className="image"
/>
</div>
</div>
{companyList?.map((i, j) => (
<div key={j} className="brand-item">
<div className="item-logo">
<img src={i.brandLogo} alt={i.brandName} className="image" />
</div>
<Button type={'link'} className="item-name text-ellipsis">
{i.brandName || i.companyName}
</Button>
</div>
))}
</HomeBrandWrap>
);
};
// 样式
const HomeBrandWrap = styled.div`
width: 100%;
//min-height: 8.71rem;
box-sizing: border-box;
//background: aquamarine;
padding: 1.33rem 0 0.83rem 0;
display: flex;
align-items: center;
justify-content: flex-start;
overflow-x: scroll;
.brand-item {
position: relative;
width: 4rem;
min-height: 6.3rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: flex-start;
flex-direction: column;
margin-right: 0.83rem;
.item-icon,
.item-logo {
position: relative;
width: 4rem;
height: 4rem;
border-radius: 50%;
background: rgba(27, 27, 27, 0.13);
.image {
width: 100%;
height: 100%;
}
}
.item-logo {
box-sizing: border-box;
padding: 0.68rem;
border: 0.04rem solid #e3e3e3;
background: #fff;
&:active,
&:hover {
filter: brightness(0.96);
}
}
.item-name {
width: 100%;
font-size: 12px;
font-weight: 400;
color: #000000;
text-align: center;
margin-top: 0.58rem;
padding: 0;
}
}
&::-webkit-scrollbar-thumb {
background: #d9d9d9;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
cursor: pointer;
}
&::-webkit-scrollbar {
background-color: transparent;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
width: 7px;
height: 7px;
}
`;
export default HomeBrandView;
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import MapContainer from '@/components/map';
const HomeMapView = () => {
// 选择索引
const [currentIndex, setCurrentIndex] = useState<number>(0);
// 网点类型
const networkTypeList = [
{ type: 0, name: '飞手团队', action: '派单', tagId: 5 },
{ type: 1, name: '租赁商家', action: '租设备', tagId: 3 },
{ type: 2, name: '培训机构', action: '报名培训', tagId: 4 },
{ type: 3, name: '维修网点', action: '维修设备', tagId: 10 },
];
// 选择事件
const handleSelect = (index: number) => {
setCurrentIndex(index);
getServiceBitmap().then();
};
// 地图网点列表
const [mapMarkerList, setMapMarkerList] = useState<
{ lat: number; lon: number; name: string }[]
>([]);
// 统一获取网点数据
const getServiceBitmap = async () => {
const res = await HomeAPI.listCompanyInfoByCoopId({
lon: 113.93029,
lat: 22.53291,
pageNo: 1,
pageSize: 9999,
coopId: networkTypeList[currentIndex].tagId,
});
if (res && res.code === '200') {
const list = (res.result.list || [])?.map((i) => ({
...i,
name: i.brandName || i.companyName,
}));
setMapMarkerList(list);
// console.log('统一获取网点数据 --->', res);
}
};
// 组件挂载
useEffect(() => {
getServiceBitmap().then();
}, []);
return (
<HomeMapWrap>
<MapContainer list={mapMarkerList} />
<div className="map-wrap flex-around">
{networkTypeList?.map((i, j) => (
<div
className={`map-item ${j === currentIndex && 'item-active'}`}
key={j}
onClick={() => handleSelect(j)}
>
{i?.name}
</div>
))}
</div>
</HomeMapWrap>
);
};
export const HomeMapWrap = styled.div`
position: relative;
height: calc((100% - 1rem) / 2);
width: 25rem;
//background: lightblue;
border: 0.04rem solid #e3e3e3;
margin-bottom: 1rem;
.map-wrap {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 2.85rem;
background: #ffffff;
z-index: 2;
.map-item {
position: relative;
width: 25%;
text-align: center;
font-size: 13px;
font-weight: 500;
color: #333333;
cursor: pointer;
&::after {
position: absolute;
content: '';
top: 0.2rem;
right: 0;
width: 0.04rem;
height: 0.83rem;
background: #e2e2e2;
}
&:last-child::after {
display: none;
}
&:hover,
&:active {
color: #ff552d;
}
}
.item-active {
color: #ff552d;
//&:hover,
//&:active {
// color: #333333;
//}
}
}
`;
export default HomeMapView;
import React, { useEffect, useState } from 'react';
import { RightOutlined } from '@ant-design/icons';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
const HomeNewsView = () => {
// 帖子类型
const indexList = [
{ label: 1, value: '#FF392B' },
{ label: 2, value: '#FE792B' },
{ label: 3, value: '#FEA32B' },
];
// 热门类型
const typeList = [
{ label: 1, value: '#FFB555' },
{ label: 2, value: '#FF6155' },
{ label: 3, value: '#B700D9' },
];
// tab栏数据
const [tabList, setTabList] = useState<{ label: string; value: any[] }[]>([
// {
// label: '热门话题',
// value: [],
// },
{
label: '热点资讯',
value: [],
},
// {
// label: '行业新闻',
// value: [],
// },
{
label: '招标快讯',
value: [],
},
]);
// 刷新子组件
const [refresh, setRefresh] = useState(true);
// tab栏索引
const [currentIndex, setCurrentIndex] = useState<number>(0);
// 获取话题列表
const getListGambit = async () => {
const res = await HomeAPI.getAppGambitList({
pageNo: 1,
pageSize: 10,
});
if (res && res.code === '200') {
tabList[0].value = res.result.list || [];
setTabList(tabList);
setRefresh(true);
// console.log('话题列表 --->', tabList);
}
};
// 热点资讯列表
const getListNews = async () => {
const res = await HomeAPI.getListNews({
pageNo: 1,
pageSize: 10,
});
if (res && res.code === '200') {
tabList[0].value = res.result.list || [];
setTabList(tabList);
setRefresh(true);
// console.log('热点资讯列表 --->', tabList);
}
};
// 获取招标快讯列表
const getListTenderInfo = async () => {
const res = await HomeAPI.getListTenderInfo({
pageNo: 1,
pageSize: 10,
});
if (res && res.code === '200') {
tabList[1].value = res.result.list || [];
setTabList(tabList);
setRefresh(true);
// console.log('招投标列表 --->', tabList);
}
};
// 选择tab栏
const handleSelect = async (index: number) => {
setRefresh(false);
setCurrentIndex(index);
if (index === 0) {
await getListNews();
return;
}
if (index === 1) {
await getListTenderInfo();
}
};
// 获取标签颜色
const getTagBgColor = (item: any[0]) => {
return typeList.find((i) => i.label === item.gambitProperty)?.value;
};
// 组件挂载
useEffect(() => {
handleSelect(0).then();
// console.log('执行到此处 --->', tabList);
}, []);
return (
<HomeNewWrap>
<div className="news-head flex-between">
<div className="head-tab flex-start">
{tabList?.map((i, j) => (
<div
className={`tab-item ${currentIndex === j && 'tab-active'}`}
key={j}
onClick={() => handleSelect(j)}
>
{i?.label}
</div>
))}
</div>
<div className="head-more flex-between">
<div className="more-text">更多</div>
<RightOutlined style={{ fontSize: 10, color: '#33333380' }} />
</div>
<img
className="head-bg"
src="https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/sharefly-web-news.png"
alt="更多"
/>
</div>
<div className="news-list">
{refresh &&
tabList?.[currentIndex]?.value?.map((i, j) => (
<div
className="list-item animate__animated animate__fast animate__fadeIn flex-start"
key={j}
>
<div
className="item-index"
style={{ color: indexList[j]?.value }}
>
{j + 1}
</div>
<div className="item-title text-ellipsis">
{i?.gambitName || i?.newsTitle || i?.tenderTitle}
</div>
{/* {currentIndex === 0 && ( */}
{/* <div */}
{/* className="item-tag" */}
{/* style={{ backgroundColor: getTagBgColor(i) }} */}
{/* > */}
{/* {i?.gambitProperty === 1 && '新'} */}
{/* {i?.gambitProperty === 2 && '热'} */}
{/* {i?.gambitProperty === 3 && '荐'} */}
{/* </div> */}
{/* )} */}
</div>
))}
</div>
</HomeNewWrap>
);
};
// 样式
const HomeNewWrap = styled.div`
height: calc((100% - 1rem) / 2);
width: 25rem;
//background: lightblue;
border: 0.04rem solid #e3e3e3;
background: linear-gradient(180deg, #ffe3d8 0%, #ffffff 21%);
.news-head {
position: relative;
width: 100%;
padding: 0 1.29rem;
.head-tab {
position: relative;
width: calc(100% - 5rem);
box-sizing: border-box;
padding: 0.83rem 0;
z-index: 2;
.tab-item {
width: 25%;
font-size: 13px;
font-weight: 500;
color: rgba(51, 51, 51, 0.6);
cursor: pointer;
}
.tab-active {
position: relative;
font-size: 14px;
color: #333333;
font-weight: 550;
z-index: 1;
&::after {
content: '';
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 2.54rem;
height: 0.29rem;
border-radius: 1rem;
background: #ff6d00;
z-index: -1;
}
}
}
.head-more {
align-items: center;
z-index: 2;
cursor: pointer;
.more-text {
font-size: 13px;
font-weight: 400;
color: rgba(51, 51, 51, 0.5);
}
}
.head-bg {
position: absolute;
top: 0;
right: 2.68rem;
width: 5.25rem;
height: 2.02rem;
z-index: 0;
}
}
.news-list {
position: relative;
width: 100%;
height: 12rem;
overflow: hidden;
overflow-y: auto;
box-sizing: border-box;
padding: 0 1.2rem;
&::-webkit-scrollbar-thumb {
background: #d9d9d9;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
cursor: pointer;
}
&::-webkit-scrollbar {
background-color: transparent;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
width: 7px;
height: 7px;
}
.list-item {
position: relative;
width: 100%;
margin-bottom: 0.5rem;
.item-index {
width: 1.5rem;
font-size: 14px;
font-weight: 550;
color: #c3c3c3;
}
.item-title {
max-width: 80%;
font-size: 14px;
font-weight: 500;
color: #333333;
&:hover,
&:active {
cursor: pointer;
color: #ff6d00;
}
}
.item-tag {
width: 1rem;
height: 1rem;
background: #ff6256;
border-radius: 0.17rem 0.17rem 0.17rem 0.17rem;
text-align: center;
line-height: 1rem;
font-size: 12px;
font-weight: 500;
color: #fff;
margin-left: 0.33rem;
}
}
}
`;
export default HomeNewsView;
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { RecommendGoodsType } from '@/api/interface/home';
// 列表类型
type ListType = InterDataType<RecommendGoodsType>;
const HomeProductView = () => {
// 推荐商品列表
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 getLowerPrice = (item: ListType[0]['mallGoodsList'][0]) => {
return (
item.priceStock?.reduce((a: any, b: any) =>
a.salePrice < b.salePrice ? a : b,
).salePrice || 0
);
};
// 组件挂载
useEffect(() => {
getRecommendGoodsList().then();
}, []);
return (
<HomeProductWrap>
{recommendGoodsList?.map((i, j) => (
<div className="product-item flex-start" key={j}>
<img
className="item-image"
src={`${i.resourcesList[0].url}?x-oss-process=image/quality,q_25`}
alt={i.tradeName}
/>
<div className="item-title text-ellipsis">{i.tradeName}</div>
<div className="item-price">
<span className="label"></span>
<span className="num">
{i.priceShow ? getLowerPrice(i).toLocaleString() : '咨询报价'}
</span>
</div>
</div>
))}
</HomeProductWrap>
);
};
export const HomeProductWrap = styled.div`
width: 100%;
//min-height: 8.71rem;
box-sizing: border-box;
//background: aquamarine;
padding: 0.83rem 0 0.15rem 0;
display: flex;
justify-content: flex-start;
align-items: center;
flex-wrap: wrap;
.product-item {
position: relative;
width: calc((100% - 0.83rem * 5) / 6);
height: 14.46rem;
margin-right: 0.83rem;
margin-bottom: 0.83rem;
border: 0.04rem solid #e3e3e3;
flex-direction: column;
box-sizing: border-box;
padding: 0.67rem 0 0 0;
background: #fff;
&:hover,
&:active {
filter: brightness(0.95);
}
&:nth-child(6n) {
margin-right: 0;
}
.item-image {
width: 9rem;
height: 9rem;
object-fit: cover;
margin-bottom: 0.5rem;
}
.item-title {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0 1.2rem;
text-align: left;
font-size: 13px;
font-weight: bold;
margin-bottom: 0.54rem;
}
.item-price {
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0 1rem;
text-align: left;
font-size: 16px;
font-weight: bold;
color: #ff1b1b;
}
}
`;
export default HomeProductView;
import React from 'react';
import { Input } from 'antd';
import { HomeSearchWrap } from '@/pages/home/comp/home-search/styled';
const HomeSearchView = () => {
return (
<HomeSearchWrap>
<div className="head-wrap">
<div className="head-logo">
<img
className="image"
src="/assets/image/home/sharefly-web-headbg.png"
alt="云享飞官网"
/>
</div>
<div className="head-search">
<Input.Search
className="search-box"
placeholder="科比特航空"
enterButton="搜索"
size={'large'}
bordered={true}
/>
</div>
</div>
</HomeSearchWrap>
);
};
export default HomeSearchView;
import styled from 'styled-components';
export const HomeSearchWrap = styled.div`
position: relative;
width: 100%;
background-image: url('https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/sharefly-web-headbg.png');
//background-size: 100% 100%;
background-size: cover;
background-position: center;
.head-wrap {
position: relative;
max-width: 1190px;
height: 16.42rem;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: flex-end;
flex-direction: column;
margin: 0 auto;
}
//padding: 0 12rem;
.head-bg {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.head-logo {
position: relative;
//width: 11.33rem;
//height: 3.04rem;
width: 12.42rem;
height: 3.08rem;
//background-image: url('https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/sharefly-web-headlogo.png');
background-image: url('/assets/image/home/sharefly-web-headbg.png');
background-size: 100% 100%;
margin-bottom: 1.88rem;
.image {
display: none;
width: 100%;
height: 100%;
object-fit: cover;
}
}
.head-search {
width: 34rem;
height: 2.04rem;
//background: rgba(255, 255, 255, 0.68);
//-webkit-backdrop-filter: saturate(100%) blur(8px);
//backdrop-filter: saturate(100%) blur(8px);
//border-radius: 0.25rem;
//opacity: 1;
//border: 0.08rem solid #ff522f;
box-sizing: border-box;
margin-bottom: 2.83rem;
.search-box {
//border: 0.08rem solid #ff522f;
box-sizing: border-box;
}
}
// 媒体查询
@media screen and (min-width: 1600px) {
padding: 0 20rem;
}
`;
import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { AppCategoryInfoType } from '@/api/interface/home';
// 列表类型
type ListType = InterDataType<AppCategoryInfoType>;
const TabView01 = () => {
// 列表数据
const [tabList, setTabList] = useState<ListType>([]);
// 获取云享商城分类
const getAppCategoryInfo = async () => {
const res = await HomeAPI.appCategoryInfo({
type: 4,
});
if (res && res.code === '200') {
setTabList(res.result?.filter((i) => i.subDTOList?.length));
// console.log('获取云享商城分类 --->', tabList);
}
};
// 组件挂载
useEffect(() => {
getAppCategoryInfo().then();
}, []);
return (
<TabViewWrap className="animate__animated animate__fast animate__fadeIn">
{tabList.map((i, j) => (
<div key={j}>
<div className={'tab-little flex-start'}>
{!!i.icon && (
<img src={i.icon} alt={i.name} className="title-image" />
)}
<div className="title-name">{i.name}</div>
</div>
<div className="tab-list flex-start">
{i.subDTOList?.map((n, m) => (
<Button type={'link'} key={m} className="list-item">
{n.name}
</Button>
))}
</div>
</div>
))}
</TabViewWrap>
);
};
// 样式
const TabViewWrap = styled.div`
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0.79rem 1.58rem;
//background: lightyellow;
.tab-little {
position: relative;
width: 100%;
box-sizing: border-box;
padding-bottom: 0.68rem;
border-bottom: 0.02rem solid #ededed;
margin-bottom: 0.5rem;
.title-image {
width: 1.68rem;
height: 1.68rem;
margin-right: 0.5rem;
}
.title-name {
font-size: 0.75rem;
font-weight: 550;
color: #333333;
}
}
.tab-list {
position: relative;
width: 100%;
flex-wrap: wrap;
margin-bottom: 1rem;
transform: translateX(-10px);
.list-item {
color: #666666;
font-weight: 500;
}
}
`;
export default TabView01;
import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterListType } from '@/api/interface';
import { IndustryListPagesType } from '@/api/interface/home';
// 列表类型
type ListType = InterListType<IndustryListPagesType>;
const TabView02 = () => {
// 列表数据
const [tabList, setTabList] = useState<ListType>([]);
// 获取分类列表
const getIndustryListPages = async () => {
const res = await HomeAPI.IndustryListPages({
pageNo: 1,
pageSize: 9999,
});
if (res && res.code === '200') {
setTabList(res.result?.list?.filter((i) => i.inspectionDTOS?.length));
console.log('获取分类列表 --->', res.result);
}
};
// 组件挂载
useEffect(() => {
getIndustryListPages().then();
}, []);
return (
<TabViewWrap className="animate__animated animate__fast animate__fadeIn">
{tabList.map((i, j) => (
<div key={j}>
<div className={'tab-little flex-start'}>
{!!i.typeImg && (
<img src={i.typeImg} alt={i.typeName} className="title-image" />
)}
<div className="title-name">{i.typeName}</div>
</div>
<div className="tab-list flex-start">
{i.inspectionDTOS?.map((n, m) => (
<Button type={'link'} key={m} className="list-item">
{n.inspectionName}
</Button>
))}
</div>
</div>
))}
</TabViewWrap>
);
};
// 样式
const TabViewWrap = styled.div`
position: relative;
width: 100%;
box-sizing: border-box;
padding: 0.79rem 1.58rem;
//background: lightyellow;
.tab-little {
position: relative;
width: 100%;
box-sizing: border-box;
padding-bottom: 0.68rem;
border-bottom: 0.02rem solid #ededed;
margin-bottom: 0.5rem;
.title-image {
width: 1.68rem;
height: 1.68rem;
margin-right: 0.5rem;
}
.title-name {
font-size: 0.75rem;
font-weight: 550;
color: #333333;
}
}
.tab-list {
position: relative;
width: 100%;
flex-wrap: wrap;
margin-bottom: 1rem;
transform: translateX(-10px);
.list-item {
color: #666666;
font-weight: 500;
}
}
`;
export default TabView02;
import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterListType } from '@/api/interface';
import { ListBrandInfoType } from '@/api/interface/home';
// 列表类型
type ListType = InterListType<ListBrandInfoType>;
const TabView03 = () => {
// 列表数据
const [tabList, setTabList] = useState<ListType>([]);
// 获取云享商城分类
const getListBrandInfo = async () => {
const res = await HomeAPI.getListBrandInfo({
pageNo: 1,
pageSize: 999,
});
if (res && res.code === '200') {
setTabList(res.result?.list?.filter((i) => i.modeInfoList?.length));
// console.log('获取云享商城分类 --->', res);
}
};
// 组件挂载
useEffect(() => {
getListBrandInfo().then();
}, []);
return (
<TabViewWrap className="animate__animated animate__fast animate__fadeIn">
{tabList.map((i, j) => (
<div key={j}>
<div className={'tab-little flex-start'}>
<div className="title-name">{i.brandName}</div>
</div>
<div className="tab-list flex-start">
{i.modeInfoList?.map((n, m) => (
<Button type={'link'} key={m} className="list-item">
{n.modeName}
</Button>
))}
</div>
</div>
))}
</TabViewWrap>
);
};
// 样式
const TabViewWrap = styled.div`
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0.79rem 1.58rem;
//background: lightyellow;
.tab-little {
position: relative;
width: 100%;
box-sizing: border-box;
padding-bottom: 0.68rem;
border-bottom: 0.02rem solid #ededed;
margin-bottom: 0.5rem;
.title-image {
width: 1.68rem;
height: 1.68rem;
margin-right: 0.5rem;
}
.title-name {
font-size: 0.75rem;
font-weight: 550;
color: #333333;
}
}
.tab-list {
position: relative;
width: 100%;
flex-wrap: wrap;
margin-bottom: 1rem;
transform: translateX(-10px);
.list-item {
color: #666666;
font-weight: 500;
}
}
`;
export default TabView03;
import React, { useEffect, useState } from 'react';
import { Button } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { GetPageHomeCategoriesType } from '@/api/interface/home';
// 列表类型
type ListType = InterDataType<GetPageHomeCategoriesType>;
const TabView04 = () => {
// 列表数据
const [tabList, setTabList] = useState<
Array<ListType[0] & { categoryList: ListType }>
>([]);
// 获取云享商城分类
const getListBrandInfo = async () => {
const res = await HomeAPI.getPageHomeCategories({
type: 3,
});
if (res && res.code === '200') {
setTabList([
{ id: 1, categoryName: '执照培训', categoryList: res.result },
]);
// console.log('获取云享商城分类 --->', res);
}
};
// 组件挂载
useEffect(() => {
getListBrandInfo().then();
}, []);
return (
<TabViewWrap className="animate__animated animate__fast animate__fadeIn">
{tabList.map((i, j) => (
<div key={j}>
<div className={'tab-little flex-start'}>
<div className="title-name">{i?.categoryName}</div>
</div>
<div className="tab-list flex-start">
{i?.categoryList?.map((n, m) => (
<Button type={'link'} key={m} className="list-item">
{n?.categoryName}
</Button>
))}
</div>
</div>
))}
</TabViewWrap>
);
};
// 样式
const TabViewWrap = styled.div`
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
padding: 0.79rem 1.58rem;
//background: lightyellow;
.tab-little {
position: relative;
width: 100%;
box-sizing: border-box;
padding-bottom: 0.68rem;
border-bottom: 0.02rem solid #ededed;
margin-bottom: 0.5rem;
.title-image {
width: 1.68rem;
height: 1.68rem;
margin-right: 0.5rem;
}
.title-name {
font-size: 0.75rem;
font-weight: 550;
color: #333333;
}
}
.tab-list {
position: relative;
width: 100%;
flex-wrap: wrap;
margin-bottom: 1rem;
transform: translateX(-10px);
.list-item {
color: #666666;
font-weight: 500;
}
}
`;
export default TabView04;
import React, { useEffect, useState } from 'react';
import { RightOutlined } from '@ant-design/icons';
import { Pagination, Rate } from 'antd';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterListType, InterReqType } from '@/api/interface';
import { AppListPilotType } from '@/api/interface/home';
// 列表类型
type ListType = InterListType<AppListPilotType>;
// 参数类型
type ReqType = InterReqType<AppListPilotType>;
const TabView05 = () => {
// 飞手列表
const [flyerList, setFlyerList] = useState<ListType>([]);
// 分页数据
const [pagination, setPagination] = useState({
pageNo: 1,
pageSize: 8,
totalPage: 0,
totalCount: 0,
});
// 获取飞手列表
const getFlyerList = async (data?: ReqType) => {
const res = await HomeAPI.appListPilot({
// 审批通过
auditStatus: 1,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize,
...data,
});
if (res && res.code === '200') {
const { list, pageNo, totalPage, totalCount } = res.result;
setFlyerList(list);
setPagination({
...pagination,
pageNo,
totalPage,
totalCount,
});
// console.log('列表数据 --->', list, pageNo, totalPage);
}
};
// 组件挂载
useEffect(() => {
getFlyerList().then();
}, []);
return (
<TabViewWrap className={'animate__animated animate__fast animate__fadeIn'}>
<div className="tab-title flex-between">
<div className="title-name">飞手约单</div>
</div>
<div className="tab-list flex-start">
{flyerList?.map((i, j) => (
<div className="list-item" key={j}>
<div className="item-arrow">
<RightOutlined style={{ fontSize: 10, color: '#A0A0A0' }} />
</div>
<div className="item-head flex-start">
<img className="head-image" src={i?.userImg} alt={i?.userName} />
<div className="head-content">
<div className="content-title flex-start">
<div className="title-name">{i?.userName}</div>
<Rate
allowHalf
disabled
defaultValue={4}
style={{ fontSize: '12px', color: '#FE562F' }}
/>
</div>
<div className="content-text flex-start">
<div className="text-item">{i?.residentCity}</div>
<div className="text-item">{i?.age}</div>
<div className="text-item">{i?.yearsOfWorking}年经验</div>
</div>
<div className="content-tag flex-start">
{i?.pilotAbility?.map((n, m) => (
<div className="tag-item" key={m}>
{n.abilityName}
</div>
))}
</div>
</div>
</div>
<div className="item-foot flex-start">
<div className="foot-state">空闲</div>
<div className="foot-text text-ellipsis">
{i?.individualResume}
</div>
</div>
</div>
))}
</div>
<div className="tab-foot flex-end">
<Pagination
size="small"
current={pagination.pageNo}
pageSize={pagination.pageSize}
total={pagination.totalCount}
onChange={async (e) => {
await getFlyerList({ pageNo: e });
}}
/>
</div>
</TabViewWrap>
);
};
// 样式
const TabViewWrap = styled.div`
position: relative;
width: 100%;
box-sizing: border-box;
padding: 1rem 1.58rem;
.tab-title {
width: 100%;
box-sizing: border-box;
border-bottom: 0.02rem solid #ededed;
padding-bottom: 0.58rem;
margin-bottom: 0.42rem;
.title-name {
font-size: 1rem;
font-weight: 550;
color: #333333;
}
}
.tab-list {
position: relative;
width: 100%;
flex-wrap: wrap;
.list-item {
position: relative;
box-sizing: border-box;
width: 14.13rem;
min-height: 5.54rem;
background: #ffffff;
border-radius: 0.25rem;
border: 0.04rem solid #e3e3e3;
margin: 0 0.85rem 0.85rem 0;
padding: 0.83rem 0 0 0.83rem;
&:active,
&:hover {
filter: brightness(0.95);
}
.item-arrow {
position: absolute;
top: 0.67rem;
right: 0.67rem;
}
.item-head {
.head-image {
width: 3rem;
height: 3rem;
border-radius: 4px;
margin-right: 0.38rem;
}
.head-content {
position: relative;
.content-title {
align-items: baseline;
margin-bottom: 0.2rem;
.title-name {
font-size: 14px;
font-weight: 550;
color: #333333;
margin-right: 0.2rem;
}
}
.content-text {
margin-bottom: 0.2rem;
.text-item {
font-size: 12px;
font-weight: 400;
margin-right: 0.5rem;
&:last-child {
margin-right: 0;
}
}
}
.content-tag {
flex-wrap: wrap;
margin-bottom: 0.33rem;
.tag-item {
min-width: 2.42rem;
height: 0.79rem;
border-radius: 0.17rem;
border: 0.04rem solid #fe562f;
text-align: center;
line-height: 0.79rem;
font-size: 0.5rem;
font-weight: 400;
color: #fe562f;
margin-right: 0.33rem;
}
}
&::after {
position: absolute;
content: '';
bottom: 0;
left: 0;
width: 8.21rem;
height: 0.02rem;
background: #dedede;
}
}
}
.item-foot {
min-height: 1.42rem;
box-sizing: border-box;
padding: 0.33rem 0;
.foot-state {
position: relative;
width: 3rem;
text-align: center;
margin-right: 0.33rem;
font-size: 12px;
color: #44d979;
&::after {
position: absolute;
content: '';
top: calc((100% - 0.25rem) / 2);
left: 0;
width: 0.25rem;
height: 0.25rem;
background: #44d979;
border-radius: 50%;
}
}
.foot-text {
width: calc(100% - 3.33rem);
font-size: 12px;
font-weight: 400;
color: #999999;
}
}
}
}
.tab-foot {
position: relative;
width: 100%;
}
`;
export default TabView05;
import React, { useEffect, useState } from 'react';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { ListBannerImgType } from '@/api/interface/home';
import TabView01 from '@/pages/home/comp/home-tab/comp/tabView01';
import TabView02 from '@/pages/home/comp/home-tab/comp/tabView02';
import TabView03 from '@/pages/home/comp/home-tab/comp/tabView03';
import TabView04 from '@/pages/home/comp/home-tab/comp/tabView04';
import TabView05 from '@/pages/home/comp/home-tab/comp/tabView05';
import { HomeTabWrap } from '@/pages/home/comp/home-tab/styled';
// 分类列表类型
type CategoryListType = InterDataType<ListBannerImgType>;
const HomeTabView = () => {
// 当前选中的项目
const [currentIndex, setCurrentIndex] = useState<number>(0);
// 一级分类列表
const [categoryList, setCategoryList] = useState<CategoryListType>([]);
// 获取一级分类列表
const getCategoryList = async () => {
const res = await HomeAPI.listBannerImg({
moduleCode: 'HOME_MENU_NEW',
});
if (res && res.code === '200') {
setCategoryList(res.result || []);
}
};
// 选择分类
const handleSelect = (index: number) => {
setCurrentIndex(index);
};
// 组件挂载
useEffect(() => {
// 获取分类数据
getCategoryList().then();
}, []);
// 渲染视图
return (
<HomeTabWrap>
<div className="tab-label">
<div className="label-head">分类</div>
{categoryList?.map((i, j) => (
<div
className={`label-item flex-start ${
currentIndex === j && 'item-active'
}`}
key={j}
onClick={() => handleSelect(j)}
>
<img className="item-image" src={i.bannerImg} alt={i.bannerName} />
<div className="item-name">{i.bannerName}</div>
</div>
))}
</div>
<div className="tab-content">
{/* 产品商城 */}
{currentIndex === 0 && <TabView01 />}
{/* 行业服务 */}
{currentIndex === 1 && <TabView02 />}
{/* 设备租赁 */}
{currentIndex === 2 && <TabView03 />}
{/* 执照培训 */}
{currentIndex === 3 && <TabView04 />}
{/* 飞手约单 */}
{currentIndex === 4 && <TabView05 />}
</div>
</HomeTabWrap>
);
};
export default HomeTabView;
import styled from 'styled-components';
export const HomeTabWrap = styled.div`
position: relative;
height: 100%;
width: calc(100% - 25rem - 1rem);
min-width: 680px;
margin-right: 1rem;
//background: lavender;
display: flex;
align-items: flex-start;
justify-content: flex-start;
.tab-label {
position: relative;
height: 100%;
width: 8.58rem;
.label-head {
position: relative;
width: 8.58rem;
height: 3.58rem;
background: #ff7202;
line-height: 3.58rem;
box-sizing: border-box;
padding: 0 1rem;
font-size: 0.92rem;
font-weight: bold;
color: #ffffff;
}
.label-item {
position: relative;
width: 8.58rem;
height: 3.75rem;
margin-bottom: 0.42rem;
box-sizing: border-box;
.item-image {
width: 3.08rem;
height: 2.08rem;
}
.item-name {
font-size: 0.83rem;
font-weight: 550;
color: #333333;
margin-left: 0.33rem;
}
&:hover,
&:active {
background: #fff4f4;
}
&:hover::after,
&:active::after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 0.13rem;
height: 100%;
background: #ff7202;
}
}
.item-active {
background: #fff4f4;
&::after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 0.13rem;
height: 100%;
background: #ff7202;
}
}
}
.tab-content {
position: relative;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: hidden;
// 超出滚动
overflow-y: auto;
border: 0.04rem solid #e3e3e3;
&::-webkit-scrollbar-thumb {
background: #d9d9d9;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
cursor: pointer;
}
&::-webkit-scrollbar {
background-color: transparent;
-webkit-border-radius: 2em;
-moz-border-radius: 2em;
border-radius: 2em;
width: 7px;
height: 7px;
}
}
`;
import React, { useEffect, useState } from 'react';
import {
RightOutlined,
SafetyCertificateFilled,
VerticalAlignTopOutlined,
} from '@ant-design/icons';
import dayjs from 'dayjs';
import styled from 'styled-components';
import { HomeAPI } from '@/api';
import { InterDataType } from '@/api/interface';
import { AppPublishListType } from '@/api/interface/home';
import { formatLocationStr } from '@/utils/formatLocation';
import { bigNumberTransform } from '@/utils/money';
// 列表类型
type ListType = InterDataType<AppPublishListType>;
const HomeTaskView = () => {
// 服务标签类型
const serviceTagList = [
{
label: '加急单',
code: 'RUSH_ORDER',
color: '#FF0000',
text: '急',
},
{
label: '置顶单',
code: 'TOP_ORDER',
color: '#FF7A2C',
icon: (
<VerticalAlignTopOutlined style={{ color: '#fff', fontSize: 10 }} />
),
},
];
// 保险列表
const insuranceList = [
{ name: '飞手险', value: 1 },
{ name: '机身险', value: 2 },
{ name: '三者险', value: 3 },
];
// 实时订单列表
const [requireList, setRequireList] = useState<ListType>([]);
// 获取实时订单列表
const getAppPublishList = async () => {
const res = await HomeAPI.appPublishList({
isNewRequirements: true,
});
if (res && res.code === '200') {
const list = res.result || [];
setRequireList(
list.slice(0, 4),
// .map((i) => ({
// ...i,
// orderLevelEnum: 'RUSH_ORDER',
// requireDescription:
// '红鲤鱼绿鲤鱼与驴,红鲤鱼绿鲤鱼与驴,红鲤鱼绿鲤鱼与驴',
// orderAmount: 999999,
// })),
);
}
};
// 需求类型列表
const [typeList, setTypeList] = useState<{ id: number; typeName: string }[]>(
[],
);
// 获取需求类型
const getRequirementsListType = async () => {
const res = await HomeAPI.getRequirementsListType();
if (res && res.code === '200') {
setTypeList(res.result || []);
}
};
// 获取当前服务的标签类型
const getServiceTag = (i: ListType[0]) => {
const item = serviceTagList.find((n) => n.code === i?.orderLevelEnum);
return item || serviceTagList[0];
};
// 获取任务城市
const getTaskCity = (i: ListType[0]) => {
const item = formatLocationStr(i?.taskAddress);
return item?.city || '深圳市';
};
// 获取任务时间
const getTaskRange = (i: ListType[0]) =>
`${dayjs(i?.taskStartTime).format('MM.DD')}~${dayjs(i?.taskEndTime).format(
'MM.DD',
)}`;
// 获取任务类型
const getTaskType = (i: ListType[0]) => {
return typeList?.find((n) => n.id === i?.requirementTypeId)?.typeName;
};
// 获取保险列表
const getInsuranceList = (i: ListType[0]) => {
return (
i?.insurance
?.split(',')
?.map((k) => insuranceList.find((n) => n.value === Number(k))?.name)
?.join(' | ') || '无'
);
};
// 获取订单金额
const getOrderAmount = (i: ListType[0]) => {
const money = (bigNumberTransform(i?.orderAmount, true) as string)?.replace(
'.00',
'',
);
// formatMoney(props.detail?.orderAmount)
return i?.orderAmount > 1 ? money : i?.orderAmount;
};
// 组件挂载
useEffect(() => {
getRequirementsListType().then();
getAppPublishList().then();
}, []);
return (
<HomeTaskWrap>
<div className="task-title">
<div className="title-label">抢单大厅</div>
<div className="title-more">
<div className="more-label">更多</div>
<div className="more-icon">
<RightOutlined style={{ color: '#998e8b', fontSize: 13 }} />
</div>
</div>
</div>
<div className="task-list">
{requireList?.map((i, j) => (
<div className="list-item" key={j}>
<div className="item-title">
{i?.orderLevelEnum !== 'REGULAR_ORDER' && (
<div
className="title-tag"
style={{ background: getServiceTag(i)?.color }}
>
{getServiceTag(i)?.icon || getServiceTag(i)?.text}
</div>
)}
<div className="title-name">{i.requireDescription}</div>
</div>
<div className="item-tag flex-start">
<div className="tag-item">{getTaskCity(i)}</div>
<div className="tag-item">{getTaskRange(i)}</div>
<div className="tag-item">{i?.serviceName}</div>
<div className="tag-item">{getTaskType(i)}</div>
</div>
<div className="item-insurance flex-start">
<SafetyCertificateFilled style={{ color: '#36C1AF' }} />
<div className="text">
<span className="label">保险要求: </span>
<span>{getInsuranceList(i)}</span>
</div>
</div>
<div className="item-time">
{dayjs(i?.createTime).format('MM-DD HH:mm')} 发布
</div>
{i?.orderAmount && (
<div className="item-price">
<span className="label">¥</span>
<span className="num">{getOrderAmount(i)}</span>
</div>
)}
</div>
))}
</div>
</HomeTaskWrap>
);
};
export const HomeTaskWrap = styled.div`
width: 100%;
min-height: 8.71rem;
background: linear-gradient(180deg, #ffe1d9 0%, #ffebe5 100%);
box-sizing: border-box;
padding: 1.13rem 1rem 1.17rem 1rem;
.task-title {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 1rem;
.title-label {
font-size: 14px;
font-weight: bold;
color: #8b2c08;
line-height: 1.04rem;
}
.title-more {
display: flex;
align-items: baseline;
justify-content: flex-end;
.more-label {
font-size: 13px;
font-weight: 400;
color: #998e8b;
margin-right: 0.2rem;
}
}
}
.task-list {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
.list-item {
position: relative;
width: calc((100% - 0.83rem * 3) / 4);
min-height: 6rem;
background: #ffffff;
box-shadow: 0 0.25rem 0.5rem 0 rgba(204, 204, 204, 0.05);
border-radius: 0.25rem;
border: 0.02rem solid #ffffff;
margin-right: 0.83rem;
box-sizing: border-box;
padding: 0.58rem 0.5rem 0.67rem 0.5rem;
&:active,
&:hover {
filter: brightness(0.96);
}
&:last-child {
margin-right: 0;
}
.item-title {
position: relative;
width: 100%;
display: flex;
align-items: center;
justify-content: flex-start;
margin-bottom: 0.5rem;
.title-tag {
position: relative;
width: 18px;
height: 18px;
background: #ff0000;
border-radius: 0.17rem;
display: flex;
align-items: center;
justify-content: center;
margin-right: 0.35rem;
text-align: center;
line-height: 18px;
color: #ffffff;
font-size: 13px;
}
.title-name {
width: 60%;
font-size: 14px;
font-weight: bold;
color: #333333;
// 单行省略
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.item-tag {
position: relative;
width: 100%;
margin-bottom: 0.5rem;
.tag-item {
position: relative;
box-sizing: border-box;
padding: 0.1rem 0.25rem;
background: #fff5f4;
border-radius: 0.08rem;
font-size: 13px;
font-weight: 400;
color: #fe2910;
margin-right: 0.33rem;
}
}
.item-insurance {
.text {
margin-left: 0.2rem;
font-size: 13px;
font-weight: 400;
color: #666666;
}
}
.item-time {
position: absolute;
bottom: 0.67rem;
right: 0.5rem;
text-align: right;
font-size: 12px;
font-weight: 400;
color: #999999;
}
.item-price {
position: absolute;
top: 0.5rem;
right: 0.5rem;
text-align: right;
font-size: 16px;
font-weight: 600;
color: #fe2910;
}
}
}
`;
export default HomeTaskView;
import React from 'react';
import { RightOutlined } from '@ant-design/icons';
import styled from 'styled-components';
const HomeTitleView = ({ title }: { title: string }) => {
return (
<HomeTitleWrap>
<div className="title-text">{title}</div>
<div className="title-more flex-start">
<div className="more-text">更多</div>
<RightOutlined style={{ fontSize: 10, color: '#fff' }} />
</div>
</HomeTitleWrap>
);
};
export const HomeTitleWrap = styled.div`
position: relative;
width: 100%;
height: 4.38rem;
//background: rgba(49, 49, 49, 0.67);
opacity: 1;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
background-image: url('https://pad-video-x.oss-cn-shenzhen.aliyuncs.com/file/sharefly-web-headbg.png');
background-size: cover;
background-position: center;
z-index: 1;
&::after {
position: absolute;
content: '';
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
background: rgba(49, 49, 49, 0.25);
}
&:hover&::after,
&:active&::after {
background: rgba(49, 49, 49, 0.15);
}
.title-text {
font-size: 1.67rem;
font-weight: bold;
color: #ffffff;
letter-spacing: 12px;
}
.title-more {
position: absolute;
right: 0.8rem;
.more-text {
font-size: 13px;
font-weight: 400;
color: #ffffff;
margin-right: 0.2rem;
}
}
`;
export default HomeTitleView;
import React from 'react';
import { useRouter } from 'next/router';
import HomeBottomView from '@/pages/home/comp/home-bottom';
import HomeBrandView from '@/pages/home/comp/home-brand';
import HomeMapView from '@/pages/home/comp/home-map';
import HomeNewsView from '@/pages/home/comp/home-news';
import HomeProductView from '@/pages/home/comp/home-product';
import HomeSearchView from '@/pages/home/comp/home-search';
import HomeTabView from '@/pages/home/comp/home-tab';
import HomeTaskView from '@/pages/home/comp/home-task';
import HomeTitleView from '@/pages/home/comp/home-title';
import { HomeWrap } from '@/pages/home/styled';
const HomeView = () => {
// 路由钩子
const router = useRouter();
// 消息提醒
// const handleClick = async () => {
// await message.success('你好');
// };
// 跳转测试
// const handleNavigate = async () => {
// await router.push('/mall');
// };
return (
<HomeWrap>
{/* 主页搜索 */}
<HomeSearchView />
{/* 网格布局 */}
<div className="home-grid">
{/* 主页分类 */}
<HomeTabView />
{/* 全国网点 */}
<HomeMapView />
{/* 主页新闻 */}
<HomeNewsView />
</div>
{/* 弹性布局 */}
<div className="home-wrap">
{/* 抢单大厅 */}
<HomeTaskView />
{/* 品牌企业 */}
<HomeBrandView />
{/* 大家都在买 */}
<HomeTitleView title="大家都在买" />
{/* 推荐商品 */}
<HomeProductView />
{/* 无人机服务 */}
<HomeTitleView title="无人机服务" />
{/* 底部标签 */}
<HomeBottomView />
</div>
{/* <h1 className="title">home</h1> */}
{/* <Button type={'primary'} onClick={handleClick}> */}
{/* 测试 */}
{/* </Button> */}
{/* <Button type={'primary'} onClick={handleNavigate}> */}
{/* 跳转 */}
{/* </Button> */}
</HomeWrap>
);
};
export default HomeView;
import styled from 'styled-components';
export const HomeWrap = styled.div`
width: 100%;
//height: 100vh;
//display: flex;
//justify-content: center;
//align-items: center;
//flex-direction: column;
.home-grid {
position: relative;
max-width: 1190px;
height: 34rem;
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: flex-start;
flex-wrap: wrap;
flex-direction: column;
padding: 2rem 0 0 0;
margin: 0 auto;
//padding: 2rem 12rem 0 12rem;
//.half {
// height: calc((100% - 1rem) / 2);
// width: 25rem;
// background: lightblue;
// margin-bottom: 1rem;
// &:last-child {
// margin-bottom: 0;
// }
//}
}
.home-wrap {
position: relative;
max-width: 1190px;
//height: 34rem;
box-sizing: border-box;
display: flex;
align-items: flex-start;
justify-content: flex-start;
//flex-wrap: wrap;
flex-direction: column;
padding: 1rem 0 0 0;
margin: 0 auto;
}
//// 媒体查询
//@media screen and (min-width: 1600px) {
// .home-grid {
// padding: 2rem 20rem 0 20rem;
// }
//}
//@media screen and (max-width: 1300px) {
// .home-grid {
// padding: 2rem 3rem 0 3rem;
// }
//}
`;
import React from 'react';
import LayoutView from '@/components/layout';
import HomeView from '@/pages/home';
const App = () => {
return (
<LayoutView>
<HomeView></HomeView>
</LayoutView>
);
};
export default App;
import React, { useEffect } from 'react';
import { Button } from 'antd';
import { useRouter } from 'next/router';
import { CommonAPI } from '@/api';
import LayoutView from '@/components/layout';
// 每次加载页面都会执行
export async function getServerSideProps() {
// 分类数据
let categoryData = {};
// 获取分类数据
const getPageHomeCategories = async () => {
const res = await CommonAPI.getPageHomeCategories({
type: 4,
});
if (res && res.code === '200') {
categoryData = res;
}
};
// 依次获取接口数据
await (async () => {
await getPageHomeCategories();
})();
return { props: { categoryData } };
}
const MallView = (props: any) => {
// 路由钩子
const router = useRouter();
// 获取接口数据
const getCooperationListTag = async () => {
const res = await CommonAPI.cooperationListTag();
if (res && res.code === '200') {
console.log('获取接口数据 --->', res);
}
};
useEffect(() => {
getCooperationListTag().then();
console.log('执行到此处12312 --->', props);
}, [props]);
return (
<>
<LayoutView>
<div>测试</div>
<Button
onClick={() => {
router.back();
}}
>
返回
</Button>
</LayoutView>
</>
);
};
export default MallView;
.main {
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 6rem;
min-height: 100vh;
}
.description {
display: inherit;
justify-content: inherit;
align-items: inherit;
font-size: 0.85rem;
max-width: var(--max-width);
width: 100%;
z-index: 2;
font-family: var(--font-mono);
}
.description a {
display: flex;
justify-content: center;
align-items: center;
gap: 0.5rem;
}
.description p {
position: relative;
margin: 0;
padding: 1rem;
background-color: rgba(var(--callout-rgb), 0.5);
border: 1px solid rgba(var(--callout-border-rgb), 0.3);
border-radius: var(--border-radius);
}
.code {
font-weight: 700;
font-family: var(--font-mono);
}
.grid {
display: grid;
grid-template-columns: repeat(4, minmax(25%, auto));
max-width: 100%;
width: var(--max-width);
}
.card {
padding: 1rem 1.2rem;
border-radius: var(--border-radius);
background: rgba(var(--card-rgb), 0);
border: 1px solid rgba(var(--card-border-rgb), 0);
transition:
background 200ms,
border 200ms;
}
.card span {
display: inline-block;
transition: transform 200ms;
}
.card h2 {
font-weight: 600;
margin-bottom: 0.7rem;
}
.card p {
margin: 0;
opacity: 0.6;
font-size: 0.9rem;
line-height: 1.5;
max-width: 30ch;
}
.center {
display: flex;
justify-content: center;
align-items: center;
position: relative;
padding: 4rem 0;
}
.center::before {
background: var(--secondary-glow);
border-radius: 50%;
width: 480px;
height: 360px;
margin-left: -400px;
}
.center::after {
background: var(--primary-glow);
width: 240px;
height: 180px;
z-index: -1;
}
.center::before,
.center::after {
content: "";
left: 50%;
position: absolute;
filter: blur(45px);
transform: translateZ(0);
}
.logo {
position: relative;
}
/* Enable hover only on non-touch devices */
@media (hover: hover) and (pointer: fine) {
.card:hover {
background: rgba(var(--card-rgb), 0.1);
border: 1px solid rgba(var(--card-border-rgb), 0.15);
}
.card:hover span {
transform: translateX(4px);
}
}
@media (prefers-reduced-motion) {
.card:hover span {
transform: none;
}
}
/* Mobile */
@media (max-width: 700px) {
.content {
padding: 4rem;
}
.grid {
grid-template-columns: 1fr;
margin-bottom: 120px;
max-width: 320px;
text-align: center;
}
.card {
padding: 1rem 2.5rem;
}
.card h2 {
margin-bottom: 0.5rem;
}
.center {
padding: 8rem 0 6rem;
}
.center::before {
transform: none;
height: 300px;
}
.description {
font-size: 0.8rem;
}
.description a {
padding: 1rem;
}
.description p,
.description div {
display: flex;
justify-content: center;
position: fixed;
width: 100%;
}
.description p {
align-items: center;
inset: 0 0 auto;
padding: 2rem 1rem 1.4rem;
border-radius: 0;
border: none;
border-bottom: 1px solid rgba(var(--callout-border-rgb), 0.25);
background: linear-gradient(
to bottom,
rgba(var(--background-start-rgb), 1),
rgba(var(--callout-rgb), 0.5)
);
background-clip: padding-box;
backdrop-filter: blur(24px);
}
.description div {
align-items: flex-end;
pointer-events: none;
inset: auto 0 0;
padding: 2rem;
height: 200px;
background: linear-gradient(
to bottom,
transparent 0%,
rgb(var(--background-end-rgb)) 40%
);
z-index: 1;
}
}
/* Tablet and Smaller Desktop */
@media (min-width: 701px) and (max-width: 1120px) {
.grid {
grid-template-columns: repeat(2, 50%);
}
}
@media (prefers-color-scheme: dark) {
.vercelLogo {
filter: invert(1);
}
.logo {
filter: invert(1) drop-shadow(0 0 0.3rem #ffffff70);
}
}
@keyframes rotate {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
:root {
--default-padding: 0 12rem;
--max-width: 1100px;
--border-radius: 12px;
--font-mono: ui-monospace, Menlo, Monaco, "Cascadia Mono", "Segoe UI Mono",
"Roboto Mono", "Oxygen Mono", "Ubuntu Monospace", "Source Code Pro",
"Fira Mono", "Droid Sans Mono", "Courier New", monospace;
--foreground-rgb: 0, 0, 0;
/*--background-start-rgb: 214, 219, 220;*/
--background-start-rgb: 255, 255, 255;
--background-end-rgb: 255, 255, 255;
--primary-glow: conic-gradient(
from 180deg at 50% 50%,
#16abff33 0deg,
#0885ff33 55deg,
#54d6ff33 120deg,
#0071ff33 160deg,
transparent 360deg
);
--secondary-glow: radial-gradient(
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
);
--tile-start-rgb: 239, 245, 249;
--tile-end-rgb: 228, 232, 233;
--tile-border: conic-gradient(
#00000080,
#00000040,
#00000030,
#00000020,
#00000010,
#00000010,
#00000080
);
--callout-rgb: 238, 240, 241;
--callout-border-rgb: 172, 175, 176;
--card-rgb: 180, 185, 188;
--card-border-rgb: 131, 134, 135;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
--primary-glow: radial-gradient(rgba(1, 65, 255, 0.4), rgba(1, 65, 255, 0));
--secondary-glow: linear-gradient(
to bottom right,
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0),
rgba(1, 65, 255, 0.3)
);
--tile-start-rgb: 2, 13, 46;
--tile-end-rgb: 2, 5, 19;
--tile-border: conic-gradient(
#ffffff80,
#ffffff40,
#ffffff30,
#ffffff20,
#ffffff10,
#ffffff10,
#ffffff80
);
--callout-rgb: 20, 20, 20;
--callout-border-rgb: 108, 108, 108;
--card-rgb: 100, 100, 100;
--card-border-rgb: 200, 200, 200;
}
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
html,
body {
max-width: 100vw;
min-width: 1200px;
/*overflow-x: hidden;*/
font-family: PingFangSC-Regular, Microsoft YaHei, Hiragino Sans GB, Helvetica, serif, sans-serif;
}
body {
font-size: 13px;
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}
a {
color: inherit;
text-decoration: none;
}
@media (prefers-color-scheme: dark) {
html {
color-scheme: dark;
}
}
.flex-center {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.flex-start {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: center;
}
.flex-baseline{
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-items: baseline;
}
.flex-end {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: center;
}
.flex-between {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
}
.flex-around {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
align-items: center;
}
.text-ellipsis{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/*::-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;*/
/*}*/
import type { ThemeConfig } from 'antd';
const themeConfig: ThemeConfig = {
token: {
fontSize: 14,
colorPrimary: '#ff552d',
},
components: {
Button: {
colorLink: '#ffffff',
colorLinkActive: '#ff552d',
colorLinkHover: '#ff552d',
contentFontSize: 12,
},
},
};
export default themeConfig;
// eslint-disable-next-line camelcase,@typescript-eslint/naming-convention
const reg_address =
'(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+?(区{1})|.+市|.+旗|.+海域|.+岛)?(?<village>.*)';
function formatLocation(str: string) {
if (!str) return;
// 中国4个直辖市
const municipality = ['重庆', '北京', '上海', '天津'];
const subStr = str.substring(0, 2);
const isExist = municipality.includes(subStr);
if (isExist) {
// eslint-disable-next-line no-param-reassign
str = str.substring(2, str.length - 1);
// eslint-disable-next-line no-param-reassign
str = `${subStr}${str}`;
}
const addr = str.match(reg_address);
if (!addr) return;
const groups = { ...addr.groups };
// 如果是直辖市,截取地址后,把省字替换成市
if (isExist) {
groups.province = groups.province.replace('省', '');
}
// eslint-disable-next-line consistent-return
return groups;
}
export default formatLocation;
/**
* 格式化地区信息
* @param {String} str 要格式化的地区信息
* @returns Object {province: "", city: "", detail: ""}
*/
export function formatLocationStr(str = '') {
const result = {
province: '',
city: '',
detail: '',
};
const provinceRegExp = /(.+?(省|自治区))(.*)/;
const provinceList = str.match(provinceRegExp);
let restStr = str;
if (provinceList) {
// eslint-disable-next-line prefer-destructuring
result.province = provinceList[1];
// eslint-disable-next-line prefer-destructuring
restStr = provinceList[3];
}
const cityRegExp = /(.+?(市|自治州|行政区))(.*)/;
const cityList = restStr.match(cityRegExp);
if (cityList) {
// eslint-disable-next-line prefer-destructuring
result.city = cityList[1];
// eslint-disable-next-line prefer-destructuring
result.detail = cityList[3];
} else {
result.detail = restStr;
}
// console.log(result)
return result;
}
// 随机生成
export const RandomNum = (minNum: number, maxNum: number) => {
return parseInt(String(Math.random() * (maxNum - minNum + 1) + minNum), 10);
};
// 授权
export const RandomShareImg = () => {
const ImgList = [
'https://share-fly.oss-cn-hangzhou.aliyuncs.com/file/shareCard20230718.jpg',
];
return ImgList[parseInt(String(Math.random() * ImgList.length), 10)];
};
// 判空
export const isNone = (val: string | number | null | undefined) => {
return val === null || val === undefined || val === '';
};
// 判零和空
export const isNoneZero = (val: string | number | null | undefined) => {
return val === null || val === undefined || val === '' || val === 0;
};
// 随机获取数组中的元素
export function getRandomArrayElements(arr: any[], count: number) {
const shuffled = arr.slice(0);
let i = arr.length;
const min = i - count;
let temp;
let index; // 只是声明变量的方式, 也可以分开写
// eslint-disable-next-line no-plusplus
while (i-- > min) {
// console.log(i);
index = Math.floor((i + 1) * Math.random()); // 这里的+1 是因为上面i--的操作 所以要加回来
temp = shuffled[index]; // 即值交换
shuffled[index] = shuffled[i];
shuffled[i] = temp;
// console.log(shuffled);
}
return shuffled.slice(min);
}
// adcode转换为省市区编号
export const adcodeToCode = (
adcode: string | number,
): {
provinceCode: string;
cityCode: string;
districtCode: string;
} => {
return {
provinceCode: String(adcode).replace(/.{4}$/, '0000'),
cityCode: String(adcode).replace(/.{2}$/, '00'),
districtCode: String(adcode),
};
};
// @ts-nocheck
/* eslint-disable */
import Big from "big.js";
import {isNone} from "@/utils/index";
export const formatCurrency = (s, n) => {
n = n > 0 && n <= 20 ? n : 2
s = `${parseFloat(`${s}`.replace(/[^\d\.-]/g, '')).toFixed(n)}`
const l = s.split('.')[0].split('').reverse()
const r = s.split('.')[1]
let t = ''
for (let i = 0; i < l.length; i++) {
t += l[i] + ((i + 1) % 3 == 0 && i + 1 != l.length ? ',' : '')
}
return t.split('').reverse().join('')
}
// 格式化千分位并补零
export const moneyFormat = (num) => {
if (Number(num).toString() !== 'NaN') {
// 添加千分符
let _n = Number(num).toLocaleString()
if (_n.indexOf('.') !== -1) {
_n = `${_n}00`
} else {
_n = `${_n}.00`
}
// 因为有千分符所以,返回数据为字符串格式,无法做运算操作,适合做直接显示使用
return _n.substring(0, _n.indexOf('.') + 3)
}
// console.log('参数格式有误')
}
// 金额大数字转换
export const bigNumberTransform = (value, type) => {
const newValue = ['', '', ''];
let fr = new Big(1000);
let num = 3;
let text1 = '';
let text2 = '';
let fm = new Big(1);
if (value === '' || value === null || isNaN(value)) {
return !type ? newValue : '';
}
value = new Big(value);
if (value.lt(0)) {
value = value.abs();
text2 = '-';
}
while (value.div(fr).gte(1)) {
fr = fr.times(10);
num += 1;
}
if (num <= 4) {
// 千
newValue[0] = value.toString();
newValue[1] = '';
} else if (num <= 8) {
// 万
text1 = '万';
fm = text1 === '万' ? new Big(10000) : new Big(10000000);
if (value.mod(fm).eq(0)) {
newValue[0] = `${value.div(fm).round()}`;
} else {
newValue[0] = `${value.div(fm).round(2, 0)}`;
}
newValue[1] = text1;
} else {
// 亿
text1 = '亿';
text1 = (num - 8) / 4 > 1 ? '万亿' : text1;
text1 = (num - 8) / 7 > 1 ? '千万亿' : text1;
text1 = (num - 8) / 10 > 1 ? '亿亿' : text1;
fm =
text1 === '亿'
? new Big(100000000)
: text1 === '千亿'
? new Big(100000000000)
: text1 === '万亿'
? new Big(1000000000000)
: text1 === '千万亿'
? new Big(1000000000000000)
: new Big(1000000000000000000);
if (value.mod(fm).eq(0)) {
newValue[0] = `${value.div(fm).round()}`;
} else {
newValue[0] = `${value.div(fm).round(2, 0)}`;
}
newValue[1] = text1;
}
if (value.lt(1000)) {
newValue[0] = `${value}`;
newValue[1] = '';
}
newValue[0] = text2 ? text2 + newValue[0] : newValue[0];
return !type ? Number(newValue).toFixed(2).toLocaleString() : Number(newValue[0]).toFixed(2).toLocaleString() + newValue[1];
};
// 格式化金额
export const formatMoney = (money) => {
return !isNone(money) ? Big(money)?.toFixed(2)?.toLocaleString() : ''
}
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"]
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论