diff --git a/src/components/CommonPopup/index.module.scss b/src/components/CommonPopup/index.module.scss
index cb12009..a51cb08 100644
--- a/src/components/CommonPopup/index.module.scss
+++ b/src/components/CommonPopup/index.module.scss
@@ -1,8 +1,8 @@
-@use '~@/scss/themeColor.scss' as theme;
+@use "~@/scss/themeColor.scss" as theme;
.common-popup {
position: fixed;
- z-index: 9999!important;
+ z-index: 9999 !important;
.common-popup__drag-handle-container {
position: position;
}
@@ -12,12 +12,12 @@
left: 50%;
width: 32px;
height: 4px;
- background-color: rgba(22, 24, 35, 0.20);
+ background-color: rgba(22, 24, 35, 0.2);
border-radius: 2px;
z-index: 10;
cursor: pointer;
transition: background-color 0.2s ease;
-
+
&:active {
background-color: #9ca3af;
}
@@ -48,13 +48,18 @@
padding: 8px 10px 0 10px;
display: flex;
gap: 8px;
- background: #FFF;
+ background: #fff;
padding-bottom: env(safe-area-inset-bottom);
-
}
.common-popup__btn {
flex: 1;
+ font-feature-settings: "liga" off, "clig" off;
+ font-family: "PingFang SC";
+ font-size: 16px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: normal;
}
.common-popup__btn-cancel {
@@ -63,7 +68,7 @@
border: none;
width: 154px;
height: 44px;
- border-radius: 12px!important;
+ border-radius: 12px !important;
border: 0.5px solid rgba(0, 0, 0, 0.06);
background: #fff;
padding: 4px 10px;
@@ -75,7 +80,7 @@
height: 44px;
border: 0.5px solid rgba(0, 0, 0, 0.06);
background: #000;
- border-radius: 12px!important;
+ border-radius: 12px !important;
padding: 4px 10px;
}
-}
\ No newline at end of file
+}
diff --git a/src/components/CustomNavbar/index.module.scss b/src/components/CustomNavbar/index.module.scss
index b1ebd81..fab7c1d 100644
--- a/src/components/CustomNavbar/index.module.scss
+++ b/src/components/CustomNavbar/index.module.scss
@@ -2,9 +2,8 @@
position: fixed;
top: 0;
left: 0;
- z-index: 999;
overflow: hidden;
- z-index: 999;
+ z-index: 9991;
width: 100%;
background-color: #fff;
-}
\ No newline at end of file
+}
diff --git a/src/components/Picker/CityPicker.tsx b/src/components/Picker/CityPicker.tsx
new file mode 100644
index 0000000..d4bbaa6
--- /dev/null
+++ b/src/components/Picker/CityPicker.tsx
@@ -0,0 +1,72 @@
+import React, { useState } from "react";
+import CommonPopup from "@/components/CommonPopup";
+import Picker from "./Picker";
+interface PickerOption {
+ text: string | number;
+ value: string | number;
+}
+
+interface PickerProps {
+ visible: boolean;
+ setvisible: (visible: boolean) => void;
+ options?: PickerOption[][] | PickerOption[];
+ value?: (string | number)[];
+ type?: "month" | "day" | "hour" | "ntrp" | null;
+ img?: string;
+ onConfirm?: (options: PickerOption[], values: (string | number)[]) => void;
+ onChange?: (value: (string | number)[]) => void;
+ style?: React.CSSProperties;
+}
+
+const PopupPicker = ({
+ visible,
+ setvisible,
+ value = [],
+ onConfirm,
+ onChange,
+ options = [],
+ style,
+}: PickerProps) => {
+ const [defaultValue, setDefaultValue] = useState<(string | number)[]>(value);
+ const changePicker = (_options: any[], values: any, _columnIndex: number) => {
+ setDefaultValue(values);
+ };
+
+ const handleConfirm = () => {
+ console.log(defaultValue, "defaultValue");
+ onChange?.(defaultValue);
+ setvisible(false);
+ };
+
+ const dialogClose = () => {
+ setvisible(false);
+ };
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
+
+export default PopupPicker;
diff --git a/src/components/Picker/index.ts b/src/components/Picker/index.ts
index a8915a1..33a37f7 100644
--- a/src/components/Picker/index.ts
+++ b/src/components/Picker/index.ts
@@ -3,4 +3,5 @@ export { default as PopupPicker } from './PopupPicker'
export { default as PickerCommon } from './PickerCommon'
export type { PickerCommonRef } from './PickerCommon'
export { default as CalendarUI } from './CalendarUI/CalendarUI'
-export { default as DialogCalendarCard } from './CalendarDialog/DialogCalendarCard'
\ No newline at end of file
+export { default as DialogCalendarCard } from './CalendarDialog/DialogCalendarCard'
+export { default as CityPicker } from './CityPicker'
\ No newline at end of file
diff --git a/src/container/listCustomNavbar/index.tsx b/src/container/listCustomNavbar/index.tsx
index 9786f42..a57f39a 100644
--- a/src/container/listCustomNavbar/index.tsx
+++ b/src/container/listCustomNavbar/index.tsx
@@ -1,13 +1,15 @@
+import { useEffect, useState } from "react";
import { View, Text, Image } from "@tarojs/components";
import img from "@/config/images";
import { useGlobalState } from "@/store/global";
-import { useUserInfo, } from '@/store/userStore'
+import { useUserInfo } from "@/store/userStore";
import { useListState } from "@/store/listStore";
import CustomNavbar from "@/components/CustomNavbar";
import { Input } from "@nutui/nutui-react-taro";
import Taro from "@tarojs/taro";
import "./index.scss";
import { getCurrentFullPath } from "@/utils";
+import { CityPicker as PopupPicker } from "@/components/Picker";
interface IProps {
config?: {
@@ -18,30 +20,60 @@ interface IProps {
};
}
+function CityPicker(props) {
+ const { visible, setVisible, cities, area, setArea } = props;
+ console.log(cities, "cities");
+ const [index, setIndex] = useState(0);
+ const [value, setValue] = useState(area);
+
+ useEffect(() => {
+ if (visible) {
+ setIndex(index + 1);
+ }
+ }, [visible]);
+
+ function onChange(value: any) {
+ console.log(value, "value");
+ setValue(value);
+ setArea(value);
+ }
+ return (
+ visible && (
+
+ )
+ );
+}
+
const ListHeader = (props: IProps) => {
const { config } = props;
- const {
- showInput = false,
- inputLeftIcon,
- leftIconClick,
- } = config || {};
- const {
- getLocationLoading,
- statusNavbarHeightInfo,
- } = useGlobalState();
- const { gamesNum, searchValue } = useListState();
+ const { showInput = false, inputLeftIcon, leftIconClick } = config || {};
+ const { getLocationLoading, statusNavbarHeightInfo } = useGlobalState();
+ const { gamesNum, searchValue, cities, area, updateArea } = useListState();
const { navBarHeight } = statusNavbarHeightInfo;
- const userInfo = useUserInfo()
- const city = (userInfo as any)?.city || ''
- const district = (userInfo as any)?.district || ''
+ const [cityPopupVisible, setCityPopupVisible] = useState(false);
- console.log("useUserInfo",city,district )
+ const userInfo = useUserInfo();
+ const province = (userInfo as any)?.province || "";
+ const city = (userInfo as any)?.city || "";
+ // const district = (userInfo as any)?.district || "";
- const currentAddress = city + district
+ useEffect(() => {
+ updateArea(["中国", province, city]);
+ }, [province, city]);
+
+ // const currentAddress = city + district;
const handleInputClick = () => {
- const currentPagePath = getCurrentFullPath()
+ const currentPagePath = getCurrentFullPath();
if (currentPagePath === "/game_pages/searchResult/index") {
Taro.navigateBack();
} else {
@@ -77,13 +109,18 @@ const ListHeader = (props: IProps) => {
height: `${navBarHeight}px`,
};
+ function handleToggleCity() {
+ setCityPopupVisible(true);
+ }
+
+ const area_city = area.at(-1);
return (
{/* 首页logo 导航*/}
@@ -96,10 +133,10 @@ const ListHeader = (props: IProps) => {
/>
-
+
{/* 位置 */}
- {currentAddress}
- {!getLocationLoading && currentAddress && (
+ {area_city}
+ {!getLocationLoading && area_city && (
)}
@@ -111,8 +148,9 @@ const ListHeader = (props: IProps) => {
{/* 搜索导航 */}
@@ -139,6 +177,13 @@ const ListHeader = (props: IProps) => {
+
);
};
diff --git a/src/game_pages/list/index.module.scss b/src/game_pages/list/index.module.scss
index a6f8c79..db7b707 100644
--- a/src/game_pages/list/index.module.scss
+++ b/src/game_pages/list/index.module.scss
@@ -4,6 +4,79 @@
}
}
+.cqContainer {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ width: 100vw;
+ height: 100vh;
+
+ .wrapper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ // gap: 24px;
+
+ .tips {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+
+ .tip1 {
+ color: #000;
+ text-align: center;
+ font-family: "PingFang SC";
+ font-size: 18px;
+ font-style: normal;
+ font-weight: 600;
+ line-height: 28px;
+ }
+
+ .tip2 {
+ color: rgba(0, 0, 0, 0.65);
+ text-align: center;
+ font-family: "PingFang SC";
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ }
+ }
+
+ .qrcodeWrappper {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 12px;
+
+ .qrcode {
+ width: 180px;
+ height: 180px;
+ // border-radius: 12px;
+ // border: 1px solid rgba(0, 0, 0, 0.06);
+ // background: lightgray 50% / cover no-repeat;
+ // box-shadow: 0 4px 36px 0 rgba(0, 0, 0, 0.16);
+ }
+
+ .qrcodeTip {
+ color: rgba(0, 0, 0, 0.65);
+ text-align: center;
+ font-family: "PingFang SC";
+ font-size: 14px;
+ font-style: normal;
+ font-weight: 400;
+ line-height: normal;
+ margin-top: -30px;
+ }
+ }
+ }
+}
+
.listPage {
background-color: #fefefe;
@@ -83,4 +156,4 @@
transform: translateY(20px);
pointer-events: none;
/* 隐藏时不响应鼠标事件 */
-}
\ No newline at end of file
+}
diff --git a/src/game_pages/list/index.tsx b/src/game_pages/list/index.tsx
index 36b2bbc..847603a 100644
--- a/src/game_pages/list/index.tsx
+++ b/src/game_pages/list/index.tsx
@@ -9,7 +9,7 @@ import Taro, {
} from "@tarojs/taro";
import { useListStore } from "@/store/listStore";
import { useGlobalState } from "@/store/global";
-import { View } from "@tarojs/components";
+import { View, Image, Text } from "@tarojs/components";
import CustomerNavBar from "@/container/listCustomNavbar";
import GuideBar from "@/components/GuideBar";
import ListContainer from "@/container/listContainer";
@@ -19,7 +19,7 @@ import { updateUserLocation } from "@/services/userService";
// import ShareCardCanvas from "@/components/ShareCardCanvas";
import { useUserActions } from "@/store/userStore";
import { useDictionaryStore } from "@/store/dictionaryStore";
-// import generateShareImage from '@/utils/share'
+import { saveImage } from "@/utils";
const ListPage = () => {
// 从 store 获取数据和方法
@@ -47,6 +47,10 @@ const ListPage = () => {
loadMoreMatches,
fetchGetGamesCount,
updateDistanceQuickFilter,
+ getCities,
+ getCityQrCode,
+ area,
+ cityQrCode,
} = store;
const {
@@ -104,6 +108,8 @@ const ListPage = () => {
useEffect(() => {
getLocation();
fetchUserInfo();
+ getCities();
+ getCityQrCode();
}, []);
// 监听数据变化,如果是第一页就滚动到顶部
@@ -317,6 +323,44 @@ const ListPage = () => {
// })
// }, [])
+ const area_city = area.at(-2);
+
+ function renderCityQrcode() {
+ let item = cityQrCode.find((item) => item.city_name === area_city);
+ if (!item) item = cityQrCode.find((item) => item.city_name === "其他");
+ return (
+
+ {item ? (
+
+
+ 当前城市暂无球局
+
+ 加入城市球友群,获得最新球局消息
+
+
+
+ {
+ saveImage(item.qr_code_url);
+ }}
+ />
+
+ 点击图片保存,使用微信扫码加入群聊
+
+
+
+ ) : (
+
+ 当前城市暂无球局, 敬请期待
+
+ )}
+
+ );
+ }
+
return (
<>
{/* 自定义导航 */}
@@ -325,82 +369,69 @@ const ListPage = () => {
showInput: isShowInputCustomerNavBar,
}}
/>
-
- {/* 列表内容 */}
-
- {/* 综合筛选 */}
- {isShowFilterPopup && (
-
-
+ {/* 列表内容 */}
+
+ {/* 综合筛选 */}
+ {isShowFilterPopup && (
+
+
+
+ )}
+
+ 0}
+ filterCount={filterCount}
+ onChange={handleSearchChange}
+ value={searchValue}
+ onInputClick={handleSearchClick}
+ />
+
+ {/* 筛选 */}
+
+
- )}
-
- 0}
- filterCount={filterCount}
- onChange={handleSearchChange}
- value={searchValue}
- onInputClick={handleSearchClick}
- />
-
- {/* 筛选 */}
-
-
-
- {/* 列表内容 */}
-
+ {/* 列表内容 */}
+
+
-
- {/* 测试分享功能 */}
- {/* */}
+ )}
>
);
diff --git a/src/other_pages/ntrp-evaluate/index.tsx b/src/other_pages/ntrp-evaluate/index.tsx
index aac57e7..4b8a238 100644
--- a/src/other_pages/ntrp-evaluate/index.tsx
+++ b/src/other_pages/ntrp-evaluate/index.tsx
@@ -553,8 +553,13 @@ function Result() {
},
});
} else {
- const url = await genCardImage();
- Taro.saveImageToPhotosAlbum({ filePath: url });
+ try {
+ const url = await genCardImage();
+ Taro.saveImageToPhotosAlbum({ filePath: url });
+ Taro.showToast({ title: "保存成功" });
+ } catch (e) {
+ Taro.showToast({ title: "图片保存失败", icon: "none" });
+ }
}
});
}
diff --git a/src/services/listApi.ts b/src/services/listApi.ts
index 2104ed4..82debd5 100644
--- a/src/services/listApi.ts
+++ b/src/services/listApi.ts
@@ -48,8 +48,8 @@ export const getGamesIntegrateList = async (params?: Record) => {
/**
* 获取列表数量
- * @param params
- * @returns
+ * @param params
+ * @returns
*/
export const getGamesCount = async (params?: Record) => {
try {
@@ -79,7 +79,7 @@ export const getSearchHistory = async (params) => {
/**
* @description 清除搜索历史
- * @returns
+ * @returns
*/
export const clearHistory = async (params) => {
try {
@@ -96,7 +96,7 @@ export const clearHistory = async (params) => {
/**
* @description 获取联想
* @param params 查询参数
- * @returns
+ * @returns
*/
export const searchSuggestion = async (params) => {
try {
@@ -109,3 +109,26 @@ export const searchSuggestion = async (params) => {
throw error;
}
}
+
+export const getCities = async () => {
+ try {
+ // 调用HTTP服务获取城市列表
+ return httpService.post('/cities/tree', {})
+ } catch (error) {
+ // 捕获并打印错误信息
+ console.error("城市列表获取失败:", error);
+ // 抛出错误以便上层处理
+ throw error;
+ }
+}
+export const getCityQrCode = async () => {
+ try {
+ // 调用HTTP服务获取城市二维码
+ return httpService.post('/hot_city_qr/list', {})
+ } catch (error) {
+ // 捕获并打印错误信息
+ console.error("城市二维码获取失败:", error);
+ // 抛出错误以便上层处理
+ throw error;
+ }
+}
diff --git a/src/store/listStore.ts b/src/store/listStore.ts
index 58675e9..29f1d4c 100644
--- a/src/store/listStore.ts
+++ b/src/store/listStore.ts
@@ -7,6 +7,8 @@ import {
clearHistory,
searchSuggestion,
getGamesCount,
+ getCities,
+ getCityQrCode,
} from "../services/listApi";
import {
ListActions,
@@ -15,6 +17,19 @@ import {
IPayload,
} from "../../types/list/types";
+function translateCityData(dataTree) {
+ return dataTree.map((item) => {
+ const { children, ...rest } = item;
+ return {
+ ...rest,
+ text: rest.name,
+ label: rest.name,
+ value: rest.name,
+ children: children?.length > 0 ? translateCityData(children) : null,
+ };
+ });
+}
+
// 完整的 Store 类型
type TennisStore = ListState & ListActions;
@@ -138,6 +153,9 @@ const commonStateDefaultValue = {
{ id: 5, label: "晚上 18:00-22:00", value: "18:00-22:00" },
{ id: 6, label: "夜间 22:00-24:00", value: "22:00-24:00" },
],
+ cities: [],
+ cityQrCode: [],
+ area: ['', '', ''] as [string, string, string],
}
// 创建 store
@@ -486,6 +504,32 @@ export const useListStore = create()((set, get) => ({
});
console.log("===更新搜索页状态:", state);
},
+
+ async getCities() {
+ const res = await getCities();
+ const state = get();
+ set({
+ ...state,
+ cities: translateCityData(res.data),
+ })
+ },
+
+ async getCityQrCode() {
+ const res = await getCityQrCode();
+ const state = get();
+ set({
+ ...state,
+ cityQrCode: res.data,
+ })
+ },
+
+ updateArea(payload: [string, string, string]) {
+ const state = get();
+ set({
+ ...state,
+ area: payload,
+ })
+ },
}));
// 导出便捷的 hooks
diff --git a/src/utils/index.ts b/src/utils/index.ts
index 198e242..8841d7a 100644
--- a/src/utils/index.ts
+++ b/src/utils/index.ts
@@ -9,3 +9,4 @@ export * from './orderActions';
export * from './routeUtil';
export * from './share'
export * from './genPoster'
+export * from './wx_helper'
diff --git a/src/utils/wx_helper.ts b/src/utils/wx_helper.ts
new file mode 100644
index 0000000..a3382f8
--- /dev/null
+++ b/src/utils/wx_helper.ts
@@ -0,0 +1,35 @@
+import Taro from "@tarojs/taro";
+
+export function saveImage(url) {
+ Taro.getSetting().then(async (res) => {
+ if (!res.authSetting["scope.writePhotosAlbum"]) {
+ Taro.authorize({
+ scope: "scope.writePhotosAlbum",
+ success: async () => {
+ try {
+ Taro.saveImageToPhotosAlbum({ filePath: url });
+ Taro.showToast({ title: "保存成功" });
+ } catch (e) {
+ Taro.showToast({ title: "图片保存失败", icon: "none" });
+ }
+ },
+ fail: () => {
+ Taro.showModal({
+ title: "提示",
+ content: "需要开启相册权限才能保存图片",
+ success: (r) => {
+ if (r.confirm) Taro.openSetting();
+ },
+ });
+ },
+ });
+ } else {
+ try {
+ Taro.saveImageToPhotosAlbum({ filePath: url });
+ Taro.showToast({ title: "保存成功" });
+ } catch (e) {
+ Taro.showToast({ title: "图片保存失败", icon: "none" });
+ }
+ }
+ });
+}
\ No newline at end of file
diff --git a/types/list/types.ts b/types/list/types.ts
index e647e61..4ae190f 100644
--- a/types/list/types.ts
+++ b/types/list/types.ts
@@ -51,10 +51,24 @@ export interface SearchPageState extends PageState {
data: TennisMatch[]
suggestionList: string[]
isShowSuggestion: boolean
- searchHistory: {id: number, title: string}[]
+ searchHistory: { id: number, title: string }[]
searchHistoryParams: Record
}
+export interface CityTree {
+ id?: number;
+ name: string;
+ children: CityTree[];
+}
+
+export interface CityQrCodeItem {
+ id: number,
+ city_name: string,
+ qr_code_url: string,
+ description: string,
+ sort_order: number
+}
+
// 主状态接口
export interface ListState {
currentPage: string
@@ -73,6 +87,9 @@ export interface ListState {
timeBubbleData: BubbleOption[]
dateRangeOptions: BubbleOption[]
gamesNum: number
+ cities: CityTree[]
+ cityQrCode: CityQrCodeItem[]
+ area: [string, string, string]
}
export interface ListActions {
@@ -96,6 +113,9 @@ export interface ListActions {
getCurrentPageState: () => { currentPageState: any; currentPageKey: string }
updateCurrentPageState: (payload: Record) => void
updateDistanceQuickFilter: (payload: Record) => void
+ getCities: () => Promise
+ getCityQrCode: () => Promise
+ updateArea: (payload: [string, string, string]) => void
}
export interface IPayload {