Compare commits

...

4 Commits

Author SHA1 Message Date
1c7f35b40f fix(dealer): 移除楼层字段优化房号相关逻辑及表单
- 删除楼层相关代码及状态管理
- 更新房号唯一键及展示逻辑,去除楼层字段
- 表单中楼层输入改为普通输入框,禁用编辑状态
- 修正提交及校验逻辑,统一房号字段处理
- 简化编辑模式房号数据回填过程
- 移除小区、楼栋、单元、楼层、房号弹出选择组件及相关逻辑
- 更改提示文案,从“请选择”改为“请填写”房号相关项
2026-04-24 20:26:52 +08:00
a2009c8cea feat(customer): 优化客户列表访问权限及新增备注字段
- 修改客户添加页面,新增“备注”输入框,支持录入客户备注信息
- 调整环境配置,统一开发、生产、测试环境的API_BASE_URL为正式地址
- 在shopDealerApply模型中新增receptionistId字段,用于查询分配的客户
- 优化客户列表权限逻辑,改为登录即可查看,不再限制角色
- 更新接口调用参数,支持查询当前登录用户提交及分配的客户
- 移除对管理员角色的特殊判断,使权限逻辑更简洁
- UI调整,未登录时显示“请先登录”提示而非“没有查看权限”
2026-04-18 10:56:47 +08:00
2ff740fb07 fix(customer): 修正表单必填属性及组件属性拼写错误
- 将小区和房号字段的 required 属性明确设置为 true
- 修复签约时间和合同时间输入框的 readOnly 属性拼写错误
- 调整姓名和手机号表单项位置,避免隐藏字段内嵌套组件
- 在姓名与手机号表单项间添加间距提升布局美观性
2026-04-16 17:31:42 +08:00
b5f66017cf feat(referral): 新增楼栋单元楼层房号精细选择功能
- 将房号唯一键增加楼层字段,修改相关函数支持楼层处理
- 新增楼栋、单元、楼层、房号的选择状态和搜索过滤功能
- 实现楼栋、单元、楼层、房号的选择弹窗和清除按钮
- 表单改用选择控件替代输入框,隐藏字段同步表单数据
- 修改表单校验,验证楼栋、楼层、房号
2026-04-16 17:11:39 +08:00
11 changed files with 1655 additions and 859 deletions

View File

@@ -35,5 +35,5 @@
} }
] ]
}, },
"lastUpdated": 1776330360601 "lastUpdated": 1776332994640
} }

View File

@@ -24,7 +24,7 @@
## Grid.tsx 硬编码改造 (13:48) ## Grid.tsx 硬编码改造 (13:48)
- 将首页4个功能按钮从后端接口请求改为硬编码 - 将首页4个功能按钮从后端接口请求改为硬编码
- 菜单项:我要推荐、客户列表、邀请好友、个人中心 - 菜单项:推荐客户、客户列表、邀请好友、个人中心
- 图片使用OSS直链避免接口延迟 - 图片使用OSS直链避免接口延迟
- 对应页面路径保持不变 - 对应页面路径保持不变

View File

@@ -2,22 +2,22 @@
export const ENV_CONFIG = { export const ENV_CONFIG = {
// 开发环境 // 开发环境
development: { development: {
// API_BASE_URL: 'https://mp-api.websoft.top/api', API_BASE_URL: 'https://cms-api.websoft.top/api',
API_BASE_URL: 'http://127.0.0.1:9200/api', // API_BASE_URL: 'http://127.0.0.1:9200/api',
APP_NAME: '开发环境', APP_NAME: '开发环境',
DEBUG: 'true', DEBUG: 'true',
}, },
// 生产环境 // 生产环境
production: { production: {
// API_BASE_URL: 'https://mp-api.websoft.top/api', API_BASE_URL: 'https://cms-api.websoft.top/api',
API_BASE_URL: 'http://127.0.0.1:9200/api', // API_BASE_URL: 'http://127.0.0.1:9200/api',
APP_NAME: '南南佐顿门窗', APP_NAME: '南南佐顿门窗',
DEBUG: 'false', DEBUG: 'false',
}, },
// 测试环境 // 测试环境
test: { test: {
// API_BASE_URL: 'https://mp-api.websoft.top/api', API_BASE_URL: 'https://cms-api.websoft.top/api',
API_BASE_URL: 'http://127.0.0.1:9200/api', // API_BASE_URL: 'http://127.0.0.1:9200/api',
APP_NAME: '测试环境', APP_NAME: '测试环境',
DEBUG: 'true', DEBUG: 'true',
} }

View File

@@ -66,4 +66,5 @@ export interface ShopDealerApplyParam extends PageParam {
userId?: number; userId?: number;
keywords?: string; keywords?: string;
applyStatus?: number; // 申请状态筛选 (10待审核 20审核通过 30驳回) applyStatus?: number; // 申请状态筛选 (10待审核 20审核通过 30驳回)
receptionistId?: number; // 接待人员用户ID用于查询分配给自己的客户
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
import {useState, useEffect, useCallback, useRef} from 'react' import {useState, useEffect, useCallback} from 'react'
import {View, Text} from '@tarojs/components' import {View, Text} from '@tarojs/components'
import Taro, {useDidShow} from '@tarojs/taro' import Taro, {useDidShow} from '@tarojs/taro'
import {Loading, InfiniteLoading, Empty, Space, Tabs, TabPane, Tag, Button, SearchBar} from '@nutui/nutui-react-taro' import {Loading, InfiniteLoading, Empty, Space, Tabs, TabPane, Tag, Button, SearchBar} from '@nutui/nutui-react-taro'
@@ -33,24 +33,10 @@ const CustomerIndex = () => {
const [page, setPage] = useState(1) const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true) const [hasMore, setHasMore] = useState(true)
// 非分销商不允许查看客户列表 // 权限检查:只要登录就能查看客户列表
const {user, hasRole, loading: userLoading} = useUser() const {user, loading: userLoading} = useUser()
// 管理员允许查看全部;普通分销商仅查看自己
const isAdminUser = user?.isAdmin === true
const canView = hasRole('dealer') || isAdminUser
const roleCheckFinished = !userLoading const roleCheckFinished = !userLoading
const noPermissionShownRef = useRef(false) const isLoggedIn = roleCheckFinished && user !== null
useEffect(() => {
if (!roleCheckFinished || canView) return
if (noPermissionShownRef.current) return
noPermissionShownRef.current = true
Taro.showToast({
title: '没有查看权限',
icon: 'none',
duration: 1500
})
}, [roleCheckFinished, canView])
// Tab配置 // Tab配置
const tabList = getStatusOptions(); const tabList = getStatusOptions();
@@ -201,14 +187,13 @@ const CustomerIndex = () => {
const currentUserId = Number(Taro.getStorageSync('UserId')) || user?.userId || 0; const currentUserId = Number(Taro.getStorageSync('UserId')) || user?.userId || 0;
// 构建API参数根据状态筛选 // 构建API参数根据状态筛选
// 查看自己提交的(userId)或分配给自己的(receptionistId)的客户
const params: any = { const params: any = {
type: 4, type: 4,
page: currentPage page: currentPage,
userId: currentUserId,
receptionistId: currentUserId
}; };
// 非管理员:只看自己添加的客户
if (!isAdminUser && currentUserId > 0) {
params.userId = currentUserId;
}
const applyStatus = mapCustomerStatusToApplyStatus(statusFilter || activeTab); const applyStatus = mapCustomerStatusToApplyStatus(statusFilter || activeTab);
if (applyStatus !== undefined) { if (applyStatus !== undefined) {
params.applyStatus = applyStatus; params.applyStatus = applyStatus;
@@ -251,7 +236,7 @@ const CustomerIndex = () => {
} finally { } finally {
setLoading(false); setLoading(false);
} }
}, [activeTab, page, isAdminUser, user?.userId]); }, [activeTab, page, user?.userId]);
const reloadMore = async () => { const reloadMore = async () => {
if (loading || !hasMore) return; // 防止重复加载 if (loading || !hasMore) return; // 防止重复加载
@@ -300,11 +285,11 @@ const CustomerIndex = () => {
const fetchStatusCounts = useCallback(async () => { const fetchStatusCounts = useCallback(async () => {
try { try {
const currentUserId = Number(Taro.getStorageSync('UserId')) || user?.userId || 0; const currentUserId = Number(Taro.getStorageSync('UserId')) || user?.userId || 0;
const baseParams: any = {type: 4}; const baseParams: any = {
// 非管理员:只统计自己添加的客户 type: 4,
if (!isAdminUser && currentUserId > 0) { userId: currentUserId,
baseParams.userId = currentUserId; receptionistId: currentUserId
} };
// 并行获取各状态的数量 // 并行获取各状态的数量
const [allRes, pendingRes, signedRes, cancelledRes] = await Promise.all([ const [allRes, pendingRes, signedRes, cancelledRes] = await Promise.all([
@@ -323,7 +308,7 @@ const CustomerIndex = () => {
} catch (error) { } catch (error) {
console.error('获取状态统计失败:', error); console.error('获取状态统计失败:', error);
} }
}, [isAdminUser, user?.userId]); }, [user?.userId]);
const getStatusCounts = () => statusCounts; const getStatusCounts = () => statusCounts;
@@ -364,22 +349,22 @@ const CustomerIndex = () => {
// 初始化统计数据 // 初始化统计数据
useEffect(() => { useEffect(() => {
if (!roleCheckFinished || !canView) return; if (!isLoggedIn) return;
fetchStatusCounts().then(); fetchStatusCounts().then();
}, [roleCheckFinished, canView]); }, [isLoggedIn]);
// 当activeTab变化时重新获取数据 // 当activeTab变化时重新获取数据
useEffect(() => { useEffect(() => {
if (!roleCheckFinished || !canView) return; if (!isLoggedIn) return;
setList([]); // 清空列表 setList([]); // 清空列表
setPage(1); // 重置页码 setPage(1); // 重置页码
setHasMore(true); // 重置加载状态 setHasMore(true); // 重置加载状态
fetchCustomerData(activeTab, true); fetchCustomerData(activeTab, true);
}, [activeTab, roleCheckFinished, canView]); }, [activeTab, isLoggedIn]);
// 监听页面显示,当从其他页面返回时刷新数据 // 监听页面显示,当从其他页面返回时刷新数据
useDidShow(() => { useDidShow(() => {
if (!roleCheckFinished || !canView) return; if (!isLoggedIn) return;
// 刷新当前tab的数据和统计信息 // 刷新当前tab的数据和统计信息
setList([]); setList([]);
setPage(1); setPage(1);
@@ -593,10 +578,11 @@ const CustomerIndex = () => {
); );
} }
if (!canView) { // 未登录时显示提示
if (!isLoggedIn) {
return ( return (
<View className="bg-white flex flex-col items-center justify-center p-4"> <View className="bg-white flex flex-col items-center justify-center p-4">
<Empty description="没有查看权限"/> <Empty description="请先登录"/>
<Button <Button
size="small" size="small"
style={{marginTop: '12px'}} style={{marginTop: '12px'}}

View File

@@ -1,3 +1,3 @@
{ export default definePageConfig({
"navigationBarTitleText": "推荐客户赚佣金" navigationBarTitleText: '推荐客户赚佣金'
} })

View File

@@ -52,7 +52,7 @@ const highlightItems = [
{ {
icon: <Star size={22} color="#ffffff" />, icon: <Star size={22} color="#ffffff" />,
title: '真实口碑', title: '真实口碑',
description: '5000+家庭选择98%满意度,支持老房换窗与整屋升级。' description: '10万+家庭选择98%满意度,支持老房换窗与整屋升级。'
} }
] ]
@@ -220,15 +220,15 @@ const BrochurePage: React.FC = () => {
<View className="brochure-page__stats"> <View className="brochure-page__stats">
<View className="brochure-page__stat"> <View className="brochure-page__stat">
<Text className="brochure-page__stat-value">10</Text> <Text className="brochure-page__stat-value">20</Text>
<Text className="brochure-page__stat-label"></Text> <Text className="brochure-page__stat-label">()</Text>
</View> </View>
<View className="brochure-page__stat"> <View className="brochure-page__stat">
<Text className="brochure-page__stat-value">15</Text> <Text className="brochure-page__stat-value">15</Text>
<Text className="brochure-page__stat-label"></Text> <Text className="brochure-page__stat-label"></Text>
</View> </View>
<View className="brochure-page__stat"> <View className="brochure-page__stat">
<Text className="brochure-page__stat-value">5000+</Text> <Text className="brochure-page__stat-value">10+</Text>
<Text className="brochure-page__stat-label"></Text> <Text className="brochure-page__stat-label"></Text>
</View> </View>
</View> </View>

View File

@@ -14,7 +14,7 @@ interface MenuItem {
const menuList: MenuItem[] = [ const menuList: MenuItem[] = [
{ {
id: 1, id: 1,
title: '我要推荐', title: '推荐客户',
icon: 'https://oss.wsdns.cn/20260330/5f54527123864193b0a2078f812b117f.png?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90', icon: 'https://oss.wsdns.cn/20260330/5f54527123864193b0a2078f812b117f.png?x-oss-process=image/resize,m_fixed,w_750/quality,Q_90',
path: '/dealer/customer/add' path: '/dealer/customer/add'
}, },

View File

@@ -12,8 +12,8 @@ const TrustSection: React.FC = () => {
{ {
icon: <ShieldCheck size={28} color="#ffffff" />, icon: <ShieldCheck size={28} color="#ffffff" />,
title: '品质保障', title: '品质保障',
highlight: '10年', highlight: '20年',
description: '质保承诺', description: '质保承诺(整窗)',
subDescription: '德国进口五金配件', subDescription: '德国进口五金配件',
bg: 'linear-gradient(135deg, #3b82f6, #2563eb)', bg: 'linear-gradient(135deg, #3b82f6, #2563eb)',
}, },
@@ -30,7 +30,7 @@ const TrustSection: React.FC = () => {
title: '客户好评', title: '客户好评',
highlight: '98%', highlight: '98%',
description: '满意度', description: '满意度',
subDescription: '5000+家庭信赖之选', subDescription: '10万+家庭信赖之选',
bg: 'linear-gradient(135deg, #f59e0b, #d97706)', bg: 'linear-gradient(135deg, #f59e0b, #d97706)',
} }
] ]