修复一堆问题
This commit is contained in:
@@ -45,7 +45,7 @@ const ListCard: React.FC<ListCardProps> = ({
|
|||||||
className="image"
|
className="image"
|
||||||
mode="aspectFill"
|
mode="aspectFill"
|
||||||
lazyLoad
|
lazyLoad
|
||||||
defaultSource="https://images.unsplash.com/photo-1554068865-24cecd4e34b8?w=200&h=200&fit=crop&crop=center"
|
defaultSource={require("@/static/emptyStatus/publish-empty-card.png")}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,25 +89,15 @@ const RadarChart: React.FC = forwardRef((props, ref) => {
|
|||||||
ctx.lineWidth = 1;
|
ctx.lineWidth = 1;
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
// 标签
|
// 标签:沿轴线外侧延伸,文字中心对齐轴线端点
|
||||||
const offset = 10;
|
const labelOffset = 28;
|
||||||
const textX = center.x + (radius + offset) * Math.cos(angle);
|
const textX = center.x + (radius + labelOffset) * Math.cos(angle);
|
||||||
const textY = center.y + (radius + offset) * Math.sin(angle);
|
const textY = center.y + (radius + labelOffset) * Math.sin(angle);
|
||||||
|
|
||||||
ctx.font = "12px sans-serif";
|
ctx.font = "12px sans-serif";
|
||||||
ctx.fillStyle = "#333";
|
ctx.fillStyle = "#333";
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
|
|
||||||
if (
|
|
||||||
Math.abs(angle) < 0.01 ||
|
|
||||||
Math.abs(Math.abs(angle) - Math.PI) < 0.01
|
|
||||||
) {
|
|
||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
} else if (angle > -Math.PI / 2 && angle < Math.PI / 2) {
|
|
||||||
ctx.textAlign = "left";
|
|
||||||
} else {
|
|
||||||
ctx.textAlign = "right";
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillText(label, textX, textY);
|
ctx.fillText(label, textX, textY);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,26 +102,15 @@ const RadarChartV2 = forwardRef<RadarChartV2Ref, RadarChartV2Props>((props, ref)
|
|||||||
ctx.lineWidth = 1 * (radarSize / 200); // 根据2倍图调整线宽
|
ctx.lineWidth = 1 * (radarSize / 200); // 根据2倍图调整线宽
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
|
|
||||||
// 标签 - 文字显示在圆圈外面
|
// 标签:沿轴线外侧延伸,文字中心对齐轴线端点(与 index.tsx 一致)
|
||||||
const offset = 10 * (radarSize / 200); // 文字距离圆圈的偏移量(2倍图)
|
const labelOffset = 28 * (radarSize / 200); // 文字距离圆圈的偏移量(2倍图)
|
||||||
const textX = center.x + (radius + offset) * Math.cos(angle);
|
const textX = center.x + (radius + labelOffset) * Math.cos(angle);
|
||||||
const textY = center.y + (radius + offset) * Math.sin(angle);
|
const textY = center.y + (radius + labelOffset) * Math.sin(angle);
|
||||||
|
|
||||||
ctx.font = `${12 * (radarSize / 200)}px sans-serif`; // 根据2倍图调整字体大小
|
ctx.font = `${12 * (radarSize / 200)}px sans-serif`; // 根据2倍图调整字体大小
|
||||||
ctx.fillStyle = "#333";
|
ctx.fillStyle = "#333";
|
||||||
ctx.textBaseline = "middle";
|
ctx.textBaseline = "middle";
|
||||||
|
|
||||||
// 调整文字对齐方式
|
|
||||||
if (
|
|
||||||
Math.abs(angle) < 0.01 ||
|
|
||||||
Math.abs(Math.abs(angle) - Math.PI) < 0.01
|
|
||||||
) {
|
|
||||||
ctx.textAlign = "center";
|
ctx.textAlign = "center";
|
||||||
} else if (angle > -Math.PI / 2 && angle < Math.PI / 2) {
|
|
||||||
ctx.textAlign = "left";
|
|
||||||
} else {
|
|
||||||
ctx.textAlign = "right";
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.fillText(label, textX, textY);
|
ctx.fillText(label, textX, textY);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ const ListContainer = (props) => {
|
|||||||
// 插入 banner 卡片
|
// 插入 banner 卡片
|
||||||
function insertBannerCard(list) {
|
function insertBannerCard(list) {
|
||||||
if (!bannerListImage) return list;
|
if (!bannerListImage) return list;
|
||||||
|
if (!list || !Array.isArray(list)) return list ?? [];
|
||||||
return [
|
return [
|
||||||
...list.slice(0, Number(bannerListIndex)),
|
...list.slice(0, Number(bannerListIndex)),
|
||||||
{ type: "banner", banner_image_url: bannerListImage, banner_detail_url: bannerDetailImage },
|
{ type: "banner", banner_image_url: bannerListImage, banner_detail_url: bannerDetailImage },
|
||||||
@@ -142,33 +143,29 @@ const ListContainer = (props) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 对于没有ntrp等级的用户每个月展示一次, 插在第二个位置后面
|
// 对于没有ntrp等级的用户每个月展示一次, 插在第二个位置后面
|
||||||
|
// insertBannerCard 需在最后统一执行,否则前面分支直接 return 时 banner 不会被插入
|
||||||
function insertEvaluateCard(list) {
|
function insertEvaluateCard(list) {
|
||||||
if (!evaluateFlag)
|
let result: any[];
|
||||||
return showNumber !== undefined ? list.slice(0, showNumber) : list;
|
|
||||||
if (!list || list.length === 0) {
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
// 如果最近一个月有测试记录,则不插入 card
|
|
||||||
if (hasTestInLastMonth) {
|
|
||||||
return showNumber !== undefined ? list.slice(0, showNumber) : list;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (list.length <= 2) {
|
if (!evaluateFlag) {
|
||||||
return [...list, { type: "evaluateCard" }];
|
result = showNumber !== undefined ? list.slice(0, showNumber) : list;
|
||||||
}
|
} else if (!list || list.length === 0) {
|
||||||
|
result = list;
|
||||||
|
} else if (hasTestInLastMonth) {
|
||||||
|
result = showNumber !== undefined ? list.slice(0, showNumber) : list;
|
||||||
|
} else if (list.length <= 2) {
|
||||||
|
result = [...list, { type: "evaluateCard" }];
|
||||||
|
} else {
|
||||||
const [item1, item2, ...rest] = list;
|
const [item1, item2, ...rest] = list;
|
||||||
|
result = [
|
||||||
let result = [
|
|
||||||
item1,
|
item1,
|
||||||
item2,
|
item2,
|
||||||
{ type: "evaluateCard" },
|
{ type: "evaluateCard" },
|
||||||
...(showNumber !== undefined ? rest.slice(0, showNumber - 3) : rest),
|
...(showNumber !== undefined ? rest.slice(0, showNumber - 3) : rest),
|
||||||
];
|
];
|
||||||
|
|
||||||
if (bannerListImage) {
|
|
||||||
return insertBannerCard(result);
|
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
|
return insertBannerCard(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
const memoizedList = useMemo(
|
const memoizedList = useMemo(
|
||||||
|
|||||||
@@ -67,12 +67,6 @@ const MainPage: React.FC = () => {
|
|||||||
try {
|
try {
|
||||||
await fetchUserInfo();
|
await fetchUserInfo();
|
||||||
await checkNicknameChangeStatus();
|
await checkNicknameChangeStatus();
|
||||||
// 启动时预取 Banner 字典(与业务无强依赖,失败不影响主流程)
|
|
||||||
try {
|
|
||||||
await useDictionaryStore.getState().fetchBannerDictionary();
|
|
||||||
} catch (e) {
|
|
||||||
console.error("预取 Banner 字典失败:", e);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取用户信息失败:", error);
|
console.error("获取用户信息失败:", error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 示例消息卡片区域
|
// 示例消息卡片区域
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ const NewFollow = () => {
|
|||||||
<View className="follow-left" onClick={() => handleUserClick(item.user_id)}>
|
<View className="follow-left" onClick={() => handleUserClick(item.user_id)}>
|
||||||
<Image
|
<Image
|
||||||
className="user-avatar" mode="aspectFill"
|
className="user-avatar" mode="aspectFill"
|
||||||
src={item.user_avatar || "https://img.yzcdn.cn/vant/cat.jpeg"}
|
src={item.user_avatar || require("@/static/userInfo/default_avatar.svg")}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|||||||
@@ -216,8 +216,7 @@ function Intro() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
Taro.redirectTo({
|
Taro.redirectTo({
|
||||||
url: `/other_pages/ntrp-evaluate/index?stage=${type}${
|
url: `/other_pages/ntrp-evaluate/index?stage=${type}${type === StageType.RESULT ? `&id=${id}` : ""
|
||||||
type === StageType.RESULT ? `&id=${id}` : ""
|
|
||||||
}`,
|
}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -539,18 +538,21 @@ function Result() {
|
|||||||
const res = await evaluateService.getTestResult({ record_id: Number(id) });
|
const res = await evaluateService.getTestResult({ record_id: Number(id) });
|
||||||
if (res.code === 0) {
|
if (res.code === 0) {
|
||||||
setResult(res.data);
|
setResult(res.data);
|
||||||
// delay(1000);
|
|
||||||
setRadarData(
|
const sortOrder = res.data.sort || [];
|
||||||
adjustRadarLabels(
|
const abilities = res.data.radar_data.abilities;
|
||||||
Object.entries(res.data.radar_data.abilities).map(([key, value]) => [
|
const sortedKeys = sortOrder.filter((k) => k in abilities);
|
||||||
|
const remainingKeys = Object.keys(abilities).filter((k) => !sortOrder.includes(k));
|
||||||
|
const allKeys = [...sortedKeys, ...remainingKeys];
|
||||||
|
let radarData: [string, number][] = allKeys.map((key) => [
|
||||||
key,
|
key,
|
||||||
Math.min(
|
Math.min(
|
||||||
100,
|
100,
|
||||||
Math.floor((value.current_score / value.max_score) * 100)
|
Math.floor((abilities[key].current_score / abilities[key].max_score) * 100)
|
||||||
),
|
),
|
||||||
])
|
]);
|
||||||
)
|
// 直接使用接口 sort 顺序,不经过 adjustRadarLabels 重新排序
|
||||||
);
|
setRadarData(radarData);
|
||||||
updateUserLevel(res.data.record_id, res.data.ntrp_level);
|
updateUserLevel(res.data.record_id, res.data.ntrp_level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -698,13 +700,12 @@ function Result() {
|
|||||||
}
|
}
|
||||||
const currentPage = getCurrentFullPath();
|
const currentPage = getCurrentFullPath();
|
||||||
Taro.redirectTo({
|
Taro.redirectTo({
|
||||||
url: `/login_pages/index/index${
|
url: `/login_pages/index/index${currentPage ? `?redirect=${encodeURIComponent(currentPage)}` : ""
|
||||||
currentPage ? `?redirect=${encodeURIComponent(currentPage)}` : ""
|
|
||||||
}`,
|
}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleGo() {}
|
function handleGo() { }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View className={styles.resultContainer}>
|
<View className={styles.resultContainer}>
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ export interface TestResultData {
|
|||||||
level_img?: string; // 等级图片URL
|
level_img?: string; // 等级图片URL
|
||||||
radar_data: RadarData;
|
radar_data: RadarData;
|
||||||
answers: Answer[];
|
answers: Answer[];
|
||||||
|
sort?: string[]; // 雷达图能力项排序,如 ["正手球质", "正手控制", ...]
|
||||||
}
|
}
|
||||||
|
|
||||||
// 单条测试记录
|
// 单条测试记录
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ interface DictionaryState {
|
|||||||
bannerDetailImage: string
|
bannerDetailImage: string
|
||||||
bannerListIndex: string
|
bannerListIndex: string
|
||||||
} | null
|
} | null
|
||||||
fetchBannerDictionary: () => Promise<void>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建字典Store
|
// 创建字典Store
|
||||||
@@ -36,7 +35,7 @@ export const useDictionaryStore = create<DictionaryState>()((set, get) => ({
|
|||||||
set({ isLoading: true, error: null })
|
set({ isLoading: true, error: null })
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const keys = 'publishing_requirements,court_type,court_surface,supplementary_information,game_play,fabu_tip,supported_cities';
|
const keys = 'publishing_requirements,court_type,court_surface,supplementary_information,game_play,fabu_tip,supported_cities,bannerListImage,bannerDetailImage,bannerListIndex';
|
||||||
const response = await commonApi.getDictionaryManyKey(keys)
|
const response = await commonApi.getDictionaryManyKey(keys)
|
||||||
|
|
||||||
if (response.code === 0 && response.data) {
|
if (response.code === 0 && response.data) {
|
||||||
@@ -53,6 +52,15 @@ export const useDictionaryStore = create<DictionaryState>()((set, get) => ({
|
|||||||
dictionaryData: dictionaryData || {},
|
dictionaryData: dictionaryData || {},
|
||||||
isLoading: false
|
isLoading: false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
set({
|
||||||
|
bannerDict: {
|
||||||
|
bannerListImage: response.data.bannerListImage || '',
|
||||||
|
bannerDetailImage: response.data.bannerDetailImage || '',
|
||||||
|
bannerListIndex: (response.data.bannerListIndex ?? '').toString(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
console.log('字典数据获取成功:', response.data)
|
console.log('字典数据获取成功:', response.data)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(response.message || '获取字典数据失败')
|
throw new Error(response.message || '获取字典数据失败')
|
||||||
@@ -67,26 +75,7 @@ export const useDictionaryStore = create<DictionaryState>()((set, get) => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取 Banner 字典(启动时或手动调用)
|
|
||||||
fetchBannerDictionary: async () => {
|
|
||||||
try {
|
|
||||||
const keys = 'bannerListImage,bannerDetailImage,bannerListIndex';
|
|
||||||
const response = await commonApi.getDictionaryManyKey(keys)
|
|
||||||
if (response.code === 0 && response.data) {
|
|
||||||
const data = response.data || {};
|
|
||||||
set({
|
|
||||||
bannerDict: {
|
|
||||||
bannerListImage: data.bannerListImage || '',
|
|
||||||
bannerDetailImage: data.bannerDetailImage || '',
|
|
||||||
bannerListIndex: (data.bannerListIndex ?? '').toString(),
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
// 保持静默,避免影响启动流程
|
|
||||||
console.error('获取 Banner 字典失败:', error)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取字典值
|
// 获取字典值
|
||||||
getDictionaryValue: (key: string, defaultValue?: any) => {
|
getDictionaryValue: (key: string, defaultValue?: any) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user