您的位置:首页 > 文旅 > 美景 > 《网站推广策划》_设计公司宣传册_深圳营销型网站定制_2023推广平台

《网站推广策划》_设计公司宣传册_深圳营销型网站定制_2023推广平台

2024/12/28 9:47:43 来源:https://blog.csdn.net/u012877217/article/details/144486565  浏览:    关键词:《网站推广策划》_设计公司宣传册_深圳营销型网站定制_2023推广平台
《网站推广策划》_设计公司宣传册_深圳营销型网站定制_2023推广平台

目录

  • 1 加载后端的数据
  • 2 为什么不直接给变量赋值
  • 3 保存部门信息
  • 4 最终的效果
  • 5 总结

现在部门管理已经完成了后端功能和前端开发,就需要在前端调用后端的数据完成界面的展示,而且在录入部门信息后需要提交到数据库里,本篇我们介绍一下前后端如何交互。

1 加载后端的数据

现在后端API已经有了,页面加载的时候需要从后端读取数据。打开应用,点击编辑JSX代码

在这里插入图片描述
输入如下代码

export default function DepartmentTree(props: JSXCompProps) {const { $w, contentSlot1, style } = props;const { Modal, Input, Tree, Button, Form } = antd;const [treeData, setTreeData] = React.useState([]);const [selectedNode, setSelectedNode] = React.useState(null);const [addChildModalVisible, setAddChildModalVisible] = React.useState(false);const [newDepartmentName, setNewDepartmentName] = React.useState("");const [contextMenuTargetId, setContextMenuTargetId] = React.useState(null);const [contextMenuPosition, setContextMenuPosition] = React.useState(null);const [form] = Form.useForm();// 初始化获取部门数据React.useEffect(() => {async function fetchDepartments() {try {const result = await $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}});if (result && result.data) {setTreeData(result.data);} else {Modal.warning({ title: "数据加载失败", content: "未获取到部门数据。" });}} catch (error) {console.error("Error fetching departments:", error);Modal.error({ title: "加载失败", content: "获取部门数据时出错,请稍后重试。" });}}fetchDepartments();}, [$w]);// 点击节点事件const handleNodeClick = (node) => {setSelectedNode(node);setContextMenuTargetId(null);form.setFieldsValue({ name: node.name });};// 切换节点展开/收起const toggleNode = (node) => {node.isOpen = !node.isOpen;setTreeData([...treeData]);};// 递归更新树节点const updateTree = (nodes, callback) => {return nodes.map((node) => {if (callback(node)) {return { ...node };}if (node.children) {return { ...node, children: updateTree(node.children, callback) };}return node;});};// 添加子部门逻辑const handleAddChild = () => {if (!newDepartmentName.trim()) {return Modal.warning({title: "部门名称不能为空",content: "请输入部门名称后重试。"});}const newChild = {id: Date.now(),name: newDepartmentName,parentId: contextMenuTargetId,children: [],isOpen: false};setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === contextMenuTargetId) {node.children = [...(node.children || []), newChild];return true;}return false;}));setAddChildModalVisible(false);setNewDepartmentName("");};// 保存表单修改const handleSaveForm = () => {form.validateFields().then((values) => {setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === selectedNode.id) {node.name = values.name;return true;}return false;}));Modal.success({ title: "保存成功", content: "部门信息已更新。" });}).catch((info) => console.error("Validate Failed:", info));};// 右键点击事件const handleRightClick = (e, node) => {e.preventDefault();setContextMenuTargetId(node.id);setContextMenuPosition({ x: e.clientX, y: e.clientY });};// 渲染树节点const renderTree = (nodes) =>nodes.map((node) => (<Tree.TreeNodekey={node.id}title={<spanonClick={() => handleNodeClick(node)}onContextMenu={(e) => handleRightClick(e, node)}>{node.name}</span>}>{node.children && renderTree(node.children)}</Tree.TreeNode>));return (<div style={{ display: "flex", ...style }}>{/* 左侧树 */}<divstyle={{flex: "1",borderRight: "1px solid #ddd",overflowY: "auto",padding: "10px",minHeight: "300px"}}><Tree showLine defaultExpandAll>{renderTree(treeData)}</Tree></div>{/* 右侧表单 */}<divstyle={{flex: "2",padding: "10px",minHeight: "300px"}}>{selectedNode ? (<Form form={form} layout="vertical"><h3>部门信息</h3><Form.Itemlabel="部门名称"name="name"rules={[{ required: true, message: "请输入部门名称" }]}><Input /></Form.Item><Form.Item label="部门编号"><Input value={selectedNode.id} disabled /></Form.Item><div style={{ marginTop: "10px" }}><Buttontype="primary"onClick={handleSaveForm}style={{ marginRight: "10px" }}>保存</Button><Button onClick={() => form.resetFields()}>取消</Button></div></Form>) : (<p>请选择左侧树节点以查看或编辑部门信息。</p>)}</div>{/* 添加子部门 Modal */}<Modaltitle="添加子部门"visible={addChildModalVisible}onOk={handleAddChild}onCancel={() => setAddChildModalVisible(false)}><Inputplaceholder="请输入部门名称"value={newDepartmentName}onChange={(e) => setNewDepartmentName(e.target.value)}/></Modal>{/* 右键菜单 */}{contextMenuPosition && (<divstyle={{position: "absolute",top: contextMenuPosition.y,left: contextMenuPosition.x,backgroundColor: "#fff",boxShadow: "0 2px 8px rgba(0,0,0,0.15)",borderRadius: "4px",zIndex: 1000}}onMouseLeave={() => setContextMenuPosition(null)}><divonClick={() => setAddChildModalVisible(true)}style={{padding: "8px 16px",cursor: "pointer",borderBottom: "1px solid #f0f0f0"}}>添加子部门</div></div>)}{/* 插槽 */}<div>{contentSlot1}</div></div>);
}

我们追加了一个代码,主要是要异步调用后端API的

  // 初始化获取部门数据React.useEffect(() => {async function fetchDepartments() {try {const result = await $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}});if (result && result.data) {setTreeData(result.data);} else {Modal.warning({ title: "数据加载失败", content: "未获取到部门数据。" });}} catch (error) {console.error("Error fetching departments:", error);Modal.error({ title: "加载失败", content: "获取部门数据时出错,请稍后重试。" });}}fetchDepartments();}, [$w]);

这里的dataSourceName和methodName是从我们的API里获取的
在这里插入图片描述
部门管理旁边的相当于我们的dataSourceName,而标识相当于我们的methodName

2 为什么不直接给变量赋值

我一开始认为,我直接获取数据就可以,比如这样

const treeData = $w.cloud.callDataSource({dataSourceName: "departmentManagement_adpurdw",methodName: "getAllDepartments",params: {}
});

但这种操作发现树是空的,并没有从后台读取数据过来。主要的原因是两方面,首先callDataSource是异步的,你这个执行完了数据其实是没返回的

两一方面,数据加载完毕并不会通知React重新渲染组件。改成useEffect的好处是,在组件首次渲染后启动数据加载任务。当数据加载完成后,通过 setTreeData 更新组件状态,React 会自动重新渲染组件并展示新数据。

尤其如果部门比较多的情况下,界面可以先出来,等数据获取完毕组装好了再次渲染树形组件,这种体验就比较好了

3 保存部门信息

数据我们现在已经可以从变量中读取了,剩下就是添加的时候将新增的部门信息保存到数据源里。这里我们调用微搭的写入方法,修改如下代码

// 添加子部门逻辑const handleAddChild = () => {if (!newDepartmentName.trim()) {return Modal.warning({title: "部门名称不能为空",content: "请输入部门名称后重试。",});}// 调用数据源写入新部门$w.cloud.callDataSource({dataSourceName: "bmb", // 数据源名称methodName: "wedaCreateV2", // 假设存在 createDepartment 方法params: {data: {bmmc: newDepartmentName, // 部门名称fbm: { _id: contextMenuTargetId }, // 父部门ID},},}).then((response) => {const newId = response?.id; // 从响应中获取新节点的 IDif (!newId) {throw new Error("数据源未返回有效ID");}const newChild = {id: newId, // 使用后端返回的 IDname: newDepartmentName,parentId: contextMenuTargetId,children: [],isOpen: false,};// 更新前端树数据setTreeData((prevTreeData) =>updateTree(prevTreeData, (node) => {if (node.id === contextMenuTargetId) {node.children = [...(node.children || []), newChild];return true;}return false;}));// 关闭模态框并清空输入setAddChildModalVisible(false);setNewDepartmentName("");Modal.success({title: "添加成功",content: `子部门 "${newDepartmentName}" 已成功添加。`,});}).catch((error) => {console.error("数据源写入失败", error);Modal.error({title: "操作失败",content: "添加子部门时出现错误,请稍后重试。",});});};

需要把上边给的完整代码的handleAddChild 进行替换,这里主要是调用了微搭的创建单条的API。在创建的时候需要传递对应的数据,因为我们的父部门是关联关系,新版的关联关系是对象类型,所以我们是按照对象的结构组织了数据。

4 最终的效果

现在已经可以从数据库里读取部门的信息,并且按照树形的结构进行展示
在这里插入图片描述
点击右键的时候可以添加部门,数据库里可以看到写入的数据
在这里插入图片描述

5 总结

我们本篇介绍了如何将前后端的功能连接起来,从代码上来讲还是比较复杂的,主要需要考虑react组件加载的机制,副作用的理解,以及微搭的异步加载机制。要想理解好这些概念需要你亲自做一遍,才会有深入的体会。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com