diff --git a/src/components/search-city/index.less b/src/components/search-city/index.less new file mode 100644 index 0000000..f028d72 --- /dev/null +++ b/src/components/search-city/index.less @@ -0,0 +1,162 @@ +@import '@/styles/variables.less'; +@import '@/styles/common.less'; + +.search-city { + background: #fff; + + &__position-title { + font-size: 24px; + color: @blColorG1; + padding: 0 24px; + margin-top: 18px; + } + + &__position-city { + font-size: 30px; + font-weight: bold; + color: @blColor; + padding: 0 24px; + margin-top: 18px; + } + + &__hot-city-title { + height: 48px; + font-size: 24px; + line-height: 48px; + padding: 0 24px; + color: #999; + background: #f2f5f7; + margin-top: 18px; + } + + &__hot-city-container { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + align-content: space-between; + width: 630px; + padding: 12px 90px 26px 30px; + background: #ffffff; + } + + &__hot-city-item { + width: 140px; + height: 58px; + font-size: 28px; + line-height: 58px; + text-align: center; + border-radius: 58px; + border: 2px solid @blColorG1; + margin-top: 18px; + } + + &__indexes-list { + width: 100%; + /* 兼容 iOS < 11.2 */ + padding-bottom: constant(safe-area-inset-bottom); + /* 兼容 iOS >= 11.2 */ + padding-bottom: env(safe-area-inset-bottom); + } + + &__indexes-fragment { + } + + &__indexes-anchor { + height: 48px; + font-size: 24px; + line-height: 48px; + padding: 0 24px; + color: @blColorG1; + background: #f2f5f7; + } + + &__indexes-cell { + position: relative; + font-size: 28px; + padding: 30px 24px; + color: @blColor; + + &::after { + content: ''; + position: absolute; + border-bottom: 1rpx solid #eaeef1; + transform: scaleY(0.5); + bottom: 0; + right: 0; + left: 24px; + } + } + + &__indexes-bar { + width: 44rpx; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + position: fixed; + right: 10px; + } + + &__indexes-bar-item { + font-size: 22px; + color: @blColor; + white-space: nowrap; + display: flex; + align-items: center; + justify-content: center; + } + + &__indexes-index-alert { + position: absolute; + z-index: 20; + width: 160px; + height: 160px; + left: 50%; + top: 50%; + margin-left: -80px; + margin-top: -80px; + border-radius: 80px; + text-align: center; + line-height: 160px; + font-size: 70px; + color: #ffffff; + background-color: rgba(0, 0, 0, 0.5); + } + + &__search-wrapper { + &.group { + background: linear-gradient(2.75deg, #ffffff 7.9%, #f2edff 97.24%); + .search-city__search { + background-color: transparent; + .taroify-search__content--rounded { + border: @blHighlightColor 1px solid; + } + } + } + } + + &__banner { + padding: 32px 24px 0; + text-align: center; + font-size: 28px; + line-height: 40px; + color: @blHighlightColor; + .flex-row(); + + .text { + padding: 0 12px; + flex: 0 1 auto; + } + .dash { + height: 1px; + flex: 1; + + &:first-child { + background: linear-gradient(270deg, #6d3df5 0%, #f7f4ff 100%); + } + &:last-child { + background: linear-gradient(90deg, #6d3df5 0%, #f7f4ff 100%); + } + } + } +} diff --git a/src/components/search-city/index.tsx b/src/components/search-city/index.tsx new file mode 100644 index 0000000..3463812 --- /dev/null +++ b/src/components/search-city/index.tsx @@ -0,0 +1,234 @@ +import { BaseEventOrig, InputProps, ScrollView } from '@tarojs/components'; +import Taro from '@tarojs/taro'; + +import { Search } from '@taroify/core'; +import { useCallback, useEffect, useState } from 'react'; + +import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST, GROUP_CITY_INDEXES_LIST } from '@/constants/city'; +import { logWithPrefix } from '@/utils/common'; + +import './index.less'; + +interface Item { + cityCode: number | string; + cityName: string; + keyword: string; +} + +const PREFIX = 'search-city'; +const HOT_CITY = [ + { cityCode: 110100, cityName: '北京' }, + { cityCode: 310100, cityName: '上海' }, + { cityCode: 440100, cityName: '广州' }, + { cityCode: 440300, cityName: '深圳' }, + { cityCode: 330100, cityName: '杭州' }, + { cityCode: 430100, cityName: '长沙' }, + { cityCode: 420100, cityName: '武汉' }, + { cityCode: 350200, cityName: '厦门' }, + { cityCode: 610100, cityName: '西安' }, + { cityCode: 410100, cityName: '郑州' }, + { cityCode: 510100, cityName: '成都' }, + { cityCode: 340100, cityName: '合肥' }, +]; + +const OFFSET_INDEX_SIZE = 2; +const log = logWithPrefix(PREFIX); +const realtimeLogger = Taro.getRealtimeLogManager(); +realtimeLogger.tag(PREFIX); +const useHeight = () => { + const [winHeight, setWinHeight] = useState(0); + const [indexItemHeight, setIndexItemHeight] = useState(0); + + useEffect(() => { + const windowInfo = Taro.getWindowInfo(); + const windowHeight = windowInfo.windowHeight; + setWinHeight(windowHeight); + // 上下预留两个选项高度的空白 + setIndexItemHeight(Math.floor(windowHeight / (26 + OFFSET_INDEX_SIZE * 2))); + }, []); + + return [winHeight, indexItemHeight]; +}; +export interface SearchCityProps { + onSelectCity: (cityCode: string) => void; + currentCity?: string; + forGroup?: boolean; + offset?: number; +} + +export default function SearchCity({ onSelectCity, currentCity = '', forGroup = false, offset = 0 }: SearchCityProps) { + const [winHeight, indexItemHeight] = useHeight(); + const [touchAnchor, setTouchAnchor] = useState(); + const [touchMoving, setTouchMoving] = useState(false); + const [searchResult, setSearchResult] = useState([]); + const showSearchList = searchResult.length > 0; + const CITY_LIST = forGroup ? GROUP_CITY_INDEXES_LIST : CITY_INDEXES_LIST; + + const handleSearchChange = useCallback((event: BaseEventOrig) => { + const value = event.detail.value; + log('handleSearchChange', value); + if (!value) { + setSearchResult([]); + return; + } + const result: Item[] = []; + CITY_LIST.forEach(obj => { + obj.data.forEach(city => { + if (city.keyword.includes(value.toLocaleUpperCase())) { + result.push({ ...city }); + } + }); + }); + setSearchResult(result); + }, []); + + const handleSelectCity = useCallback( + (e: React.MouseEvent) => { + const cityCode = e.currentTarget.dataset.code; + onSelectCity(String(cityCode)); + }, + [onSelectCity] + ); + + const handleTouchStart = useCallback( + (e: React.TouchEvent) => { + const pageY = e.touches[0].pageY; + const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; + if (index < 0 || index >= CITY_LIST.length) { + return; + } + const item = CITY_LIST[index]; + if (item) { + setTouchMoving(true); + setTouchAnchor(item.letter); + } + }, + [indexItemHeight] + ); + + const handleTouchMove = useCallback( + (e: React.TouchEvent) => { + const pageY = e.touches[0].pageY; + const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; + if (index < 0 || index >= CITY_LIST.length) { + return; + } + const item = CITY_LIST[index]; + item && setTouchAnchor(item.letter); + }, + [indexItemHeight] + ); + + const handleTouchEnd = useCallback((e: React.TouchEvent) => { + e.stopPropagation(); + setTouchMoving(false); + log('touch end'); + }, []); + + const handleClickAnchor = useCallback((anchor: string) => { + setTouchAnchor(anchor); + log('click anchor', anchor); + }, []); + + return ( +
+ +
+ {forGroup && ( +
+
+
点击城市名称,进本地通告群,免费招主播
+
+
+ )} + +
+ {showSearchList && ( +
+ {searchResult.map(city => ( +
+ {city.cityName} +
+ ))} +
+ )} + {!showSearchList && ( +
+
当前城市
+
{CITY_CODE_TO_NAME_MAP.get(currentCity)}
+
热门城市
+
+ {HOT_CITY.map(city => ( +
+ {city.cityName} +
+ ))} +
+
+ {CITY_LIST.map(item => { + return ( +
+
+ {item.letter} +
+ {item.data.map(city => ( +
+ {city.cityName} +
+ ))} +
+ ); + })} +
+
+ )} +
+
+ {!showSearchList && ( +
+ {CITY_LIST.map(item => { + return ( +
handleClickAnchor(item.letter)} + > + {item.letter} +
+ ); + })} +
+ )} + {touchAnchor && touchMoving &&
{touchAnchor}
} +
+
+ ); +} diff --git a/src/components/user-batch-publish/index.less b/src/components/user-batch-publish/index.less new file mode 100644 index 0000000..f43a4df --- /dev/null +++ b/src/components/user-batch-publish/index.less @@ -0,0 +1,89 @@ +@import '@/styles/common.less'; +@import '@/styles/variables.less'; + +.user-batch-publish { + padding: 16px 24px; + + &__header-image { + width: 100%; + height: 120px; + margin-top: 24px; + } + + &__title { + font-size: 32px; + line-height: 48px; + font-weight: 500; + color: @blColor; + margin-top: 24px; + + &:first-child { + margin-top: 0; + } + } + + &__cell { + height: 100px; + padding-left: 32px; + padding-right: 32px; + border-radius: 16px; + margin-top: 24px; + } + + &__cost-describe { + height: 100px; + padding: 0 32px; + border-radius: 16px; + .flex-row(); + justify-content: space-between; + background: #FFFFFF; + margin-top: 24px; + + &__price { + font-size: 48px; + line-height: 48px; + font-weight: 500; + color: @blHighlightColor; + } + + &__original_price { + flex: 1; + font-size: 32px; + line-height: 34px; + font-weight: 400; + color: @blColorG1; + margin-left: 16px; + text-decoration: line-through; + } + } + + &__illustrate { + padding: 24px 32px; + margin-top: 24px; + font-size: 28px; + line-height: 48px; + font-weight: 400; + color: @blColorG2; + background: #FFFFFF; + border-radius: 16px; + + &__describe { + .flex-row(); + font-size: 28px; + line-height: 48px; + font-weight: 400; + color: @blColorG2; + margin-top: 8px; + + &__view { + color: @blHighlightColor; + margin-left: 4px; + } + } + } + + &__buy-button { + .button(@width: 100%; @height: 80px; @fontSize: 32px); + margin-top: 40px; + } +} diff --git a/src/components/user-batch-publish/index.tsx b/src/components/user-batch-publish/index.tsx new file mode 100644 index 0000000..0db5830 --- /dev/null +++ b/src/components/user-batch-publish/index.tsx @@ -0,0 +1,195 @@ +import { Button, Image, Text } from '@tarojs/components'; +import Taro from '@tarojs/taro'; + +import { Cell } from '@taroify/core'; +import { useCallback, useState, useEffect } from 'react'; + +import PageLoading from '@/components/page-loading'; +import { PublishJobQrCodeDialog } from '@/components/product-dialog/publish-job'; +import SafeBottomPadding from '@/components/safe-bottom-padding'; +import { ISelectOption, PopupSelect } from '@/components/select'; +import { PageUrl } from '@/constants/app'; +import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product'; +import { BatchPublishGroup } from '@/types/group'; +import { logWithPrefix } from '@/utils/common'; +import { + getOrderPrice, + isCancelPay, + requestAllBuyProduct, + requestCreatePayInfo, + requestOrderInfo, + requestPayment, +} from '@/utils/product'; +import { navigateTo } from '@/utils/route'; +import Toast from '@/utils/toast'; + +import './index.less'; + +interface CityValue extends BatchPublishGroup { + cityName: string; +} + +interface CityOption extends ISelectOption { + value: CityValue; +} + +const PREFIX = 'user-batch-publish'; +const log = logWithPrefix(PREFIX); +const SERVICE_ILLUSTRATE = `群发次数:每日一次,连发3天 +群发内容:仅限主播招聘通告,违规内容不发 +联系方法:通告中留通告主联系方式,主播直接联系`; +const cityValues: CityValue[] = [ + { cityCode: '440100', cityName: '广州', count: 300 }, + { cityCode: '440300', cityName: '深圳', count: 100 }, + { cityCode: '330100', cityName: '杭州', count: 300 }, + { cityCode: '110100', cityName: '北京', count: 100 }, + { cityCode: '510100', cityName: '成都', count: 50 }, + { cityCode: '430100', cityName: '长沙', count: 50 }, + { cityCode: '350200', cityName: '厦门', count: 50 }, + { cityCode: '310100', cityName: '上海', count: 100 }, + { cityCode: '420100', cityName: '武汉', count: 50 }, + { cityCode: '610100', cityName: '西安', count: 50 }, + { cityCode: '410100', cityName: '郑州', count: 100 }, +].sort((a, b) => b.count - a.count); +const MIN_GROUP_SIZE = 20; +const GROUP_OPTIONS = [ + { value: MIN_GROUP_SIZE, productSpecId: ProductSpecId.GroupBatchPublish20, label: '20', price: 18 }, + { value: 50, productSpecId: ProductSpecId.GroupBatchPublish50, label: '50', price: 40 }, + { value: 100, productSpecId: ProductSpecId.GroupBatchPublish100, label: '100', price: 68 }, + { value: 300, productSpecId: ProductSpecId.GroupBatchPublish300, label: '300', price: 128 }, + { value: 500, productSpecId: ProductSpecId.GroupBatchPublish500, label: '500', price: 188 }, + { value: 1000, productSpecId: ProductSpecId.GroupBatchPublish1000, label: '1000', price: 288 }, +]; + +const calcPrice = (city: CityValue | null) => { + if (!city) { + return {}; + } + const { count } = city; + const originalPrice = count * 1; + const price = GROUP_OPTIONS.find(o => o.value === count)?.price || 18; + const productSpecId = GROUP_OPTIONS.find(o => o.value === count)?.productSpecId || ProductSpecId.GroupBatchPublish20; + return { price, originalPrice, productSpecId }; +}; + +export default function UserBatchPublish() { + const [loading, setLoading] = useState(true); + const [showCitySelect, setShowCitySelect] = useState(false); + const [showQrCode, setShowQrCode] = useState(false); + const [city, setCity] = useState(null); + const [cityOptions, setCityOptions] = useState([]); + const { price, originalPrice, productSpecId } = calcPrice(city); + + const handleClickCity = useCallback(() => setShowCitySelect(true), []); + + const handleSelectCity = useCallback(value => { + setCity(value); + setShowCitySelect(false); + }, []); + + const handleClickViewGroup = useCallback(() => navigateTo(PageUrl.GroupList, { city: city?.cityCode }), [city]); + + const handleClickBuy = useCallback(async () => { + // if (1 < 2) { + // await new Promise(r => setTimeout(r, 3000)); + // setShowQrCode(true); + // return; + // } + if (!price || !productSpecId) { + return; + } + try { + Taro.showLoading(); + const allowBuy = await requestAllBuyProduct(ProductType.GroupBatchPublish); + if (!allowBuy) { + Taro.hideLoading(); + Toast.info('您最近已购买过,可直接联系客服'); + setShowQrCode(true); + return; + } + const { payOrderNo, createPayInfo } = await requestCreatePayInfo({ + type: OrderType.GroupBatchPublish, + amt: getOrderPrice(price), + // amt: 1, + productCode: ProductType.GroupBatchPublish, + productSpecId: productSpecId, + }); + log('handleBuy payInfo', payOrderNo, createPayInfo); + await requestPayment({ + timeStamp: createPayInfo.timeStamp, + nonceStr: createPayInfo.nonceStr, + package: createPayInfo.packageVal, + signType: createPayInfo.signType, + paySign: createPayInfo.paySign, + }); + const { status } = await requestOrderInfo({ payOrderNo }); + log('handleBuy orderInfo', status); + if (status !== OrderStatus.Success) { + throw new Error('order status error'); + } + Taro.hideLoading(); + setShowQrCode(true); + } catch (e) { + Taro.hideLoading(); + Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试'); + log('handleBuy error', e); + } + }, [price, productSpecId]); + + useEffect(() => { + try { + const cOptions: CityOption[] = cityValues.map(value => ({ value, label: value.cityName })); + const initCity = cOptions[0].value; + + setLoading(false); + setCity(initCity); + setCityOptions(cOptions); + log('init data done', cOptions); + } catch (e) { + Toast.error('加载失败请重试'); + } + }, []); + + if (loading) { + return ; + } + + return ( +
+ +
请选择城市
+ +
可购买群数
+ +
服务费用
+
+
{`${price}元`}
+
{`原价:${originalPrice}元`}
+
+
服务说明
+
+ {SERVICE_ILLUSTRATE} +
+
附:
+
+ 播络合作群列表 +
+
+
+ + +
+ setShowCitySelect(false)} + /> + setShowQrCode(false)} open={showQrCode} /> +
+
+ ); +} diff --git a/src/constants/city.ts b/src/constants/city.ts index edbf6d6..77ac332 100644 --- a/src/constants/city.ts +++ b/src/constants/city.ts @@ -5859,3 +5859,151 @@ export const CITY_INDEXES_LIST = [ ], }, ]; + +export const GROUP_CITY_INDEXES_LIST = [ + { + letter: 'C', + data: [ + { + cityCode: '500100', + cityName: '重庆', + keyword: 'CHONGQING重庆', + }, + { + cityCode: '510100', + cityName: '成都', + keyword: 'CHENGDOU成都', + }, + ], + }, + { + letter: 'D', + data: [ + { + cityCode: '441900', + cityName: '东莞', + keyword: 'DONGGUAN东莞', + }, + ], + }, + { + letter: 'F', + data: [ + { + cityCode: '440600', + cityName: '佛山', + keyword: 'FUSHAN佛山', + }, + { + cityCode: '350100', + cityName: '福州', + keyword: 'FUZHOU福州', + }, + ], + }, + { + letter: 'G', + data: [ + { + cityCode: '440100', + cityName: '广州', + keyword: 'GUANGZHOU广州', + }, + ], + }, + { + letter: 'H', + data: [ + { + cityCode: '340100', + cityName: '合肥', + keyword: 'HEFEI合肥', + }, + ], + }, + { + letter: 'N', + data: [ + { + cityCode: '320100', + cityName: '南京', + keyword: 'NANJING南京', + }, + ], + }, + { + letter: 'Q', + data: [ + { + cityCode: '370200', + cityName: '青岛', + keyword: 'QINGDAO青岛', + }, + ], + }, + { + letter: 'S', + data: [ + { + cityCode: '310100', + cityName: '上海', + keyword: 'SHANGHAI上海', + }, + { + cityCode: '440300', + cityName: '深圳', + keyword: 'SHENZHEN深圳', + }, + { + cityCode: '320500', + cityName: '苏州', + keyword: 'SUZHOU苏州', + }, + { + cityCode: '330300', + cityName: '温州', + keyword: 'WENZHOU温州', + }, + ], + }, + { + letter: 'T', + data: [ + { + cityCode: '120100', + cityName: '天津', + keyword: 'TIANJIN天津', + }, + ], + }, + { + letter: 'W', + data: [ + { + cityCode: '420100', + cityName: '武汉', + keyword: 'WUHAN武汉', + }, + ], + }, + { + letter: 'X', + data: [ + { + cityCode: '610100', + cityName: '西安', + keyword: 'XIAN西安', + }, + ], + }, + { + letter: 'Z', + data: [ + { + cityCode: '410100', + cityName: '郑州', + keyword: 'ZHENGZHOU郑州', + }, + ], + }, +]; diff --git a/src/constants/group.ts b/src/constants/group.ts index 88436be..5d649bd 100644 --- a/src/constants/group.ts +++ b/src/constants/group.ts @@ -1,3 +1,5 @@ +import { GroupItem } from '@/types/group'; + export enum GroupType { // 所有可加入的群 All = 'ALL', @@ -29,3 +31,30 @@ export const GROUP_STATUS_OPTIONS = [ { label: '全部', value: GroupStatus.All }, { label: '已申请', value: GroupStatus.Requested }, ]; + +export const GROUPS: GroupItem[] = [ + { title: '【杭州】', cityCode: 330100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc223f495e159af95e' }, + { title: '【广州】', cityCode: 440100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb4b88b8abb7a7c8b' }, + { title: '【深圳】', cityCode: 440300, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcfe70d8736e14bb64' }, + { title: '【北京】', cityCode: 110100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb119c94575e91262' }, + { title: '【上海】', cityCode: 310100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4189e68429cf07f8' }, + { title: '【郑州】', cityCode: 410100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd1c53b7bf8ecdb97' }, + { title: '【长沙】', cityCode: 430100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc76be8f2b3f8aa437' }, + { title: '【成都】', cityCode: 510100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcf75cefbdc62946fa' }, + { title: '【重庆】', cityCode: 500100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd7008f747d545f83' }, + { title: '【武汉】', cityCode: 420100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc047c94f8c709b395' }, + { title: '【厦门】', cityCode: 350200, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc2007a895cb48464b' }, + { title: '【西安】', cityCode: 610100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc34768971b7354220' }, + { title: '【合肥】', cityCode: 340100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc41c9785cc2035277' }, + { title: '【南京】', cityCode: 320100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcc6dc8d0a9692b70e' }, + { title: '【青岛】', cityCode: 370200, serviceUrl: 'https://work.weixin.qq.com/kfid/kfce8d7a68190f6a1d2' }, + { title: '【佛山】', cityCode: 440600, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcfac1132df386fac8' }, + { title: '【东莞】', cityCode: 441900, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb2b0e39026f7dddc' }, + { title: '【苏州】', cityCode: 320500, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4642f90a6e3528ff' }, + { title: '【福州】', cityCode: 350100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc126483dedadde82b' }, + { title: '【泉州】', cityCode: 350500, serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4c8c42b1a9337aaf' }, + { title: '【温州】', cityCode: 330300, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb0ea5f197a18b335' }, + { title: '【天津】', cityCode: 120100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcda46c23dade6f6a3' }, + { title: '【昆明】', cityCode: 530100, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcf2aebcbf3d46d9cd' }, + { title: '【全国】', cityCode: 440300, serviceUrl: 'https://work.weixin.qq.com/kfid/kfcc60ac7b6420787a8' }, +]; diff --git a/src/fragments/profile/intention/index.tsx b/src/fragments/profile/intention/index.tsx index d80ef3a..3e21d98 100644 --- a/src/fragments/profile/intention/index.tsx +++ b/src/fragments/profile/intention/index.tsx @@ -12,8 +12,8 @@ import { EmployType, EMPLOY_TYPE_TITLE_MAP, FULL_PRICE_OPTIONS, PART_PRICE_OPTIO import { SalaryRange } from '@/types/job'; import { MaterialProfile } from '@/types/material'; import { logWithPrefix } from '@/utils/common'; -import { isFullTimePriceRequired, isPartTimePriceRequired } from '@/utils/job' -import { getCurrentCity } from '@/utils/location'; +import { isFullTimePriceRequired, isPartTimePriceRequired } from '@/utils/job'; +import { getCurrentCityCode } from '@/utils/location'; import { navigateTo } from '@/utils/route'; import './index.less'; @@ -76,9 +76,9 @@ function ProfileIntentionFragment(props: IProps, ref) { ); const handleClickAddCity = useCallback(() => { - const currentCity = getCurrentCity(); + const currentCityCode = getCurrentCityCode(); realtimeLogger.info('handleClickAddCity', OpenSource.AddIndentCity); - navigateTo(PageUrl.CitySearchProfile, { city: currentCity, source: OpenSource.AddIndentCity }); + navigateTo(PageUrl.CitySearchProfile, { city: currentCityCode, source: OpenSource.AddIndentCity }); }, []); const handleSelectCity = useCallback( @@ -98,10 +98,10 @@ function ProfileIntentionFragment(props: IProps, ref) { const handleEmployTypeChange = useCallback((value: EmployType) => { setEmployType(value); if (value === EmployType.Full) { - setPartSalary({ minSalary: 0, maxSalary: 0 }) + setPartSalary({ minSalary: 0, maxSalary: 0 }); } if (value === EmployType.Part) { - setFullSalary({ minSalary: 0, maxSalary: 0 }) + setFullSalary({ minSalary: 0, maxSalary: 0 }); } }, []); @@ -173,24 +173,26 @@ function ProfileIntentionFragment(props: IProps, ref) { - {isFullTimePriceRequired(employType) && - ( + {isFullTimePriceRequired(employType) && ( + - )} - {isPartTimePriceRequired(employType) && - ( + + )} + {isPartTimePriceRequired(employType) && ( + - )} + + )} diff --git a/src/hooks/use-config.tsx b/src/hooks/use-config.tsx index 88fa2dd..93b2375 100644 --- a/src/hooks/use-config.tsx +++ b/src/hooks/use-config.tsx @@ -48,7 +48,7 @@ const CompanyTabs: TabItemType[] = [ { type: PageType.BatchPublish, pagePath: PageUrl.UserBatchPublish, - text: '群代发', + text: '代招代发', }, ]; diff --git a/src/pages/group-v2/index.tsx b/src/pages/group-v2/index.tsx index f13ef5d..704231d 100644 --- a/src/pages/group-v2/index.tsx +++ b/src/pages/group-v2/index.tsx @@ -7,8 +7,10 @@ import { useCallback } from 'react'; import HomePage from '@/components/home-page'; import LoginButton from '@/components/login-button'; import { APP_TAB_BAR_ID } from '@/constants/app'; +import { GROUPS } from '@/constants/group'; import useInviteCode from '@/hooks/use-invite-code'; import useListHeight, { IUseListHeightProps } from '@/hooks/use-list-height'; +import { GroupItem } from '@/types/group'; import { openCustomerServiceChat } from '@/utils/common'; import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner'; import { getPageQuery } from '@/utils/route'; @@ -16,11 +18,6 @@ import { getCommonShareMessage } from '@/utils/share'; import './index.less'; -interface GroupItem { - title: string; - serviceUrl: string; -} - const PREFIX = 'group-v2-page'; const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`; const CALC_LIST_PROPS: IUseListHeightProps = { @@ -30,32 +27,6 @@ const CALC_LIST_PROPS: IUseListHeightProps = { return diffRect.top - rect.top; }, }; -const GROUPS: GroupItem[] = [ - { title: '【杭州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc223f495e159af95e' }, - { title: '【广州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb4b88b8abb7a7c8b' }, - { title: '【深圳】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcfe70d8736e14bb64' }, - { title: '【北京】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb119c94575e91262' }, - { title: '【上海】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4189e68429cf07f8' }, - { title: '【郑州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd1c53b7bf8ecdb97' }, - { title: '【长沙】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc76be8f2b3f8aa437' }, - { title: '【成都】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcf75cefbdc62946fa' }, - { title: '【重庆】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcd7008f747d545f83' }, - { title: '【武汉】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc047c94f8c709b395' }, - { title: '【厦门】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc2007a895cb48464b' }, - { title: '【西安】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc34768971b7354220' }, - { title: '【合肥】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc41c9785cc2035277' }, - { title: '【南京】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcc6dc8d0a9692b70e' }, - { title: '【青岛】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfce8d7a68190f6a1d2' }, - { title: '【佛山】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcfac1132df386fac8' }, - { title: '【东莞】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb2b0e39026f7dddc' }, - { title: '【苏州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4642f90a6e3528ff' }, - { title: '【福州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc126483dedadde82b' }, - { title: '【泉州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfc4c8c42b1a9337aaf' }, - { title: '【温州】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcb0ea5f197a18b335' }, - { title: '【天津】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcda46c23dade6f6a3' }, - { title: '【昆明】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcf2aebcbf3d46d9cd' }, - { title: '【全国】', serviceUrl: 'https://work.weixin.qq.com/kfid/kfcc60ac7b6420787a8' }, -]; export default function GroupV2() { const listHeight = useListHeight(CALC_LIST_PROPS); diff --git a/src/pages/search-city-profile/index.less b/src/pages/search-city-profile/index.less index ea36334..bb37cd3 100644 --- a/src/pages/search-city-profile/index.less +++ b/src/pages/search-city-profile/index.less @@ -1,123 +1,4 @@ @import '@/styles/variables.less'; .search-city-profile { - background: #FFF; - - &__position-title { - font-size: 24px; - color: @blColorG1; - padding: 0 24px; - margin-top: 18px; - } - - &__position-city { - font-size: 30px; - font-weight: bold; - color: @blColor; - padding: 0 24px; - margin-top: 18px; - } - - &__hot-city-title { - height: 48px; - font-size: 24px; - line-height: 48px; - padding: 0 24px; - color: #999; - background: #f2f5f7; - margin-top: 18px; - } - - &__hot-city-container { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-content: space-between; - width: 630px; - padding: 12px 90px 26px 30px; - background: #FFFFFF; - } - - &__hot-city-item { - width: 140px; - height: 58px; - font-size: 28px; - line-height: 58px; - text-align: center; - border-radius: 58px; - border: 2px solid @blColorG1; - margin-top: 18px; - } - - &__indexes-list { - width: 100%; - /* 兼容 iOS < 11.2 */ - padding-bottom: constant(safe-area-inset-bottom); - /* 兼容 iOS >= 11.2 */ - padding-bottom: env(safe-area-inset-bottom); - } - - &__indexes-fragment {} - - &__indexes-anchor { - height: 48px; - font-size: 24px; - line-height: 48px; - padding: 0 24px; - color: @blColorG1; - background: #f2f5f7; - } - - &__indexes-cell { - position: relative; - font-size: 28px; - padding: 30px 24px; - color: @blColor; - - &::after { - content: ''; - position: absolute; - border-bottom: 1rpx solid #eaeef1; - transform: scaleY(0.5); - bottom: 0; - right: 0; - left: 24px; - } - } - - &__indexes-bar { - width: 44rpx; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - position: fixed; - right: 10px; - } - - &__indexes-bar-item { - font-size: 22px; - color: @blColor; - white-space: nowrap; - display: flex; - align-items: center; - justify-content: center; - } - - &__indexes-index-alert { - position: absolute; - z-index: 20; - width: 160px; - height: 160px; - left: 50%; - top: 50%; - margin-left: -80px; - margin-top: -80px; - border-radius: 80px; - text-align: center; - line-height: 160px; - font-size: 70px; - color: #FFFFFF; - background-color: rgba(0, 0, 0, 0.5); - } } diff --git a/src/pages/search-city-profile/index.tsx b/src/pages/search-city-profile/index.tsx index fff0b3f..fd525fc 100644 --- a/src/pages/search-city-profile/index.tsx +++ b/src/pages/search-city-profile/index.tsx @@ -1,130 +1,29 @@ -import { BaseEventOrig, InputProps, ScrollView } from '@tarojs/components'; import Taro, { useLoad } from '@tarojs/taro'; -import { Search } from '@taroify/core'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; +import SearchCity from '@/components/search-city'; import { EventName, OpenSource } from '@/constants/app'; -import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST } from '@/constants/city'; import { logWithPrefix } from '@/utils/common'; import { getPageQuery, navigateBack } from '@/utils/route'; - import './index.less'; -interface Item { - cityCode: number | string; - cityName: string; - keyword: string; -} - const PREFIX = 'search-city-profile'; -const HOT_CITY = [ - { cityCode: 110100, cityName: '北京' }, - { cityCode: 310100, cityName: '上海' }, - { cityCode: 440100, cityName: '广州' }, - { cityCode: 440300, cityName: '深圳' }, - { cityCode: 330100, cityName: '杭州' }, - { cityCode: 430100, cityName: '长沙' }, - { cityCode: 420100, cityName: '武汉' }, - { cityCode: 350200, cityName: '厦门' }, - { cityCode: 610100, cityName: '西安' }, - { cityCode: 410100, cityName: '郑州' }, - { cityCode: 510100, cityName: '成都' }, - { cityCode: 340100, cityName: '合肥' }, -]; -const OFFSET_INDEX_SIZE = 2; + const log = logWithPrefix(PREFIX); const realtimeLogger = Taro.getRealtimeLogManager(); realtimeLogger.tag(PREFIX); -const useHeight = () => { - const [winHeight, setWinHeight] = useState(0); - const [indexItemHeight, setIndexItemHeight] = useState(0); - useEffect(() => { - const windowInfo = Taro.getWindowInfo(); - const windowHeight = windowInfo.windowHeight; - setWinHeight(windowHeight); - // 上下预留两个选项高度的空白 - setIndexItemHeight(Math.floor(windowHeight / (26 + OFFSET_INDEX_SIZE * 2))); - }, []); - - return [winHeight, indexItemHeight]; -}; - -export default function SearchCity() { - const [winHeight, indexItemHeight] = useHeight(); +export default function SearchCityProfilePage() { const [currentCity, setCurrentCity] = useState(''); - const [touchAnchor, setTouchAnchor] = useState(); - const [touchMoving, setTouchMoving] = useState(false); - const [searchResult, setSearchResult] = useState([]); const openSourceRef = useRef(OpenSource.None); - const showSearchList = searchResult.length > 0; - const handleSearchChange = useCallback((event: BaseEventOrig) => { - const value = event.detail.value; - log('handleSearchChange', value); - if (!value) { - setSearchResult([]); - return; - } - const result: Item[] = []; - CITY_INDEXES_LIST.forEach(obj => { - obj.data.forEach(city => { - if (city.keyword.includes(value.toLocaleUpperCase())) { - result.push({ ...city }); - } - }); - }); - setSearchResult(result); - }, []); - - const handleSelectCity = useCallback((e: React.MouseEvent) => { - const cityCode = e.currentTarget.dataset.code; + const handleSelectCity = useCallback(cityCode => { realtimeLogger.info('handleSelectCity openSource', openSourceRef.current); Taro.eventCenter.trigger(EventName.SELECT_CITY, { openSource: openSourceRef.current, cityCode: String(cityCode) }); navigateBack(1); }, []); - const handleTouchStart = useCallback( - (e: React.TouchEvent) => { - const pageY = e.touches[0].pageY; - const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; - if (index < 0 || index >= CITY_INDEXES_LIST.length) { - return; - } - const item = CITY_INDEXES_LIST[index]; - if (item) { - setTouchMoving(true); - setTouchAnchor(item.letter); - } - }, - [indexItemHeight] - ); - - const handleTouchMove = useCallback( - (e: React.TouchEvent) => { - const pageY = e.touches[0].pageY; - const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; - if (index < 0 || index >= CITY_INDEXES_LIST.length) { - return; - } - const item = CITY_INDEXES_LIST[index]; - item && setTouchAnchor(item.letter); - }, - [indexItemHeight] - ); - - const handleTouchEnd = useCallback((e: React.TouchEvent) => { - e.stopPropagation(); - setTouchMoving(false); - log('touch end'); - }, []); - - const handleClickAnchor = useCallback((anchor: string) => { - setTouchAnchor(anchor); - log('click anchor', anchor); - }, []); - useLoad(() => { const query = getPageQuery<{ city: string; source: OpenSource }>(); log('query', query); @@ -139,94 +38,7 @@ export default function SearchCity() { return (
- - - {showSearchList && ( -
- {searchResult.map(city => ( -
- {city.cityName} -
- ))} -
- )} - {!showSearchList && ( -
-
当前城市
-
{CITY_CODE_TO_NAME_MAP.get(currentCity)}
-
热门城市
-
- {HOT_CITY.map(city => ( -
- {city.cityName} -
- ))} -
-
- {CITY_INDEXES_LIST.map(item => { - return ( -
-
- {item.letter} -
- {item.data.map(city => ( -
- {city.cityName} -
- ))} -
- ); - })} -
-
- )} -
-
- {!showSearchList && ( -
- {CITY_INDEXES_LIST.map(item => { - return ( -
handleClickAnchor(item.letter)} - > - {item.letter} -
- ); - })} -
- )} - {touchAnchor && touchMoving &&
{touchAnchor}
} -
+
); } diff --git a/src/pages/search-city/index.less b/src/pages/search-city/index.less index 537c4bb..015f9d7 100644 --- a/src/pages/search-city/index.less +++ b/src/pages/search-city/index.less @@ -1,123 +1,4 @@ @import '@/styles/variables.less'; -.search-city { - background: #FFF; - - &__position-title { - font-size: 24px; - color: @blColorG1; - padding: 0 24px; - margin-top: 18px; - } - - &__position-city { - font-size: 30px; - font-weight: bold; - color: @blColor; - padding: 0 24px; - margin-top: 18px; - } - - &__hot-city-title { - height: 48px; - font-size: 24px; - line-height: 48px; - padding: 0 24px; - color: #999; - background: #f2f5f7; - margin-top: 18px; - } - - &__hot-city-container { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - align-content: space-between; - width: 630px; - padding: 12px 90px 26px 30px; - background: #FFFFFF; - } - - &__hot-city-item { - width: 140px; - height: 58px; - font-size: 28px; - line-height: 58px; - text-align: center; - border-radius: 58px; - border: 2px solid @blColorG1; - margin-top: 18px; - } - - &__indexes-list { - width: 100%; - /* 兼容 iOS < 11.2 */ - padding-bottom: constant(safe-area-inset-bottom); - /* 兼容 iOS >= 11.2 */ - padding-bottom: env(safe-area-inset-bottom); - } - - &__indexes-fragment {} - - &__indexes-anchor { - height: 48px; - font-size: 24px; - line-height: 48px; - padding: 0 24px; - color: @blColorG1; - background: #f2f5f7; - } - - &__indexes-cell { - position: relative; - font-size: 28px; - padding: 30px 24px; - color: @blColor; - - &::after { - content: ''; - position: absolute; - border-bottom: 1rpx solid #eaeef1; - transform: scaleY(0.5); - bottom: 0; - right: 0; - left: 24px; - } - } - - &__indexes-bar { - width: 44rpx; - display: flex; - flex-direction: column; - align-items: center; - justify-content: flex-start; - position: fixed; - right: 10px; - } - - &__indexes-bar-item { - font-size: 22px; - color: @blColor; - white-space: nowrap; - display: flex; - align-items: center; - justify-content: center; - } - - &__indexes-index-alert { - position: absolute; - z-index: 20; - width: 160px; - height: 160px; - left: 50%; - top: 50%; - margin-left: -80px; - margin-top: -80px; - border-radius: 80px; - text-align: center; - line-height: 160px; - font-size: 70px; - color: #FFFFFF; - background-color: rgba(0, 0, 0, 0.5); - } -} \ No newline at end of file +.page.search-city { +} diff --git a/src/pages/search-city/index.tsx b/src/pages/search-city/index.tsx index 2c0a705..907dd73 100644 --- a/src/pages/search-city/index.tsx +++ b/src/pages/search-city/index.tsx @@ -1,129 +1,29 @@ -import { BaseEventOrig, InputProps, ScrollView } from '@tarojs/components'; import Taro, { useLoad } from '@tarojs/taro'; -import { Search } from '@taroify/core'; -import { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useRef, useState } from 'react'; +import SearchCity from '@/components/search-city'; import { EventName, OpenSource } from '@/constants/app'; -import { CITY_CODE_TO_NAME_MAP, CITY_INDEXES_LIST } from '@/constants/city'; import { logWithPrefix } from '@/utils/common'; import { getPageQuery, navigateBack } from '@/utils/route'; import './index.less'; -interface Item { - cityCode: number | string; - cityName: string; - keyword: string; -} +const PREFIX = 'page-search-city'; -const PREFIX = 'search-city'; -const HOT_CITY = [ - { cityCode: 110100, cityName: '北京' }, - { cityCode: 310100, cityName: '上海' }, - { cityCode: 440100, cityName: '广州' }, - { cityCode: 440300, cityName: '深圳' }, - { cityCode: 330100, cityName: '杭州' }, - { cityCode: 430100, cityName: '长沙' }, - { cityCode: 420100, cityName: '武汉' }, - { cityCode: 350200, cityName: '厦门' }, - { cityCode: 610100, cityName: '西安' }, - { cityCode: 410100, cityName: '郑州' }, - { cityCode: 510100, cityName: '成都' }, - { cityCode: 340100, cityName: '合肥' }, -]; -const OFFSET_INDEX_SIZE = 2; const log = logWithPrefix(PREFIX); const realtimeLogger = Taro.getRealtimeLogManager(); realtimeLogger.tag(PREFIX); -const useHeight = () => { - const [winHeight, setWinHeight] = useState(0); - const [indexItemHeight, setIndexItemHeight] = useState(0); - useEffect(() => { - const windowInfo = Taro.getWindowInfo(); - const windowHeight = windowInfo.windowHeight; - setWinHeight(windowHeight); - // 上下预留两个选项高度的空白 - setIndexItemHeight(Math.floor(windowHeight / (26 + OFFSET_INDEX_SIZE * 2))); - }, []); - - return [winHeight, indexItemHeight]; -}; - -export default function SearchCity() { - const [winHeight, indexItemHeight] = useHeight(); +export default function SearchCityPage() { const [currentCity, setCurrentCity] = useState(''); - const [touchAnchor, setTouchAnchor] = useState(); - const [touchMoving, setTouchMoving] = useState(false); - const [searchResult, setSearchResult] = useState([]); const openSourceRef = useRef(OpenSource.None); - const showSearchList = searchResult.length > 0; - const handleSearchChange = useCallback((event: BaseEventOrig) => { - const value = event.detail.value; - log('handleSearchChange', value); - if (!value) { - setSearchResult([]); - return; - } - const result: Item[] = []; - CITY_INDEXES_LIST.forEach(obj => { - obj.data.forEach(city => { - if (city.keyword.includes(value.toLocaleUpperCase())) { - result.push({ ...city }); - } - }); - }); - setSearchResult(result); - }, []); - - const handleSelectCity = useCallback((e: React.MouseEvent) => { - const cityCode = e.currentTarget.dataset.code; + const handleSelectCity = useCallback(cityCode => { Taro.eventCenter.trigger(EventName.SELECT_CITY, { openSource: openSourceRef.current, cityCode: String(cityCode) }); navigateBack(1); }, []); - const handleTouchStart = useCallback( - (e: React.TouchEvent) => { - const pageY = e.touches[0].pageY; - const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; - if (index < 0 || index >= CITY_INDEXES_LIST.length) { - return; - } - const item = CITY_INDEXES_LIST[index]; - if (item) { - setTouchMoving(true); - setTouchAnchor(item.letter); - } - }, - [indexItemHeight] - ); - - const handleTouchMove = useCallback( - (e: React.TouchEvent) => { - const pageY = e.touches[0].pageY; - const index = Math.floor(pageY / indexItemHeight) - OFFSET_INDEX_SIZE; - if (index < 0 || index >= CITY_INDEXES_LIST.length) { - return; - } - const item = CITY_INDEXES_LIST[index]; - item && setTouchAnchor(item.letter); - }, - [indexItemHeight] - ); - - const handleTouchEnd = useCallback((e: React.TouchEvent) => { - e.stopPropagation(); - setTouchMoving(false); - log('touch end'); - }, []); - - const handleClickAnchor = useCallback((anchor: string) => { - setTouchAnchor(anchor); - log('click anchor', anchor); - }, []); - useLoad(() => { const query = getPageQuery<{ city: string; source: OpenSource }>(); log('query', query); @@ -138,94 +38,7 @@ export default function SearchCity() { return (
- - - {showSearchList && ( -
- {searchResult.map(city => ( -
- {city.cityName} -
- ))} -
- )} - {!showSearchList && ( -
-
当前城市
-
{CITY_CODE_TO_NAME_MAP.get(currentCity)}
-
热门城市
-
- {HOT_CITY.map(city => ( -
- {city.cityName} -
- ))} -
-
- {CITY_INDEXES_LIST.map(item => { - return ( -
-
- {item.letter} -
- {item.data.map(city => ( -
- {city.cityName} -
- ))} -
- ); - })} -
-
- )} -
-
- {!showSearchList && ( -
- {CITY_INDEXES_LIST.map(item => { - return ( -
handleClickAnchor(item.letter)} - > - {item.letter} -
- ); - })} -
- )} - {touchAnchor && touchMoving &&
{touchAnchor}
} -
+
); } diff --git a/src/pages/user-batch-publish/index.less b/src/pages/user-batch-publish/index.less index f395326..3aabde1 100644 --- a/src/pages/user-batch-publish/index.less +++ b/src/pages/user-batch-publish/index.less @@ -1,90 +1,64 @@ @import '@/styles/common.less'; @import '@/styles/variables.less'; -.page-user-batch-publish { - padding: 24px; +.page-biz-service { padding-bottom: 200px; - &__header-image { - width: 100%; - height: 120px; - margin-top: 24px; - } + &__tabs { + --tabs-active-color: @blHighlightColor; + --tabs-nav-background-color: #fff; + --tabs-wrap-height: 98px; - &__title { - font-size: 32px; - line-height: 48px; - font-weight: 500; - color: @blColor; - margin-top: 24px; + > .taroify-tabs__wrap { + position: fixed; + width: 100vw; + top: 0; + left: 0; + z-index: 2; + } - &:first-child { - margin-top: 0; + > .taroify-tabs__content { + padding-top: var(--tabs-wrap-height); } } - &__cell { - height: 100px; - padding-left: 32px; - padding-right: 32px; - border-radius: 16px; - margin-top: 24px; - } - - &__cost-describe { - height: 100px; - padding: 0 32px; - border-radius: 16px; - .flex-row(); - justify-content: space-between; - background: #FFFFFF; - margin-top: 24px; - - &__price { - font-size: 48px; - line-height: 48px; + &__recruitment { + padding: 24px; + &-card { + background: #fff; + padding: 32px; + border-radius: 24px; + } + &-h5 { font-weight: 500; - color: @blHighlightColor; - } - - &__original_price { - flex: 1; font-size: 32px; - line-height: 34px; - font-weight: 400; - color: @blColorG1; - margin-left: 16px; - text-decoration: line-through; - } - } + line-height: 40px; + color: #1d2129; + padding-bottom: 16px; + padding-top: 40px; - &__illustrate { - padding: 24px 32px; - margin-top: 24px; - font-size: 28px; - line-height: 48px; - font-weight: 400; - color: @blColorG2; - background: #FFFFFF; - border-radius: 16px; - - &__describe { - .flex-row(); - font-size: 28px; - line-height: 48px; - font-weight: 400; - color: @blColorG2; - margin-top: 8px; - - &__view { - color: @blHighlightColor; - margin-left: 4px; + &:first-child { + padding-top: 0; } } - } - &__buy-button { - .button(@width: 100%; @height: 80px; @fontSize: 32px); - margin-top: 40px; + &-body { + font-size: 28px; + line-height: 40px; + + & + & { + padding-top: 20px; + } + } + + &-btn-group { + .flex-row(); + justify-content: center; + margin-top: 40px; + } + + &-btn { + .button(@height: 72px; @width: 384px; @fontSize: 28px; @fontWeight: 400; @borderRadius: 44px; @highlight: 0); + } } -} \ No newline at end of file +} diff --git a/src/pages/user-batch-publish/index.tsx b/src/pages/user-batch-publish/index.tsx index 3e6920d..0c56a2d 100644 --- a/src/pages/user-batch-publish/index.tsx +++ b/src/pages/user-batch-publish/index.tsx @@ -1,197 +1,66 @@ -import { Button, Image, Text } from '@tarojs/components'; -import Taro, { useLoad } from '@tarojs/taro'; - -import { Cell } from '@taroify/core'; -import { useCallback, useState } from 'react'; +import { useShareAppMessage } from '@tarojs/taro'; +import { Button, Tabs } from '@taroify/core'; +import { useCallback } from 'react'; import HomePage from '@/components/home-page'; -import PageLoading from '@/components/page-loading'; -import { PublishJobQrCodeDialog } from '@/components/product-dialog/publish-job'; -import SafeBottomPadding from '@/components/safe-bottom-padding'; -import { ISelectOption, PopupSelect } from '@/components/select'; -import { PageUrl } from '@/constants/app'; -import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product'; -import { BatchPublishGroup } from '@/types/group'; -import { logWithPrefix } from '@/utils/common'; -import { - getOrderPrice, - isCancelPay, - requestAllBuyProduct, - requestCreatePayInfo, - requestOrderInfo, - requestPayment, -} from '@/utils/product'; -import { navigateTo } from '@/utils/route'; -import Toast from '@/utils/toast'; - +import SearchCity from '@/components/search-city'; +import UserBatchPublish from '@/components/user-batch-publish'; +import { GROUPS } from '@/constants/group'; +import { openCustomerServiceChat } from '@/utils/common'; +import { getCurrentCityCode } from '@/utils/location'; +import { getCommonShareMessage } from '@/utils/share'; import './index.less'; -interface CityValue extends BatchPublishGroup { - cityName: string; -} +const PREFIX = 'page-biz-service'; -interface CityOption extends ISelectOption { - value: CityValue; -} - -const PREFIX = 'page-user-batch-publish'; -const log = logWithPrefix(PREFIX); -const SERVICE_ILLUSTRATE = `群发次数:每日一次,连发3天 -群发内容:仅限主播招聘通告,违规内容不发 -联系方法:通告中留通告主联系方式,主播直接联系`; -const cityValues: CityValue[] = [ - { cityCode: '440100', cityName: '广州', count: 300 }, - { cityCode: '440300', cityName: '深圳', count: 100 }, - { cityCode: '330100', cityName: '杭州', count: 300 }, - { cityCode: '110100', cityName: '北京', count: 100 }, - { cityCode: '510100', cityName: '成都', count: 50 }, - { cityCode: '430100', cityName: '长沙', count: 50 }, - { cityCode: '350200', cityName: '厦门', count: 50 }, - { cityCode: '310100', cityName: '上海', count: 100 }, - { cityCode: '420100', cityName: '武汉', count: 50 }, - { cityCode: '610100', cityName: '西安', count: 50 }, - { cityCode: '410100', cityName: '郑州', count: 100 }, -].sort((a, b) => b.count - a.count); -const MIN_GROUP_SIZE = 20; -const GROUP_OPTIONS = [ - { value: MIN_GROUP_SIZE, productSpecId: ProductSpecId.GroupBatchPublish20, label: '20', price: 18 }, - { value: 50, productSpecId: ProductSpecId.GroupBatchPublish50, label: '50', price: 40 }, - { value: 100, productSpecId: ProductSpecId.GroupBatchPublish100, label: '100', price: 68 }, - { value: 300, productSpecId: ProductSpecId.GroupBatchPublish300, label: '300', price: 128 }, - { value: 500, productSpecId: ProductSpecId.GroupBatchPublish500, label: '500', price: 188 }, - { value: 1000, productSpecId: ProductSpecId.GroupBatchPublish1000, label: '1000', price: 288 }, -]; - -const calcPrice = (city: CityValue | null) => { - if (!city) { - return {}; - } - const { count } = city; - const originalPrice = count * 1; - const price = GROUP_OPTIONS.find(o => o.value === count)?.price || 18; - const productSpecId = GROUP_OPTIONS.find(o => o.value === count)?.productSpecId || ProductSpecId.GroupBatchPublish20; - return { price, originalPrice, productSpecId }; -}; - -export default function UserBatchPublish() { - const [loading, setLoading] = useState(true); - const [showCitySelect, setShowCitySelect] = useState(false); - const [showQrCode, setShowQrCode] = useState(false); - const [city, setCity] = useState(null); - const [cityOptions, setCityOptions] = useState([]); - const { price, originalPrice, productSpecId } = calcPrice(city); - - const handleClickCity = useCallback(() => setShowCitySelect(true), []); - - const handleSelectCity = useCallback(value => { - setCity(value); - setShowCitySelect(false); +export default function BizService() { + const handleOpenService = useCallback(() => { + openCustomerServiceChat('https://work.weixin.qq.com/kfid/kfcd60708731367168d'); }, []); - - const handleClickViewGroup = useCallback(() => navigateTo(PageUrl.GroupList, { city: city?.cityCode }), [city]); - - const handleClickBuy = useCallback(async () => { - // if (1 < 2) { - // await new Promise(r => setTimeout(r, 3000)); - // setShowQrCode(true); - // return; - // } - if (!price || !productSpecId) { - return; + const handleSelectCity = useCallback(cityCode => { + const group = GROUPS.find(g => String(g.cityCode) === cityCode); + if (group) { + openCustomerServiceChat(group.serviceUrl); } - try { - Taro.showLoading(); - const allowBuy = await requestAllBuyProduct(ProductType.GroupBatchPublish); - if (!allowBuy) { - Taro.hideLoading(); - Toast.info('您最近已购买过,可直接联系客服'); - setShowQrCode(true); - return; - } - const { payOrderNo, createPayInfo } = await requestCreatePayInfo({ - type: OrderType.GroupBatchPublish, - amt: getOrderPrice(price), - // amt: 1, - productCode: ProductType.GroupBatchPublish, - productSpecId: productSpecId, - }); - log('handleBuy payInfo', payOrderNo, createPayInfo); - await requestPayment({ - timeStamp: createPayInfo.timeStamp, - nonceStr: createPayInfo.nonceStr, - package: createPayInfo.packageVal, - signType: createPayInfo.signType, - paySign: createPayInfo.paySign, - }); - const { status } = await requestOrderInfo({ payOrderNo }); - log('handleBuy orderInfo', status); - if (status !== OrderStatus.Success) { - throw new Error('order status error'); - } - Taro.hideLoading(); - setShowQrCode(true); - } catch (e) { - Taro.hideLoading(); - Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试'); - log('handleBuy error', e); - } - }, [price, productSpecId]); - - useLoad(async () => { - try { - const cOptions: CityOption[] = cityValues.map(value => ({ value, label: value.cityName })); - const initCity = cOptions[0].value; - - setLoading(false); - setCity(initCity); - setCityOptions(cOptions); - log('init data done', cOptions); - } catch (e) { - Toast.error('加载失败请重试'); - } - }); - - if (loading) { - return ; - } + }, []); + useShareAppMessage(() => getCommonShareMessage()); return (
- -
请选择城市
- -
可购买群数
- -
服务费用
-
-
{`${price}元`}
-
{`原价:${originalPrice}元`}
-
-
服务说明
-
- {SERVICE_ILLUSTRATE} -
-
附:
-
- 播络合作群列表 + + + + + + + + +
+
+
服务城市
+
江、沪、皖-上海、南京、合肥
+
粤、闽-广州、深圳、佛山、厦门、福州、泉州
+
京、鲁-北京、青岛
+
鄂、豫、湘、陕-长沙、武汉、郑州、西安
+
川、渝、云-成都、重庆、昆明
+
服务方式及收费标准
+
服务方式:提供录屏和基本资料供挑选,挑中安排面试
+
收费标准:安排一场面试200元
+
收费方式:预付费,按安排面试场数扣费
+
服务能力
+
+ 我们在每个城市均有数量众多的主播群,少则几十个,多则上千个,有各种类型和层次的带货主播资源 +
+
+ +
+
-
-
- - -
- setShowCitySelect(false)} - /> - setShowQrCode(false)} open={showQrCode} /> -
+ +
); diff --git a/src/types/group.ts b/src/types/group.ts index 4bf84f7..e89ebf6 100644 --- a/src/types/group.ts +++ b/src/types/group.ts @@ -49,3 +49,8 @@ export interface GetGroupsResponse extends IPaginationResponse { export interface GetGroupDetailsRequest { blGroupId: string; } +export interface GroupItem { + title: string; + cityCode: number; + serviceUrl: string; +} diff --git a/src/utils/location.ts b/src/utils/location.ts index 97a3c37..35e2f8d 100644 --- a/src/utils/location.ts +++ b/src/utils/location.ts @@ -33,9 +33,12 @@ export const calcDistance = (distance: number, fractionDigits = 2) => { } return '999km'; }; +export const getCurrentCityCode = () => { + return selectLocation(store.getState()).cityCode; +}; export const getCurrentCity = () => { - const cityCode = selectLocation(store.getState()).cityCode; + const cityCode = getCurrentCityCode(); return CITY_CODE_TO_NAME_MAP.get(cityCode) || ''; };