Merge branch 'trunk' into feat/partner

* trunk:
  feat: login
This commit is contained in:
eleanor.mao 2025-05-22 18:13:41 +08:00
commit fa30ec2988
9 changed files with 177 additions and 132 deletions

View File

@ -53,10 +53,17 @@ export interface SearchCityProps {
onSelectCity: (cityCode: string) => void;
currentCity?: string;
forGroup?: boolean;
banner?: string;
offset?: number;
}
export default function SearchCity({ onSelectCity, currentCity = '', forGroup = false, offset = 0 }: SearchCityProps) {
export default function SearchCity({
onSelectCity,
currentCity = '',
banner = '',
forGroup = false,
offset = 0,
}: SearchCityProps) {
const [winHeight, indexItemHeight] = useHeight();
const [touchAnchor, setTouchAnchor] = useState<string | undefined>();
const [touchMoving, setTouchMoving] = useState(false);
@ -134,13 +141,13 @@ export default function SearchCity({ onSelectCity, currentCity = '', forGroup =
<div className={PREFIX}>
<ScrollView scrollY style={{ height: winHeight - offset }} scrollIntoView={touchAnchor}>
<div className={`${PREFIX}__search-wrapper ${forGroup ? 'group' : ''}`}>
{forGroup && (
{forGroup && banner ? (
<div className={`${PREFIX}__banner`}>
<div className="dash"></div>
<div className="text"></div>
<div className="text">{banner}</div>
<div className="dash"></div>
</div>
)}
) : null}
<Search
className={`${PREFIX}__search`}
placeholder="输入城市名称"
@ -211,7 +218,7 @@ export default function SearchCity({ onSelectCity, currentCity = '', forGroup =
onTouchMove={handleTouchMove}
onTouchEnd={handleTouchEnd}
onTouchCancel={handleTouchEnd}
style={{ top: indexItemHeight * OFFSET_INDEX_SIZE + offset }}
style={{ top: indexItemHeight * OFFSET_INDEX_SIZE + (forGroup ? 72 : 0) }}
>
{CITY_LIST.map(item => {
return (

View File

@ -2,77 +2,7 @@
@import '@/styles/variables.less';
.group-v2-page {
padding: 24px;
&__header {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
margin-bottom: 32px;
&__left-line,
&__right-line {
width: 88px;
height: 1px;
}
&__left-line {
background: linear-gradient(270deg, #CCCCCC -0.05%, rgba(204, 204, 204, 0) 99.95%);
}
&__right-line {
background: linear-gradient(90deg, #CCCCCC 0%, rgba(204, 204, 204, 0) 100%);
}
&__title {
font-size: 28px;
line-height: 40px;
font-weight: 400;
color: @blColorG2;
margin: 0 16px;
}
}
&__group-card {
.flex-row();
width: 100%;
padding: 32px;
background: #FFF;
border-radius: 16px;
margin-top: 24px;
box-sizing: border-box;
&:first-child {
margin-top: 0;
}
&__avatar {
width: 88px;
height: 88px;
border-radius: 6px;
border: 4px solid #D9D9D9;
}
&__title {
flex: 1;
font-size: 32px;
line-height: 40px;
font-weight: 500;
color: @blColor;
align-self: flex-start;
margin-left: 36px;
}
&__button {
.button(@width: 176px; @height: 56px; @fontSize: 28px; @fontWeight: 500);
}
}
&__bottom-padding {
width: 100%;
height: 24px;
}
padding-bottom: 200px;
height: 100vh;
box-sizing: border-box;
}

View File

@ -1,39 +1,23 @@
import { Image } from '@tarojs/components';
import { NodesRef, useLoad, useShareAppMessage } from '@tarojs/taro';
import { useLoad, useShareAppMessage } from '@tarojs/taro';
import { List } from '@taroify/core';
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 SearchCity from '@/components/search-city';
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 { getCurrentCityCode } from '@/utils/location';
import { getInviteCodeFromQueryAndUpdate } from '@/utils/partner';
import { getPageQuery } from '@/utils/route';
import { getCommonShareMessage } from '@/utils/share';
import './index.less';
const PREFIX = 'group-v2-page';
const LIST_CONTAINER_CLASS = `${PREFIX}__list-container`;
const CALC_LIST_PROPS: IUseListHeightProps = {
selectors: [`.${LIST_CONTAINER_CLASS}`, `#${APP_TAB_BAR_ID}`],
calc: (rects: [NodesRef.BoundingClientRectCallbackResult, NodesRef.BoundingClientRectCallbackResult]) => {
const [rect, diffRect] = rects;
return diffRect.top - rect.top;
},
};
export default function GroupV2() {
const listHeight = useListHeight(CALC_LIST_PROPS);
const inviteCode = useInviteCode();
const handleClick = useCallback((group: GroupItem) => openCustomerServiceChat(group.serviceUrl), []);
useLoad(() => {
const query = getPageQuery();
getInviteCodeFromQueryAndUpdate(query);
@ -41,32 +25,23 @@ export default function GroupV2() {
useShareAppMessage(() => getCommonShareMessage(true, inviteCode));
const handleSelectCity = useCallback(cityCode => {
const group = GROUPS.find(g => String(g.cityCode) === cityCode);
if (group) {
openCustomerServiceChat(group.serviceUrl);
}
}, []);
return (
<HomePage>
<div className={PREFIX}>
<div className={`${PREFIX}__header`}>
<div className={`${PREFIX}__header__left-line`} />
<div className={`${PREFIX}__header__title`}></div>
<div className={`${PREFIX}__header__right-line`} />
</div>
<div className={LIST_CONTAINER_CLASS}>
<List style={{ height: `${listHeight}px` }} disabled fixedHeight>
{GROUPS.map(group => (
<div className={`${PREFIX}__group-card`} key={group.serviceUrl}>
<Image
mode="aspectFit"
className={`${PREFIX}__group-card__avatar`}
src="https://neighbourhood.cn/addGroup.jpg"
/>
<div className={`${PREFIX}__group-card__title`}>{group.title}</div>
<LoginButton className={`${PREFIX}__group-card__button`} onClick={() => handleClick(group)}>
</LoginButton>
</div>
))}
<div className={`${PREFIX}__bottom-padding`} />
</List>
</div>
<SearchCity
onSelectCity={handleSelectCity}
currentCity={getCurrentCityCode()}
forGroup
offset={72}
banner="点击城市加入本地通告群,高薪工作早知道"
/>
</div>
</HomePage>
);

View File

@ -1,3 +1,4 @@
export default definePageConfig({
navigationBarTitleText: '',
navigationStyle: 'custom',
});

View File

@ -6,6 +6,12 @@
height: 100vh;
.flex-column();
&.color-bg {
background: linear-gradient(180deg, #efecff 0%, #f7f5ff 100%);
padding-top: 347px;
display: block;
}
&__app {
margin-top: 50%;
}
@ -22,4 +28,68 @@
color: @blColorG2;
margin-top: 32px;
}
&__role-app {
padding: 64px;
}
&__greet {
font-size: 28px;
line-height: 56px;
color: @blColorG1;
margin-bottom: 14px;
}
&__title {
font-weight: 500;
font-size: 48px;
line-height: 57px;
color: @blColor;
margin-bottom: 75px;
}
&__card {
background: rgba(255, 255, 255, 0.5);
border: 2px solid #ffffff;
border-radius: 16px;
padding: 56px 40px 56px;
.flex-row();
& + & {
margin-top: 64px;
}
}
&__avatar {
width: 140px;
height: 140px;
border-radius: 50%;
}
&__content {
padding-left: 34px;
.flex-column();
flex: 1;
align-items: start;
.title {
font-weight: 600;
font-size: 40px;
line-height: 48px;
color: @blColor;
margin-bottom: 16px;
}
.desc {
font-size: 28px;
line-height: 40px;
color: @blColorG1;
}
}
&__arrow {
width: 24px;
height: 24px;
}
}

View File

@ -1,23 +1,76 @@
import { Image } from '@tarojs/components';
import { useLoad } from '@tarojs/taro';
import { switchDefaultTab } from '@/utils/app';
import { useLoad } from '@tarojs/taro';
import Slogan from '@/components/slogan';
import { PageUrl, RoleType } from '@/constants/app';
import { ANCHOR_TAB_LIST, COMPANY_TAB_LIST } from '@/hooks/use-config';
import store from '@/store';
import { changeHomePage } from '@/store/actions';
import { getRoleType, switchDefaultTab, switchRoleType } from '@/utils/app';
import { switchTab } from '@/utils/route';
import './index.less';
const PREFIX = 'page-start';
export default function Start() {
const mode = getRoleType();
useLoad(() => {
switchDefaultTab();
});
const handleAnchor = async () => {
await switchRoleType(RoleType.Anchor);
store.dispatch(changeHomePage(ANCHOR_TAB_LIST[0].type));
await switchTab(ANCHOR_TAB_LIST[0].pagePath as PageUrl);
};
const handleCompany = async () => {
await switchRoleType(RoleType.Company);
store.dispatch(changeHomePage(COMPANY_TAB_LIST[0].type));
await switchTab(COMPANY_TAB_LIST[0].pagePath as PageUrl);
};
return (
<div className={PREFIX}>
<div className={`${PREFIX}__app`}>
<Image className={`${PREFIX}__icon`} mode="aspectFit" src={require('@/statics/svg/slogan.svg')} />
<div className={`${PREFIX}__text`}> </div>
</div>
<div className={`${PREFIX} ${mode ? '' : 'color-bg'}`}>
{mode && (
<div className={`${PREFIX}__app`}>
<Image className={`${PREFIX}__icon`} mode="aspectFit" src={require('@/statics/svg/slogan.svg')} />
<div className={`${PREFIX}__text`}> </div>
</div>
)}
{!mode && (
<>
<div className={`${PREFIX}__role-app`}>
<div className={`${PREFIX}__greet`}>Hi</div>
<div className={`${PREFIX}__title`}></div>
<div className={`${PREFIX}__card`} onClick={handleAnchor}>
<Image
className={`${PREFIX}__avatar anchor`}
src="https://publiccdn.neighbourhood.com.cn/img/avatar_f.png"
mode="aspectFill"
/>
<div className={`${PREFIX}__content`}>
<div className="title"></div>
<div className="desc"></div>
</div>
<Image src={require('@/statics/svg/arrow-right.svg')} mode="aspectFill" className={`${PREFIX}__arrow`} />
</div>
<div className={`${PREFIX}__card`} onClick={handleCompany}>
<Image
className={`${PREFIX}__avatar company`}
src="https://publiccdn.neighbourhood.com.cn/img/avatar_m.png"
mode="aspectFill"
/>
<div className={`${PREFIX}__content`}>
<div className="title"></div>
<div className="desc"></div>
</div>
<Image src={require('@/statics/svg/arrow-right.svg')} mode="aspectFill" className={`${PREFIX}__arrow`} />
</div>
</div>
<Slogan />
</>
)}
</div>
);
}

View File

@ -30,7 +30,13 @@ export default function BizService() {
<div className={PREFIX}>
<Tabs className={`${PREFIX}__tabs`} defaultValue={0}>
<Tabs.TabPane value={0} title="主播群">
<SearchCity onSelectCity={handleSelectCity} currentCity={getCurrentCityCode()} forGroup offset={72} />
<SearchCity
onSelectCity={handleSelectCity}
currentCity={getCurrentCityCode()}
forGroup
offset={72}
banner="点击城市名称,进本地通告群,免费招主播"
/>
</Tabs.TabPane>
<Tabs.TabPane value={1} title="群代发">
<UserBatchPublish />

View File

@ -18,10 +18,10 @@ const DEFAULT_LOCATION: LocationInfo = {
longitude: 113.280637,
};
const defaultAppMode = Taro.getStorageSync<RoleType>(CacheKey.APP_MODE_NEW) || RoleType.Anchor;
const defaultAppMode = Taro.getStorageSync<RoleType>(CacheKey.APP_MODE_NEW);
const INIT_STATE: AppState = {
roleType: defaultAppMode,
homePageType: defaultAppMode === RoleType.Anchor ? PageType.JOB : PageType.Anchor,
homePageType: defaultAppMode === RoleType.Company ? PageType.Anchor : PageType.JOB,
location: Taro.getStorageSync<LocationInfo>(CacheKey.CACHE_LOCATION_INFO) || DEFAULT_LOCATION,
};

View File

@ -25,6 +25,9 @@ export const isCompanyMode = () => getRoleType() === RoleType.Company;
export const switchDefaultTab = async () => {
await sleep(1);
const mode = getRoleType();
if (!mode) {
return;
}
const tabList = mode === RoleType.Anchor ? ANCHOR_TAB_LIST : COMPANY_TAB_LIST;
const item = tabList[0];
store.dispatch(changeHomePage(item.type));