feat:1
This commit is contained in:
@@ -44,9 +44,9 @@ const QuotationPage = () => {
|
||||
const [selectedTemplateId, setSelectedTemplateId] = useState(null);
|
||||
const [templates, setTemplates] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [selectedCategory, setSelectedCategory] = useState("all");
|
||||
const [categories, setCategories] = useState([]);
|
||||
|
||||
const [customers,setCustomers]=useState([])
|
||||
const [loadingCustomers, setLoadingCustomers] = useState(false);
|
||||
const [selectedCustomer, setSelectedCustomer] = useState(null);
|
||||
const {
|
||||
resources: quotations,
|
||||
loading: loadingQuotations,
|
||||
@@ -56,9 +56,18 @@ const QuotationPage = () => {
|
||||
} = useResources(pagination, sorter, "quota");
|
||||
|
||||
useEffect(() => {
|
||||
fetchQuotations();
|
||||
}, []);
|
||||
fetchQuotations({
|
||||
current: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
field: sorter.field,
|
||||
order: sorter.order,
|
||||
search: selectedCustomer ? JSON.stringify({ customerId: selectedCustomer }) : "" // 添加搜索参数
|
||||
});
|
||||
|
||||
}, [selectedCustomer, pagination.current, pagination.pageSize, sorter]); // 添加更多依赖项
|
||||
useEffect(()=>{
|
||||
fetchCustomers();
|
||||
},[])
|
||||
const handleTableChange = (pagination, filters, sorter) => {
|
||||
setPagination(pagination);
|
||||
setSorter(sorter);
|
||||
@@ -106,11 +115,7 @@ const QuotationPage = () => {
|
||||
}
|
||||
}, [isModalVisible]);
|
||||
|
||||
useEffect(() => {
|
||||
if (templates.length > 0) {
|
||||
setCategories(getAllCategories(templates));
|
||||
}
|
||||
}, [templates]);
|
||||
|
||||
|
||||
const handleTemplateSelect = (templateId) => {
|
||||
setSelectedTemplateId(templateId);
|
||||
@@ -126,23 +131,6 @@ const QuotationPage = () => {
|
||||
setSelectedTemplateId(null);
|
||||
};
|
||||
|
||||
const getAllCategories = (templates) => {
|
||||
const categorySet = new Set();
|
||||
templates.forEach((template) => {
|
||||
template.attributes.category?.forEach((cat) => {
|
||||
categorySet.add(JSON.stringify(cat));
|
||||
});
|
||||
});
|
||||
return Array.from(categorySet).map((cat) => JSON.parse(cat));
|
||||
};
|
||||
|
||||
const getFilteredTemplates = () => {
|
||||
if (selectedCategory === "all") return templates;
|
||||
return templates.filter((template) =>
|
||||
template.attributes.category?.some((cat) => cat.id === selectedCategory)
|
||||
);
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
title: "报价单名称",
|
||||
@@ -333,6 +321,24 @@ const QuotationPage = () => {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
const fetchCustomers = async () => {
|
||||
setLoadingCustomers(true);
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('resources')
|
||||
.select('*')
|
||||
.eq('type', 'customer')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
setCustomers(data || []);
|
||||
} catch (error) {
|
||||
console.error('获取客户列表失败:', error);
|
||||
message.error('获取客户列表失败');
|
||||
} finally {
|
||||
setLoadingCustomers(false);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<Card
|
||||
@@ -344,15 +350,29 @@ const QuotationPage = () => {
|
||||
}
|
||||
className="h-full w-full overflow-auto"
|
||||
extra={
|
||||
<div className="flex justify-between my-4">
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setIsModalVisible(true)}
|
||||
>
|
||||
新增报价单
|
||||
</Button>
|
||||
</div>
|
||||
<Space>
|
||||
<Select
|
||||
allowClear
|
||||
loading={loadingCustomers}
|
||||
placeholder="按客户筛选"
|
||||
style={{ width: 200 }}
|
||||
options={customers.map(c => ({
|
||||
label: c.attributes.name,
|
||||
value: c.id
|
||||
}))}
|
||||
onChange={(value) => {
|
||||
setSelectedCustomer(value);
|
||||
setPagination({ current: 1, pageSize: pagination.pageSize });
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
onClick={() => setIsModalVisible(true)}
|
||||
>
|
||||
新增报价单
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
|
||||
@@ -177,7 +177,7 @@ const TaskTemplate = ({ id, isView, onCancel,isEdit }) => {
|
||||
title={
|
||||
<span className="flex items-center space-x-2 text-gray-700">
|
||||
<span className="w-1 h-4 bg-blue-500 rounded-full" />
|
||||
<span>服务明细</span>
|
||||
<span>相关任务</span>
|
||||
</span>
|
||||
}
|
||||
bordered={false}
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Spin,
|
||||
Modal,
|
||||
Empty,
|
||||
Select,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import {
|
||||
@@ -37,7 +38,8 @@ const TaskPage = () => {
|
||||
const [selectedTemplateId, setSelectedTemplateId] = useState(null);
|
||||
const [templates, setTemplates] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const [customers,setCustomers]=useState([])
|
||||
const [loadingCustomers, setLoadingCustomers] = useState(false);
|
||||
const {
|
||||
resources: tasks,
|
||||
loading: loadingTasks,
|
||||
@@ -45,11 +47,30 @@ const TaskPage = () => {
|
||||
fetchResources: fetchTasks,
|
||||
deleteResource: deleteTask,
|
||||
} = useResources(pagination, sorter, "task");
|
||||
const [selectedCustomer, setSelectedCustomer] = useState(null);
|
||||
|
||||
useEffect(() => {
|
||||
fetchTasks();
|
||||
fetchCustomers()
|
||||
}, []);
|
||||
const fetchCustomers = async () => {
|
||||
setLoadingCustomers(true);
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('resources')
|
||||
.select('*')
|
||||
.eq('type', 'customer')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (error) throw error;
|
||||
setCustomers(data || []);
|
||||
} catch (error) {
|
||||
console.error('获取客户列表失败:', error);
|
||||
message.error('获取客户列表失败');
|
||||
} finally {
|
||||
setLoadingCustomers(false);
|
||||
}
|
||||
};
|
||||
const columns = [
|
||||
{
|
||||
title: "任务名称",
|
||||
@@ -58,6 +79,24 @@ const TaskPage = () => {
|
||||
ellipsis: true,
|
||||
className: "dark:text-gray-200",
|
||||
},
|
||||
{
|
||||
title: "相关人员",
|
||||
dataIndex: ["attributes", "customers"],
|
||||
key: "customers",
|
||||
render: (customers, record) => (
|
||||
<Space>
|
||||
{customers?.map((customer) => (
|
||||
<Tag
|
||||
key={customer.id}
|
||||
color="blue"
|
||||
className="cursor-pointer"
|
||||
>
|
||||
{customer.name}
|
||||
</Tag>
|
||||
))}
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
dataIndex: ["attributes", "timeRange"],
|
||||
@@ -258,6 +297,7 @@ const TaskPage = () => {
|
||||
pageSize: pagination.pageSize,
|
||||
field: sorter.field,
|
||||
order: sorter.order,
|
||||
search: selectedCustomer ? JSON.stringify({ customerId: selectedCustomer }) : undefined
|
||||
});
|
||||
};
|
||||
|
||||
@@ -307,6 +347,29 @@ const TaskPage = () => {
|
||||
}
|
||||
className="h-full w-full overflow-auto dark:bg-gray-800 dark:border-gray-700"
|
||||
extra={
|
||||
<Space>
|
||||
<Select
|
||||
allowClear
|
||||
loading={loadingCustomers}
|
||||
placeholder="按客户筛选"
|
||||
variant="filled"
|
||||
style={{ width: 200 }}
|
||||
options={customers.map(c => ({
|
||||
label: c.attributes.name,
|
||||
value: c.id
|
||||
}))}
|
||||
onChange={(value) => {
|
||||
setSelectedCustomer(value);
|
||||
setPagination({ current: 1, pageSize: pagination.pageSize });
|
||||
fetchTasks({
|
||||
current: 1,
|
||||
pageSize: pagination.pageSize,
|
||||
field: sorter.field,
|
||||
order: sorter.order,
|
||||
search: value ? JSON.stringify({ customerId: value }) : undefined
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
type="primary"
|
||||
icon={<PlusOutlined />}
|
||||
@@ -315,6 +378,7 @@ const TaskPage = () => {
|
||||
>
|
||||
新增任务
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
>
|
||||
<Table
|
||||
|
||||
@@ -629,11 +629,11 @@ const StorageManager = () => {
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<Search
|
||||
<Input
|
||||
variant="filled"
|
||||
placeholder="搜索文件名..."
|
||||
allowClear
|
||||
onChange={(e) => setSearchText(e.target.value)}
|
||||
className="w-full"
|
||||
size="large"
|
||||
/>
|
||||
<div className=" p-3 rounded-lg shadow-sm">
|
||||
|
||||
@@ -25,6 +25,8 @@ export const MembershipTable = ({ memberships, onUpdate, onDelete, onAdd }) => {
|
||||
try {
|
||||
const row = await form.validateFields();
|
||||
setEditingKey('');
|
||||
console.log(row,'row');
|
||||
|
||||
onUpdate(key, row);
|
||||
} catch (error) {
|
||||
console.error('Save failed:', error);
|
||||
@@ -93,16 +95,20 @@ export const MembershipTable = ({ memberships, onUpdate, onDelete, onAdd }) => {
|
||||
</Space>
|
||||
) : (
|
||||
<Space>
|
||||
<Button
|
||||
|
||||
{!record.is_creator && (
|
||||
<>
|
||||
|
||||
|
||||
<Button
|
||||
disabled={editingKey !== '' || record.isCreator}
|
||||
icon={<EditOutlined />}
|
||||
onClick={() => edit(record)}
|
||||
type="link"
|
||||
size='small'
|
||||
size='small'
|
||||
>
|
||||
编辑
|
||||
</Button>
|
||||
{!record.isCreator && (
|
||||
<Popconfirm
|
||||
title="确定要删除该成员吗?"
|
||||
onConfirm={() => onDelete(record.id)}
|
||||
@@ -116,6 +122,7 @@ export const MembershipTable = ({ memberships, onUpdate, onDelete, onAdd }) => {
|
||||
删除
|
||||
</Button>
|
||||
</Popconfirm>
|
||||
</>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
|
||||
@@ -162,7 +162,6 @@ const TeamManagement = () => {
|
||||
try {
|
||||
await updateTeam(id, values);
|
||||
await loadTeams();
|
||||
message.success('更新团队成功');
|
||||
} catch (error) {
|
||||
message.error('更新团队失败');
|
||||
}
|
||||
|
||||
@@ -9,13 +9,19 @@ export const resourceService = {
|
||||
.eq('type', type)
|
||||
|
||||
if (searchQuery) {
|
||||
query = query.or(`external_id.ilike.%${searchQuery}%`);
|
||||
const searchParams = JSON.parse(searchQuery);
|
||||
if (searchParams.customerId) {
|
||||
query = query.filter('attributes->customers', 'cs',
|
||||
JSON.stringify([{id: searchParams.customerId}])
|
||||
);
|
||||
}
|
||||
}
|
||||
if (orderBy) {
|
||||
query = query.order(orderBy, { ascending });
|
||||
}
|
||||
const from = (page - 1) * pageSize;
|
||||
query = query.range(from, from + pageSize - 1);
|
||||
const to = from + pageSize - 1;
|
||||
query = query.range(from, to);
|
||||
|
||||
const { data, count, error } = await query;
|
||||
if (error) throw error;
|
||||
@@ -25,6 +31,7 @@ export const resourceService = {
|
||||
total: count || 0,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("获取资源列表失败:", error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user