Merge branch 'main' of github.com:xuqssq/uppmkt-admin

This commit is contained in:
‘Liammcl’
2024-12-28 19:24:06 +08:00
12 changed files with 259 additions and 175 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View File

@@ -1,18 +1,24 @@
import React from 'react'; import React from "react";
import { RocketOutlined } from '@ant-design/icons';
import { Typography } from 'antd';
const { Text } = Typography; import logo from "@/assets/logo.png";
import logoCollapsed from "@/assets/logo-collapsed.png";
export const Logo = ({ collapsed, isDarkMode }) => ( export const Logo = ({ collapsed, isDarkMode }) => (
<div className="logo"> <div className="logo">
<div className="flex items-center justify-center gap-2"> <div className="flex items-center justify-center gap-2">
<RocketOutlined className="text-2xl text-primary-500" /> {collapsed ? (
{!collapsed && ( <div className="flex items-center justify-center">
<Text className="text-lg font-semibold m-0" style={{ color: 'var(--primary-color)' }}> <img
Uppeta src={logoCollapsed}
</Text> alt="logo"
className="w-1/2 object-contain"
/>
</div>
) : (
<div className="flex items-center justify-center">
<img src={logo} alt="logo" className="w-1/2 object-contain mr-2" />
</div>
)} )}
</div> </div>
</div> </div>
); );

View File

@@ -15,7 +15,7 @@ const MainLayout = () => {
<Layout className="h-screen overflow-hidden"> <Layout className="h-screen overflow-hidden">
<Sidebar collapsed={collapsed} /> <Sidebar collapsed={collapsed} />
<Layout className="flex flex-col "> <Layout className="flex flex-col ">
<Header collapsed={collapsed} setCollapsed={setCollapsed} /> <Header collapsed={collapsed} setCollapsed={setCollapsed}/>
<Content <Content
className={` className={`
m-2 p-4 rounded-lg overflow-auto h-full m-2 p-4 rounded-lg overflow-auto h-full

View File

@@ -617,6 +617,7 @@ const SectionList = ({
max={100} max={100}
value={taxRate} value={taxRate}
onChange={(value) => setTaxRate(value)} onChange={(value) => setTaxRate(value)}
disabled={isView}
/> />
</div> </div>
</div> </div>

View File

@@ -143,13 +143,15 @@ const CustomerPage = () => {
} }
className='h-full w-full overflow-auto' className='h-full w-full overflow-auto'
extra={ extra={
<Button <div className="flex justify-between my-4">
type="primary" <Button
icon={<PlusOutlined />} type="primary"
onClick={() => navigate('/company/customerInfo')} icon={<PlusOutlined />}
> onClick={() => navigate("/company/customerInfo")}
新增客户 >
</Button> 新增客户
</Button>
</div>
} }
> >
<Table <Table

View File

@@ -1,20 +1,50 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from "react";
import { Card, Table, Button, message, Popconfirm, Tag, Space, Spin, Modal, Empty, Select, Typography, Statistic, Divider } from 'antd'; import {
import { PlusOutlined, EditOutlined, DeleteOutlined, EyeOutlined, CopyOutlined, FileAddOutlined, AppstoreOutlined } from '@ant-design/icons'; Card,
import { useResources } from '@/hooks/resource/useResource'; Table,
import { useNavigate } from 'react-router-dom'; Button,
import { supabase } from '@/config/supabase' message,
import { formatExchangeRate,EXCHANGE_RATE,defaultSymbol } from '@/utils/exchange_rate'; Popconfirm,
Tag,
Space,
Spin,
Modal,
Empty,
Select,
Typography,
Statistic,
Divider,
} from "antd";
import {
PlusOutlined,
EditOutlined,
DeleteOutlined,
EyeOutlined,
CopyOutlined,
FileAddOutlined,
AppstoreOutlined,
} from "@ant-design/icons";
import { useResources } from "@/hooks/resource/useResource";
import { useNavigate } from "react-router-dom";
import { supabase } from "@/config/supabase";
import {
formatExchangeRate,
EXCHANGE_RATE,
defaultSymbol,
} from "@/utils/exchange_rate";
const QuotationPage = () => { const QuotationPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [pagination, setPagination] = useState({ current: 1, pageSize: 10 }); const [pagination, setPagination] = useState({ current: 1, pageSize: 10 });
const [sorter, setSorter] = useState({ field: 'created_at', order: 'descend' }); const [sorter, setSorter] = useState({
field: "created_at",
order: "descend",
});
const [isModalVisible, setIsModalVisible] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false);
const [selectedTemplateId, setSelectedTemplateId] = useState(null); const [selectedTemplateId, setSelectedTemplateId] = useState(null);
const [templates, setTemplates] = useState([]); const [templates, setTemplates] = useState([]);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [selectedCategory, setSelectedCategory] = useState('all'); const [selectedCategory, setSelectedCategory] = useState("all");
const [categories, setCategories] = useState([]); const [categories, setCategories] = useState([]);
const { const {
@@ -22,8 +52,8 @@ const QuotationPage = () => {
loading: loadingQuotations, loading: loadingQuotations,
total, total,
fetchResources: fetchQuotations, fetchResources: fetchQuotations,
deleteResource: deleteQuotation deleteResource: deleteQuotation,
} = useResources(pagination, sorter, 'quota'); } = useResources(pagination, sorter, "quota");
useEffect(() => { useEffect(() => {
fetchQuotations(); fetchQuotations();
@@ -43,10 +73,10 @@ const QuotationPage = () => {
const handleDelete = async (id) => { const handleDelete = async (id) => {
try { try {
await deleteQuotation(id); await deleteQuotation(id);
message.success('删除成功'); message.success("删除成功");
fetchQuotations(); fetchQuotations();
} catch (error) { } catch (error) {
message.error('删除失败:' + error.message); message.error("删除失败:" + error.message);
} }
}; };
@@ -89,7 +119,7 @@ const QuotationPage = () => {
if (selectedTemplateId) { if (selectedTemplateId) {
navigate(`/company/quotaInfo?templateId=${selectedTemplateId}`); navigate(`/company/quotaInfo?templateId=${selectedTemplateId}`);
} else { } else {
navigate('/company/quotaInfo'); navigate("/company/quotaInfo");
} }
setIsModalVisible(false); setIsModalVisible(false);
setSelectedTemplateId(null); setSelectedTemplateId(null);
@@ -97,41 +127,41 @@ const QuotationPage = () => {
const getAllCategories = (templates) => { const getAllCategories = (templates) => {
const categorySet = new Set(); const categorySet = new Set();
templates.forEach(template => { templates.forEach((template) => {
template.attributes.category?.forEach(cat => { template.attributes.category?.forEach((cat) => {
categorySet.add(JSON.stringify(cat)); categorySet.add(JSON.stringify(cat));
}); });
}); });
return Array.from(categorySet).map(cat => JSON.parse(cat)); return Array.from(categorySet).map((cat) => JSON.parse(cat));
}; };
const getFilteredTemplates = () => { const getFilteredTemplates = () => {
if (selectedCategory === 'all') return templates; if (selectedCategory === "all") return templates;
return templates.filter(template => return templates.filter((template) =>
template.attributes.category?.some(cat => cat.id === selectedCategory) template.attributes.category?.some((cat) => cat.id === selectedCategory)
); );
}; };
const columns = [ const columns = [
{ {
title: '报价单名称', title: "报价单名称",
dataIndex: ['attributes', 'quataName'], dataIndex: ["attributes", "quataName"],
key: 'quataName', key: "quataName",
ellipsis: true, ellipsis: true,
}, },
{ {
title: '客户信息', title: "客户信息",
dataIndex: ['attributes', 'customers'], dataIndex: ["attributes", "customers"],
key: 'customers', key: "customers",
render: (customers, record) => ( render: (customers, record) => (
<Space> <Space>
{customers?.map(customer => ( {customers?.map((customer) => (
<Tag <Tag
key={customer.id} key={customer.id}
color="blue" color="blue"
className='cursor-pointer' className="cursor-pointer"
onClick={() => { onClick={() => {
navigate(`/company/customerInfo/${customer.id}`) navigate(`/company/customerInfo/${customer.id}`);
}} }}
> >
{customer.name} {customer.name}
@@ -141,61 +171,70 @@ const QuotationPage = () => {
), ),
}, },
{ {
title: '报价总额', title: "报价总额",
dataIndex: ['attributes'], dataIndex: ["attributes"],
key: 'totalAmount', key: "totalAmount",
align: 'right', align: "right",
render: (attributes) => { render: (attributes) => {
// 获取货币符号 // 获取货币符号
const currencySymbol = EXCHANGE_RATE[attributes?.currency]?.symbol || defaultSymbol; const currencySymbol =
EXCHANGE_RATE[attributes?.currency]?.symbol || defaultSymbol;
return ( return (
<div className="space-y-1"> <div className="space-y-1">
<div className="flex justify-between items-center text-sm"> <div className="flex justify-between items-center text-sm">
<Typography.Text type="secondary" style={{ fontSize: '12px' }}> <Typography.Text type="secondary" style={{ fontSize: "12px" }}>
税前{formatExchangeRate(attributes?.currency, attributes.beforeTaxAmount)} 税前
{formatExchangeRate(
attributes?.currency,
attributes.beforeTaxAmount
)}
</Typography.Text> </Typography.Text>
</div> </div>
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<Statistic <Statistic
value={formatExchangeRate(attributes?.currency, attributes.afterTaxAmount)} value={formatExchangeRate(
attributes?.currency,
attributes.afterTaxAmount
)}
precision={2} precision={2}
valueStyle={{ valueStyle={{
fontSize: '16px', fontSize: "16px",
fontWeight: 600, fontWeight: 600,
color: '#1890ff' color: "#1890ff",
}} }}
className="!mb-0" className="!mb-0"
/> />
</div> </div>
</div> </div>
); );
}, },
}, },
{ {
title: '创建日期', title: "创建日期",
dataIndex: 'created_at', dataIndex: "created_at",
key: 'created_at', key: "created_at",
sorter: true, sorter: true,
render: (text) => ( render: (text) => (
<span>{new Date(text).toLocaleString('zh-CN', { <span>
year: 'numeric', {new Date(text).toLocaleString("zh-CN", {
month: '2-digit', year: "numeric",
day: '2-digit', month: "2-digit",
hour: '2-digit', day: "2-digit",
minute: '2-digit' hour: "2-digit",
})}</span> minute: "2-digit",
})}
</span>
), ),
}, },
{ {
title: '操作', title: "操作",
key: 'action', key: "action",
fixed: 'right', fixed: "right",
render: (_, record) => ( render: (_, record) => (
<Space size={0}> <Space size={0}>
<Button <Button
size='small' size="small"
type="link" type="link"
icon={<CopyOutlined />} icon={<CopyOutlined />}
onClick={() => copyItem(record)} onClick={() => copyItem(record)}
@@ -203,7 +242,7 @@ const QuotationPage = () => {
复制 复制
</Button> </Button>
<Button <Button
size='small' size="small"
type="link" type="link"
icon={<EyeOutlined />} icon={<EyeOutlined />}
onClick={() => navigate(`/company/quotaInfo/preview/${record.id}`)} onClick={() => navigate(`/company/quotaInfo/preview/${record.id}`)}
@@ -211,10 +250,12 @@ const QuotationPage = () => {
查看 查看
</Button> </Button>
<Button <Button
size='small' size="small"
type="link" type="link"
icon={<EditOutlined />} icon={<EditOutlined />}
onClick={() => navigate(`/company/quotaInfo/${record.id}?edit=true`)} onClick={() =>
navigate(`/company/quotaInfo/${record.id}?edit=true`)
}
> >
编辑 编辑
</Button> </Button>
@@ -226,7 +267,7 @@ const QuotationPage = () => {
cancelText="取消" cancelText="取消"
okButtonProps={{ danger: true }} okButtonProps={{ danger: true }}
> >
<Button size='small' type="link" danger icon={<DeleteOutlined />}> <Button size="small" type="link" danger icon={<DeleteOutlined />}>
删除 删除
</Button> </Button>
</Popconfirm> </Popconfirm>
@@ -239,19 +280,21 @@ const QuotationPage = () => {
const groups = new Map(); const groups = new Map();
// 添加未分类组 // 添加未分类组
groups.set('uncategorized', { groups.set("uncategorized", {
name: '未分类', name: "未分类",
templates: templates.filter(t => !t.attributes.category || t.attributes.category.length === 0) templates: templates.filter(
(t) => !t.attributes.category || t.attributes.category.length === 0
),
}); });
// 按分类分组 // 按分类分组
templates.forEach(template => { templates.forEach((template) => {
if (template.attributes.category) { if (template.attributes.category) {
template.attributes.category.forEach(cat => { template.attributes.category.forEach((cat) => {
if (!groups.has(cat.id)) { if (!groups.has(cat.id)) {
groups.set(cat.id, { groups.set(cat.id, {
name: cat.name, name: cat.name,
templates: [] templates: [],
}); });
} }
groups.get(cat.id).templates.push(template); groups.get(cat.id).templates.push(template);
@@ -259,35 +302,35 @@ const QuotationPage = () => {
} }
}); });
return Array.from(groups.values()).filter(group => group.templates.length > 0); return Array.from(groups.values()).filter(
(group) => group.templates.length > 0
);
}; };
const copyItem = async (record) => { const copyItem = async (record) => {
try { try {
setLoading(true); setLoading(true);
// 深拷贝原有数据的 attributes // 深拷贝原有数据的 attributes
const newAttributes = JSON.parse(JSON.stringify(record.attributes)); const newAttributes = JSON.parse(JSON.stringify(record.attributes));
// 修改报价单名称,添加"副本"标识 // 修改报价单名称,添加"副本"标识
newAttributes.quataName = `${newAttributes.quataName} (副本)`; newAttributes.quataName = `${newAttributes.quataName} (副本)`;
// 创建新的报价单记录 // 创建新的报价单记录
const { data, error } = await supabase const { data, error } = await supabase.from("resources").insert([
.from('resources') {
.insert([ type: "quota",
{ attributes: newAttributes,
type: 'quota', },
attributes: newAttributes ]);
}
]);
if (error) throw error; if (error) throw error;
message.success('复制成功'); message.success("复制成功");
// 刷新列表 // 刷新列表
fetchQuotations(); fetchQuotations();
} catch (error) { } catch (error) {
console.error('复制报价单失败:', error); console.error("复制报价单失败:", error);
message.error('复制失败:' + error.message); message.error("复制失败:" + error.message);
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -301,19 +344,21 @@ const QuotationPage = () => {
<Tag color="blue">{total} 个报价单</Tag> <Tag color="blue">{total} 个报价单</Tag>
</Space> </Space>
} }
className='h-full w-full overflow-auto' className="h-full w-full overflow-auto"
extra={ extra={
<Button <div className="flex justify-between my-4">
type="primary" <Button
icon={<PlusOutlined />} type="primary"
onClick={() => setIsModalVisible(true)} icon={<PlusOutlined />}
> onClick={() => setIsModalVisible(true)}
新增报价单 >
</Button> 新增报价单
</Button>
</div>
} }
> >
<Table <Table
className='w-full' className="w-full"
columns={columns} columns={columns}
dataSource={quotations} dataSource={quotations}
rowKey="id" rowKey="id"
@@ -373,7 +418,7 @@ const QuotationPage = () => {
</div> </div>
<div className="grid grid-cols-3 gap-4"> <div className="grid grid-cols-3 gap-4">
{group.templates.map(template => ( {group.templates.map((template) => (
<div <div
key={template.id} key={template.id}
onClick={() => handleTemplateSelect(template.id)} onClick={() => handleTemplateSelect(template.id)}
@@ -381,8 +426,8 @@ const QuotationPage = () => {
relative p-4 rounded-xl cursor-pointer transition-all duration-200 relative p-4 rounded-xl cursor-pointer transition-all duration-200
${ ${
selectedTemplateId === template.id selectedTemplateId === template.id
? 'ring-2 ring-blue-500 bg-blue-50/40 dark:bg-blue-900/40' ? "ring-2 ring-blue-500 bg-blue-50/40 dark:bg-blue-900/40"
: 'hover:bg-gray-50 dark:hover:bg-gray-700/50 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md' : "hover:bg-gray-50 dark:hover:bg-gray-700/50 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md"
} }
dark:bg-gray-800 dark:bg-gray-800
`} `}
@@ -393,7 +438,7 @@ const QuotationPage = () => {
{template.attributes.templateName} {template.attributes.templateName}
</h4> </h4>
<p className="text-sm text-gray-600 dark:text-gray-400 mt-1 line-clamp-2"> <p className="text-sm text-gray-600 dark:text-gray-400 mt-1 line-clamp-2">
{template.attributes.description || '暂无描述'} {template.attributes.description || "暂无描述"}
</p> </p>
</div> </div>
<div className="text-blue-600 dark:text-blue-400 font-medium whitespace-nowrap"> <div className="text-blue-600 dark:text-blue-400 font-medium whitespace-nowrap">
@@ -422,7 +467,11 @@ const QuotationPage = () => {
{selectedTemplateId === template.id && ( {selectedTemplateId === template.id && (
<div className="absolute top-3 right-3"> <div className="absolute top-3 right-3">
<div className="w-5 h-5 bg-blue-500 dark:bg-blue-600 rounded-full flex items-center justify-center"> <div className="w-5 h-5 bg-blue-500 dark:bg-blue-600 rounded-full flex items-center justify-center">
<svg className="w-3 h-3 text-white" fill="currentColor" viewBox="0 0 20 20"> <svg
className="w-3 h-3 text-white"
fill="currentColor"
viewBox="0 0 20 20"
>
<path d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" /> <path d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" />
</svg> </svg>
</div> </div>
@@ -440,4 +489,4 @@ const QuotationPage = () => {
); );
}; };
export default QuotationPage; export default QuotationPage;

View File

@@ -1,21 +1,24 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from "react";
import { Card, Table, Button, message, Popconfirm, Tag, Space } from 'antd'; import { Card, Table, Button, message, Popconfirm, Tag, Space } from "antd";
import { PlusOutlined, EditOutlined, DeleteOutlined } from '@ant-design/icons'; import { PlusOutlined, EditOutlined, DeleteOutlined } from "@ant-design/icons";
import { useResources } from '@/hooks/resource/useResource'; import { useResources } from "@/hooks/resource/useResource";
import { useNavigate } from 'react-router-dom'; import { useNavigate } from "react-router-dom";
const SupplierPage = () => { const SupplierPage = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const [pagination, setPagination] = useState({ current: 1, pageSize: 10 }); const [pagination, setPagination] = useState({ current: 1, pageSize: 10 });
const [sorter, setSorter] = useState({ field: 'created_at', order: 'descend' }); const [sorter, setSorter] = useState({
field: "created_at",
order: "descend",
});
const { const {
resources: suppliers, resources: suppliers,
loading, loading,
total, total,
fetchResources: fetchSuppliers, fetchResources: fetchSuppliers,
deleteResource: deleteSupplier deleteResource: deleteSupplier,
} = useResources(pagination, sorter, 'supplier'); } = useResources(pagination, sorter, "supplier");
useEffect(() => { useEffect(() => {
fetchSuppliers(); fetchSuppliers();
@@ -35,66 +38,70 @@ const SupplierPage = () => {
const handleDelete = async (id) => { const handleDelete = async (id) => {
try { try {
await deleteSupplier(id); await deleteSupplier(id);
message.success('删除成功'); message.success("删除成功");
fetchSuppliers(); fetchSuppliers();
} catch (error) { } catch (error) {
message.error('删除失败:' + error.message); message.error("删除失败:" + error.message);
} }
}; };
const columns = [ const columns = [
{ {
title: '供应商名称', title: "供应商名称",
dataIndex: ['attributes', 'name'], dataIndex: ["attributes", "name"],
key: 'name', key: "name",
ellipsis: true, ellipsis: true,
}, },
{ {
title: '联系人', title: "联系人",
dataIndex: ['attributes', 'contact'], dataIndex: ["attributes", "contact"],
key: 'contact', key: "contact",
}, },
{ {
title: '电话', title: "电话",
dataIndex: ['attributes', 'phone'], dataIndex: ["attributes", "phone"],
key: 'phone', key: "phone",
}, },
{ {
title: '状态', title: "状态",
dataIndex: ['attributes', 'status'], dataIndex: ["attributes", "status"],
key: 'status', key: "status",
render: (status) => ( render: (status) => (
<Tag color={status === 'active' ? 'green' : 'red'}> <Tag color={status === "active" ? "green" : "red"}>
{status === 'active' ? '启用' : '禁用'} {status === "active" ? "启用" : "禁用"}
</Tag> </Tag>
), ),
}, },
{ {
title: '创建日期', title: "创建日期",
dataIndex: 'created_at', dataIndex: "created_at",
key: 'created_at', key: "created_at",
sorter: true, sorter: true,
render: (text) => ( render: (text) => (
<span>{new Date(text).toLocaleString('zh-CN', { <span>
year: 'numeric', {new Date(text).toLocaleString("zh-CN", {
month: '2-digit', year: "numeric",
day: '2-digit', month: "2-digit",
hour: '2-digit', day: "2-digit",
minute: '2-digit' hour: "2-digit",
})}</span> minute: "2-digit",
})}
</span>
), ),
}, },
{ {
title: '操作', title: "操作",
key: 'action', key: "action",
fixed: 'right', fixed: "right",
render: (_, record) => ( render: (_, record) => (
<Space size={0}> <Space size={0}>
<Button <Button
size='small' size="small"
type="link" type="link"
icon={<EditOutlined />} icon={<EditOutlined />}
onClick={() => navigate(`/company/supplierInfo/${record.id}?edit=true`)} onClick={() =>
navigate(`/company/supplierInfo/${record.id}?edit=true`)
}
> >
编辑 编辑
</Button> </Button>
@@ -106,7 +113,7 @@ const SupplierPage = () => {
cancelText="取消" cancelText="取消"
okButtonProps={{ danger: true }} okButtonProps={{ danger: true }}
> >
<Button size='small' type="link" danger icon={<DeleteOutlined />}> <Button size="small" type="link" danger icon={<DeleteOutlined />}>
删除 删除
</Button> </Button>
</Popconfirm> </Popconfirm>
@@ -123,15 +130,17 @@ const SupplierPage = () => {
<Tag color="blue">{total} 个供应商</Tag> <Tag color="blue">{total} 个供应商</Tag>
</Space> </Space>
} }
className='h-full w-full overflow-auto' className="h-full w-full overflow-auto"
extra={ extra={
<Button <div className="flex justify-between my-4">
type="primary" <Button
icon={<PlusOutlined />} type="primary"
onClick={() => navigate('/company/supplierInfo')} icon={<PlusOutlined />}
> onClick={() => navigate("/company/supplierInfo")}
新增供应商 >
</Button> 新增供应商
</Button>
</div>
} }
> >
<Table <Table
@@ -153,4 +162,4 @@ const SupplierPage = () => {
); );
}; };
export default SupplierPage; export default SupplierPage;

View File

@@ -30,9 +30,11 @@ const TaskPage = () => {
<Card <Card
title="任务管理" title="任务管理"
extra={ extra={
<Button type="primary" icon={<PlusOutlined />}> <div className="flex justify-between my-4">
新增任务 <Button type="primary" icon={<PlusOutlined />}>
</Button> 新增任务
</Button>
</div>
} }
> >
<Table columns={columns} dataSource={[]} rowKey="id" /> <Table columns={columns} dataSource={[]} rowKey="id" />

View File

@@ -35,9 +35,11 @@ const CommunicationTasks = () => {
<Card <Card
title="沟通任务" title="沟通任务"
extra={ extra={
<Button type="primary" icon={<PlusOutlined />}> <div className="flex justify-between my-4">
新增任务 <Button type="primary" icon={<PlusOutlined />}>
</Button> 新增任务
</Button>
</div>
} }
> >
<Table columns={columns} dataSource={[]} rowKey="id" /> <Table columns={columns} dataSource={[]} rowKey="id" />

View File

@@ -86,7 +86,7 @@ const ResourceTask = () => {
}, },
{ {
title: "操作", title: "操作",
fixed: 'right', fixed: "right",
key: "action", key: "action",
render: (_, record) => ( render: (_, record) => (
<Space size={0}> <Space size={0}>
@@ -136,13 +136,15 @@ const ResourceTask = () => {
} }
className="h-full w-full overflow-auto" className="h-full w-full overflow-auto"
extra={ extra={
<Button <div className="flex justify-between my-4">
type="primary" <Button
icon={<PlusOutlined />} type="primary"
onClick={() => navigate("/resource/task/edit")} icon={<PlusOutlined />}
> onClick={() => navigate("/resource/task/edit")}
新增任务 >
</Button> 新增任务
</Button>
</div>
} }
> >
<Table <Table

View File

@@ -206,4 +206,15 @@ html.dark::view-transition-old(root) {
.ant-menu { .ant-menu {
height: 100%; height: 100%;
border: none !important;
background-color: transparent !important;
}
.ant-layout-sider {
@apply rounded-r-xl dark:!bg-black/80
}
.ant-layout-header{
@apply rounded-b-sm ml-2
} }