From 4cc4aaa70719c7474b243ade18f1deb095beb899 Mon Sep 17 00:00:00 2001 From: chashaobao Date: Fri, 30 Jan 2026 21:47:50 +0800 Subject: [PATCH] feat: --- src/components/job-manage-card/index.tsx | 10 ++- src/components/job-manage-list/index.less | 28 ++++++- src/components/job-manage-list/index.tsx | 13 ++- src/components/prejob-popup/index.tsx | 23 +++++- src/components/user-batch-publish/index.tsx | 91 +++++++-------------- src/constants/product.ts | 3 + src/fragments/user/company/index.less | 19 +++++ src/fragments/user/company/index.tsx | 20 ++++- src/hooks/use-config.tsx | 2 +- src/hooks/use-publish-job.ts | 10 +-- src/pages/certification-manage/index.less | 24 +----- src/pages/certification-manage/index.tsx | 34 +------- src/pages/group-detail/index.tsx | 7 +- src/pages/invite-operations/index.tsx | 29 +++++-- src/pages/job-detail/index.tsx | 18 +--- src/pages/job-publish/index.tsx | 28 +++++-- src/pages/job/index.tsx | 14 ++-- src/pages/material-view/index.tsx | 19 +++-- src/pages/user-batch-publish/index.tsx | 52 ++++++------ src/types/location.ts | 8 +- 20 files changed, 247 insertions(+), 205 deletions(-) diff --git a/src/components/job-manage-card/index.tsx b/src/components/job-manage-card/index.tsx index b7fa7a7..9c4b6ae 100644 --- a/src/components/job-manage-card/index.tsx +++ b/src/components/job-manage-card/index.tsx @@ -2,11 +2,12 @@ import { Image } from '@tarojs/components'; import { Arrow } from '@taroify/icons'; import classNames from 'classnames'; -import React, { useCallback } from 'react'; +import React, { useCallback, useMemo } from 'react'; -import { cityValues } from '@/components/user-batch-publish'; +// import { cityValues } from '@/components/user-batch-publish'; import { PageUrl } from '@/constants/app'; import { JOB_MANAGE_STATUS_TITLE_MAP, JobManageStatus } from '@/constants/job'; +import useCityOperators from '@/hooks/use-city-operators'; import { JobManageInfo } from '@/types/job'; import { getJobLocation } from '@/utils/job'; import { navigateTo } from '@/utils/route'; @@ -30,6 +31,9 @@ const STATUS_CLASS_MAP = { }; function GoBatchTag({ cityCode, jobId }: { cityCode: string; jobId: JobManageInfo['id'] }) { + const cityOperators = useCityOperators(); + const availableCities = useMemo(() => cityOperators.filter(c => c.sendCount), [cityOperators]); + const handleClick = useCallback( e => { e.preventDefault(); @@ -38,7 +42,7 @@ function GoBatchTag({ cityCode, jobId }: { cityCode: string; jobId: JobManageInf }, [cityCode, jobId] ); - if (!cityValues.find(c => c.cityCode === cityCode)) { + if (!availableCities.find(c => c.cityCode === cityCode)) { return null; } return ( diff --git a/src/components/job-manage-list/index.less b/src/components/job-manage-list/index.less index 1df8cd1..e9261db 100644 --- a/src/components/job-manage-list/index.less +++ b/src/components/job-manage-list/index.less @@ -1,2 +1,28 @@ @import '@/styles/common.less'; -@import '@/styles/variables.less'; \ No newline at end of file +@import '@/styles/variables.less'; + +.job-manage-list { + &__empty-tips { + width: 100%; + height: 100vh; + padding-top: 218px; + box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + position: absolute; + + &__icon { + width: 386px; + height: 278px; + } + + &__describe { + font-size: 28px; + font-weight: 500; + line-height: 40px; + color: @blColor; + margin-top: 50px; + } + } +} diff --git a/src/components/job-manage-list/index.tsx b/src/components/job-manage-list/index.tsx index 1575094..1a7ca5e 100644 --- a/src/components/job-manage-list/index.tsx +++ b/src/components/job-manage-list/index.tsx @@ -1,3 +1,4 @@ +import { Image } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { List, PullRefresh } from '@taroify/core'; @@ -28,7 +29,15 @@ const FIRST_PAGE = 0; const PAGE_SIZE = 40; const PREFIX = 'job-manage-list'; const log = logWithPrefix(PREFIX); - +const EmptyTips = (props: { className?: string; height?: number }) => { + const { className, height } = props; + return ( +
+ +
当前还没有通告
+
+ ); +}; function JobManageList(props: IJobManageListProps) { const { className, listHeight, refreshDisabled, visible = true, status, onListEmpty } = props; const [refreshing, setRefreshing] = useState(false); @@ -151,6 +160,8 @@ function JobManageList(props: IJobManageListProps) { onRefresh={handleRefresh} disabled={refreshDisabled} > + {Boolean(!dataList.length) && } + void; + onRefresh: () => void; + needLogin?: boolean; isCreateResume?: boolean; onConfirm: (type: GET_CONTACT_TYPE) => void; } @@ -27,6 +30,7 @@ const GET_CONTACT_TYPE_OPTIONS = [ title: '创建模卡(免费报单)', desc: '免费报单,优先推荐给企业,机会更多', btnText: '创建', + needLogin: true, }, { type: GET_CONTACT_TYPE.VIP, @@ -51,7 +55,7 @@ const GET_CONTACT_TYPE_OPTIONS = [ }, ]; -export function PrejobPopup({ onCancel, isCreateResume, onConfirm }: IProps) { +export function PrejobPopup({ onCancel, isCreateResume, onConfirm, onRefresh }: IProps) { const [openPopup, setOpenPopup] = useState(true); const [openDialog, setOpenDialog] = useState(false); const [clicked, setClicked] = useState(!!Taro.getStorageSync(CacheKey.JOIN_GROUP_POPUP_CLICKED)); @@ -98,9 +102,20 @@ export function PrejobPopup({ onCancel, isCreateResume, onConfirm }: IProps) {
{option.desc}
- + {option.needLogin ? ( + + {option.btnText} + + ) : ( + + )}
); diff --git a/src/components/user-batch-publish/index.tsx b/src/components/user-batch-publish/index.tsx index eaf5345..b008fb0 100644 --- a/src/components/user-batch-publish/index.tsx +++ b/src/components/user-batch-publish/index.tsx @@ -2,7 +2,7 @@ import { Button } from '@tarojs/components'; import Taro from '@tarojs/taro'; import { Cell, Dialog } from '@taroify/core'; -import { Fragment, useCallback, useEffect, useState } from 'react'; +import { Fragment, useCallback, useEffect, useMemo, useState } from 'react'; import PageLoading from '@/components/page-loading'; import { PublishJobQrCodeDialog } from '@/components/product-dialog/publish-job'; @@ -11,9 +11,10 @@ import SafeBottomPadding from '@/components/safe-bottom-padding'; import { ISelectOption, PopupSelect } from '@/components/select'; import { PageUrl } from '@/constants/app'; import { JobManageStatus } from '@/constants/job'; -import { OrderStatus, OrderType, ProductSpecId, ProductType } from '@/constants/product'; +import { OrderStatus, OrderType, ProductType } from '@/constants/product'; +import useCityOperators from '@/hooks/use-city-operators'; import { usePublishJob } from '@/hooks/use-publish-job'; -import { BatchPublishGroup } from '@/types/group'; +import { CityConfigListItem } from '@/types/location'; import { logWithPrefix } from '@/utils/common'; import { requestJobDetail } from '@/utils/job'; import { @@ -28,65 +29,29 @@ 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; +interface CityOption extends ISelectOption { + value: CityConfigListItem; } const PREFIX = 'user-batch-publish'; const log = logWithPrefix(PREFIX); -export const cityValues: CityValue[] = [ - { cityCode: '440100', cityName: '广州', count: 800 }, - { cityCode: '440300', cityName: '深圳', count: 100 }, - { cityCode: '330100', cityName: '杭州', count: 750 }, - { cityCode: '110100', cityName: '北京', count: 150 }, - { cityCode: '510100', cityName: '成都', count: 100 }, - { cityCode: '500100', cityName: '重庆', count: 50 }, - { cityCode: '430100', cityName: '长沙', count: 50 }, - { cityCode: '350200', cityName: '厦门', count: 50 }, - { cityCode: '310100', cityName: '上海', count: 150 }, - { cityCode: '420100', cityName: '武汉', count: 80 }, - { cityCode: '610100', cityName: '西安', count: 60 }, - { cityCode: '410100', cityName: '郑州', count: 150 }, -].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: 60, productSpecId: ProductSpecId.GroupBatchPublish60, label: '60', price: 48 }, - { value: 80, productSpecId: ProductSpecId.GroupBatchPublish80, label: '80', price: 58 }, - { value: 100, productSpecId: ProductSpecId.GroupBatchPublish100, label: '100', price: 68 }, - { value: 150, productSpecId: ProductSpecId.GroupBatchPublish150, label: '150', price: 98 }, - { value: 300, productSpecId: ProductSpecId.GroupBatchPublish300, label: '300', price: 128 }, - { value: 500, productSpecId: ProductSpecId.GroupBatchPublish500, label: '500', price: 168 }, - { value: 750, productSpecId: ProductSpecId.GroupBatchPublish750, label: '750', price: 188 }, - { value: 800, productSpecId: ProductSpecId.GroupBatchPublish800, label: '800', price: 198 }, - { 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 }; -}; -const cityOptions: CityOption[] = cityValues.map(value => ({ value, label: value.cityName })); export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: string; jobId?: string }) { const [loading, setLoading] = useState(true); const [showQrCode, setShowQrCode] = useState(false); const [selectable, setSelectable] = useState(false); const [showCitySelect, setShowCitySelect] = useState(false); - const [city, setCity] = useState(null); - const { price, originalPrice, productSpecId } = calcPrice(city); + const [city, setCity] = useState(null); const [showPublishJob, setShowPublishJob] = useState(false); + const cityOperators = useCityOperators(); + + const availableCities = useMemo(() => cityOperators.filter(c => c.sendCount), [cityOperators]); + const cityOptions: CityOption[] = useMemo( + () => availableCities.map(value => ({ value, label: value.cityName })), + [availableCities] + ); + const [showBuy, setShowBuy, handlePublishJob] = usePublishJob(jobId); const handleClickCity = useCallback(() => setShowCitySelect(true), []); @@ -102,7 +67,7 @@ export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: strin // setShowQrCode(true); // return; // } - if (!price || !productSpecId) { + if (!city || !city.payPrice || !city.showPrice || !city.sendCount || !city.productSpecId) { return; } try { @@ -127,10 +92,10 @@ export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: strin const { payOrderNo, createPayInfo } = await requestCreatePayInfo({ type: OrderType.GroupBatchPublish, - amt: getOrderPrice(price), + amt: city.payPrice, // amt: 1, productCode: ProductType.GroupBatchPublish, - productSpecId: productSpecId, + productSpecId: city.productSpecId, }); log('handleBuy payInfo', payOrderNo, createPayInfo); await requestPayment({ @@ -152,14 +117,14 @@ export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: strin Toast.error(isCancelPay(e) ? '取消购买' : '购买失败请重试'); log('handleBuy error', e); } - }, [jobId, price, productSpecId]); + }, [cityCode, jobId, city]); useEffect(() => { - // if (!cityCode) { - // return; - // } + if (!availableCities.length) { + return; + } try { - const initCity = cityCode ? cityValues.find(o => o.cityCode === cityCode) : cityValues[0]; + const initCity = cityCode ? availableCities.find(o => o.cityCode === cityCode) : availableCities[0]; setSelectable(!cityCode); @@ -172,7 +137,7 @@ export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: strin } catch (e) { Toast.error('加载失败请重试'); } - }, [cityCode]); + }, [availableCities, cityCode]); if (loading) { return ; @@ -203,11 +168,13 @@ export default function UserBatchPublish({ cityCode, jobId }: { cityCode?: strin 查看该城市合作群列表
可购买群数
- +
服务费用
-
{`${price}元`}
-
{`原价:${originalPrice}元`}
+
{`${city?.showPrice}元`}
+
{`原价:${city?.originalPrice || city?.sendCount}元`}
diff --git a/src/pages/job-detail/index.tsx b/src/pages/job-detail/index.tsx index 9f2888c..116e5d7 100644 --- a/src/pages/job-detail/index.tsx +++ b/src/pages/job-detail/index.tsx @@ -9,7 +9,6 @@ import CommonDialog from '@/components/common-dialog'; import DevDiv from '@/components/dev-div'; import JobRecommendList from '@/components/job-recommend-list'; import { JoinGroupHint } from '@/components/join-group-hint'; -import LoginButton from '@/components/login-button'; import PageLoading from '@/components/page-loading'; import { PrejobPopup } from '@/components/prejob-popup'; import ProductJobContactDialog from '@/components/product-dialog/job-contact'; @@ -41,7 +40,6 @@ import { getJumpUrl, getPageQuery, navigateTo } from '@/utils/route'; import { getCommonShareMessage } from '@/utils/share'; import { formatDate } from '@/utils/time'; import Toast from '@/utils/toast'; -import { isNeedPhone } from '@/utils/user'; import './index.less'; const PREFIX = 'job-detail'; @@ -74,8 +72,6 @@ const AnchorFooter = (props: { data: JobDetails }) => { const [showMaterialGuide, setShowMaterialGuide] = useState(false); const [productInfo, setProductInfo] = useState(); const [productRecord, setProductRecord] = useState(); - const userInfo = useUserInfo(); - const needPhone = isNeedPhone(userInfo); const getProductRecord = useCallback(async () => { const result = await requestProductUseRecord(ProductType.VIP, { jobId: data.id }); @@ -211,21 +207,14 @@ const AnchorFooter = (props: { data: JobDetails }) => { - +
{showJobContactDialog && ( @@ -242,6 +231,7 @@ const AnchorFooter = (props: { data: JobDetails }) => { isCreateResume={productInfo?.isCreateResume} onCancel={() => setShowMaterialGuide(false)} onConfirm={handleConfirmPrejob} + onRefresh={handleRefresh} /> )} { + console.log('哈哈哈哈触发 refresh job publish list'); Taro.eventCenter.trigger(EventName.COMPANY_JOB_PUBLISH_CHANGED); setTimeout(() => { Taro.eventCenter.trigger(EventName.COMPANY_JOB_PUBLISH_CHANGED); @@ -214,13 +215,13 @@ export default function JobPublish() { createdJobIdRef.current = jobId; refreshJobPublishList(); - if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { - // 去认证 - store.dispatch(cacheJobId(jobId)); - navigateTo(PageUrl.CertificationStart); - Taro.hideLoading(); - return; - } + // if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { + // // 去认证 + // store.dispatch(cacheJobId(jobId)); + // navigateTo(PageUrl.CertificationStart); + // Taro.hideLoading(); + // return; + // } const [time] = await requestProductBalance(ProductType.CompanyPublishJob); if (time <= 0) { @@ -249,10 +250,19 @@ export default function JobPublish() { } finally { Taro.hideLoading(); } - }, [getCreateJobInfo, isUpdate, job, userInfo.bossAuthStatus, refreshJobPublishList]); + }, [getCreateJobInfo, isUpdate, job, refreshJobPublishList]); const handleNext = useCallback(async () => { Taro.showLoading(); + + if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { + // 去认证 + store.dispatch(cacheJobId(createdJobIdRef.current)); + navigateTo(PageUrl.CertificationStart); + Taro.hideLoading(); + return; + } + try { await postPublishJob(createdJobIdRef.current); refreshJobPublishList(); @@ -270,7 +280,7 @@ export default function JobPublish() { } finally { Taro.hideLoading(); } - }, [refreshJobPublishList]); + }, [refreshJobPublishList, userInfo.bossAuthStatus]); const handleClosePublishJob = useCallback(() => { setShowBuy(false); diff --git a/src/pages/job/index.tsx b/src/pages/job/index.tsx index 3d8f97a..a6f9a9d 100644 --- a/src/pages/job/index.tsx +++ b/src/pages/job/index.tsx @@ -19,7 +19,7 @@ import { logWithPrefix } from '@/utils/common'; import { getWxLocation, isNotNeedAuthorizeLocation, requestLocation } from '@/utils/location'; import { requestUnreadMessageCount } from '@/utils/message'; import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner'; -import { getJumpUrl, getPageQuery, navigateTo } from '@/utils/route'; +import { getPageQuery, navigateTo } from '@/utils/route'; import { getCommonShareMessage } from '@/utils/share'; import Toast from '@/utils/toast'; import { getAgreementSigned, setAgreementSigned } from '@/utils/user'; @@ -138,13 +138,11 @@ export default function Job() { }); useShareAppMessage(() => { - if (sortType === SortType.CREATE_TIME) { - return { - title: '这里有今日全城新增通告,快来看看', - path: getJumpUrl(PageUrl.Job, { sortType, c: inviteCode }), - }; - } - return getCommonShareMessage({ inviteCode, path: PageUrl.Job }); + return getCommonShareMessage({ + inviteCode, + path: PageUrl.Job, + params: sortType === SortType.CREATE_TIME ? { sortType } : {}, + }); }); return ( diff --git a/src/pages/material-view/index.tsx b/src/pages/material-view/index.tsx index ae7b82d..20be72a 100644 --- a/src/pages/material-view/index.tsx +++ b/src/pages/material-view/index.tsx @@ -97,11 +97,11 @@ export default function MaterialViewPage() { } const jobDetail = await requestJobDetail(jobId); if (jobDetail.status !== JobManageStatus.Open) { - if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { - store.dispatch(cacheJobId(jobId)); - navigateTo(PageUrl.CertificationStart); - return; - } + // if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { + // store.dispatch(cacheJobId(jobId)); + // navigateTo(PageUrl.CertificationStart); + // return; + // } setShowBuy(true); return; @@ -137,6 +137,13 @@ export default function MaterialViewPage() { }, [profile, jobId]); const handleNext = useCallback(async () => { setShowBuy(false); + + if (userInfo.bossAuthStatus !== CertificationStatusType.Success) { + store.dispatch(cacheJobId(jobId!)); + navigateTo(PageUrl.CertificationStart); + return; + } + try { await postPublishJob(jobId!); await handleClickContact(); @@ -150,7 +157,7 @@ export default function MaterialViewPage() { } collectEvent(CollectEventName.PUBLISH_JOB_FAILED, e); } - }, [handleClickContact, jobId]); + }, [handleClickContact, jobId, userInfo.bossAuthStatus]); const handleClickNoViewTimes = useCallback(() => { setNoTimeDialogVisible(false); navigateBack(); diff --git a/src/pages/user-batch-publish/index.tsx b/src/pages/user-batch-publish/index.tsx index 8c6b6fc..0e11de2 100644 --- a/src/pages/user-batch-publish/index.tsx +++ b/src/pages/user-batch-publish/index.tsx @@ -24,7 +24,7 @@ const COMMENT_IMAGE = 'https://publiccdn.neighbourhood.com.cn/img/delegate-comme export default function BizService() { const inviteCode = useInviteCode(); const cityOperators = useCityOperators(); - const [value, setValue] = useState('0'); + const [value, setValue] = useState('1'); const handleClickDelegate = useCallback(() => { navigateTo(PageUrl.GroupDelegatePublish); @@ -81,31 +81,31 @@ export default function BizService() {
- -
-
-
服务城市
-
江、沪、皖-上海、南京、合肥
-
粤、闽-广州、深圳、佛山、厦门、福州、泉州
-
京、鲁-北京、青岛
-
鄂、豫、湘、陕-长沙、武汉、郑州、西安
-
川、渝、云-成都、重庆、昆明
-
服务方式及收费标准
-
服务方式:提供录屏和基本资料供挑选,挑中安排面试
-
收费标准:安排一场面试200元
-
收费方式:预付费,按安排面试场数扣费
-
服务能力
-
- 我们在每个城市均有数量众多的主播群,少则几十个,多则上千个,有各种类型和层次的带货主播资源 -
-
- -
-
-
-
+ {/**/} + {/*
*/} + {/*
*/} + {/*
服务城市
*/} + {/*
江、沪、皖-上海、南京、合肥
*/} + {/*
粤、闽-广州、深圳、佛山、厦门、福州、泉州
*/} + {/*
京、鲁-北京、青岛
*/} + {/*
鄂、豫、湘、陕-长沙、武汉、郑州、西安
*/} + {/*
川、渝、云-成都、重庆、昆明
*/} + {/*
服务方式及收费标准
*/} + {/*
服务方式:提供录屏和基本资料供挑选,挑中安排面试
*/} + {/*
收费标准:安排一场面试200元
*/} + {/*
收费方式:预付费,按安排面试场数扣费
*/} + {/*
服务能力
*/} + {/*
*/} + {/* 我们在每个城市均有数量众多的主播群,少则几十个,多则上千个,有各种类型和层次的带货主播资源*/} + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + {/*
*/} + {/*
*/} + {/*
*/}