Created
June 5, 2025 14:43
-
-
Save NanamiNakano/38701930ca454c09ac6c3f5f6e20a7b9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import User from "./UserType/User.ts" | |
| export default class ContractNegotiation { | |
| CNID: number | null; | |
| title: string; | |
| description: string; | |
| dateCreated: string; | |
| sender: User | null; | |
| constructor(cnid: number = null, title: string, description: string, sender: User | null = null) { | |
| this.CNID = cnid; | |
| this.title = title; | |
| this.description = description; | |
| this.dateCreated = new Date().toISOString(); | |
| this.sender = sender; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Input } from "@headlessui/react"; | |
| import { inputClassNames } from "../../env"; | |
| import ContractNegotiationModel from "../../models/ContractNegotiation"; | |
| import { useDispatch, useSelector } from "react-redux"; | |
| import { useCallback, useState } from "react"; | |
| import { UserCredential } from "../../models/UserCredential"; | |
| import { api } from "../../axios"; | |
| import PageRequest from "../../models/PageRequest"; | |
| import Pageable from "../../models/Pageable"; | |
| import { doInvalidCredentialAction } from "../../tools/AuthTools"; | |
| import { useNavigate } from "react-router"; | |
| import PageableList from "../../components/PageableList"; | |
| export default function ContractNegotiation() { | |
| function createEmptyContract() { | |
| return new ContractNegotiationModel( | |
| 0, | |
| "", | |
| "" | |
| ) | |
| } | |
| const { userInfo }: { userInfo: UserCredential } = useSelector( | |
| (s: any) => s.auth, | |
| ); | |
| const [currentContract, setCurrentContract] = useState<ContractNegotiationModel>(createEmptyContract()); | |
| const [pageContent, setPageContent] = useState<Pageable | null>(null); | |
| const navigate = useNavigate(); | |
| const dispatch = useDispatch(); | |
| console.log(userInfo) | |
| async function refresh(page = 0) { | |
| const pr = new PageRequest(); | |
| try { | |
| const result = await api.Trade.getListedCoNes( | |
| page, | |
| userInfo.token, | |
| pr, | |
| ); | |
| if (result.status === 200 && result.content) { | |
| const pageData = JSON.parse(result.content) as Pageable; | |
| setPageContent(pageData); | |
| } | |
| } catch (error: any) { | |
| if (error.message.includes("401")) { | |
| doInvalidCredentialAction(dispatch, navigate); | |
| } else console.error("加载员工数据失败:", error); | |
| } | |
| } | |
| const createContract = useCallback(async () => { | |
| try { | |
| const result = await api.Trade.createContractNegotiation( | |
| userInfo.token, | |
| currentContract, | |
| ); | |
| if (result.status === 200) { | |
| alert("操作成功!"); | |
| refresh(); | |
| setCurrentContract(createEmptyContract()); | |
| } else { | |
| alert(`操作失败: ${result.message || "未知错误"}`); | |
| } | |
| } catch (error: any) { | |
| console.error("操作失败:", error); | |
| alert(`操作失败: ${error.message || "未知错误"}`); | |
| } | |
| }, [currentContract, userInfo.token]); | |
| return ( | |
| <> | |
| <h1 className="text-3xl font-semibold">合同谈判</h1> | |
| <div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mt-4"> | |
| {/* 合同谈判表单 */} | |
| <div> | |
| <h2 className="text-xl font-semibold mb-4">标题</h2> | |
| <div className="space-y-3"> | |
| <Input | |
| className={inputClassNames} | |
| placeholder="标题" | |
| type="text" | |
| value={currentContract.title || ""} | |
| onChange={e => | |
| setCurrentContract(prev => ({ ...prev, title: e.target.value })) | |
| } | |
| /> | |
| <Input | |
| className={inputClassNames} | |
| placeholder="描述" | |
| type="text" | |
| value={currentContract.description || ""} | |
| onChange={e => | |
| setCurrentContract(prev => ({ ...prev, description: e.target.value })) | |
| } | |
| /> | |
| </div> | |
| <div className="flex gap-2 mt-4"> | |
| <button | |
| onClick={() => createContract()} | |
| className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600" | |
| > | |
| 提交 | |
| </button> | |
| <button | |
| onClick={() => setCurrentContract(createEmptyContract())} | |
| className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600" | |
| > | |
| 清空表单 | |
| </button> | |
| </div> | |
| </div> | |
| {/* 工单列表 */} | |
| <div> | |
| <h2 className="text-xl font-semibold mb-4">工单列表</h2> | |
| <button | |
| onClick={() => refresh()} | |
| className="mb-2 px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600" | |
| > | |
| 刷新列表 | |
| </button> | |
| <PageableList page={pageContent} /> | |
| </div> | |
| </div> | |
| {/* 当前员工信息调试显示 */} | |
| <div className="mt-6"> | |
| <details> | |
| <summary className="cursor-pointer text-sm text-gray-600"> | |
| 调试信息 | |
| </summary> | |
| <pre className="text-xs bg-gray-100 p-2 rounded mt-2"> | |
| {JSON.stringify(currentContract, null, 2)} | |
| </pre> | |
| </details> | |
| </div> | |
| </> | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment