ant-design实现树的穿梭框,穿梭后右侧是已选树(二)

news2024/11/30 20:28:31

 根据上一篇目标一,进一步实现树的穿梭框

主要内容:

基于ant-design树的穿梭框,实现穿梭后右侧是已选树,(当前antd右侧只有一个层级)

理想的树的穿梭框:

左边是完整的树,右边是已选的树,左边已选穿梭到右边,左边已选的消失,右边增加已选,右边也可以勾选然后穿梭回去左边,左边出现右边消失。

目标1:右边是已选的树,左边已选穿梭到右边,左边树不变可以继续操作,右边只可以看结果 

目标2:右边是已选的树,左边已选穿梭到右边,左边已选的消失掉,右边可以选择穿梭回去 

主要核心办法:左边不展示已被穿梭的数据(不改变左边的原数组,采用隐藏的方式,已经被穿梭的或者子集全部被穿梭的不展示)

目标2:目前效果 

步骤一:把目标一的搜索进行优化

改动代码:

  onSearch={(dir, val) => {
            if (dir === 'left') { // 左边搜索
              if (val !== '') {
                const newDeptList = this.onsearchDataSource(dataSource, val);
                this.setState({ newDataSource: newDeptList });
              } else {
                this.setState({ newDataSource: dataSource });// 左边没搜索时候的原始数据
              }
            } else { //右边搜索
              if (val !== '') {
                const newDeptList = this.onsearchDataSource(rightDataSource, val);
                this.setState({ newRightDataSource: newDeptList });
              } else {
                this.setState({ newRightDataSource: rightDataSource }); // 右边没搜索时候的原始数据
              }
            }
          }}
// 树搜索函数 
onsearchDataSource(dataSource, val) {
    // 递归查找存在的父级
    const deepFilter = (i, val) => {
      return (
        i.children.filter((o) => {
          if (o.label.indexOf(val) > -1) {
            return true;
          }
          if (o.children && o.children.length > 0) {
            return deepFilter(o, val);
          }
        }).length > 0
      );
    };
    const filterMenu = (list, val) => {
      return list
        .filter((item) => {
          if (item.label.indexOf(val) > -1) {
            return true;
          }
          if (item.children && item.children.length > 0) {
            return deepFilter(item, val);
          }
          return false;
        })
        .map((item) => {
          item = Object.assign({}, item);
          if (item.children) {
            item.children = item.children.filter((res) => res.label.indexOf(val) > -1);
            filterMenu(item.children, val);
          }
          return item;
        });
    };
    return filterMenu(dataSource, val);
  }

步骤二:把目标onCheck函数进行更新

onCheck={(_, even) => {
                    const {
                      checkedNodes,
                      node: {
                        props: { eventKey },
                      },
                    } = even;
                    // 筛选出最底层的子集 集合
                    const checkedChildKeys = checkedNodes.reduce((arr, e) => {
                      if (e.props.children.length <= 0) {
                        arr.push(e.key);
                      }
                      return arr;
                    }, []);
           
                    if (_.length > 0) {
                      this.setState({ currTargetKeys: lodash.union(targetKeys, checkedChildKeys) });
                      onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
                      // 增加随机数 为了可以触发向右穿梭的按钮 触发后删除随机数
                      onItemSelect('DEL' + Math.random(), true);
                    } else {
                  // 加上如果勾来勾去又没勾的情况
                      this.setState({ currTargetKeys: targetKeys });
                    }
                  }}
 

左边的tree : 

if (direction === 'left') {
              const checkedKeys = [...selectedKeys, ...currTargetKeys];
              return newDataSource.length > 0 ? (
                <Tree
                  blockNode
                  showLine
                  defaultExpandParent={true}
                  disabled={disabled}
                  checkable
                  checkedKeys={checkedKeys}
                  onCheck={(_, even) => {
                    const {
                      checkedNodes,
                      node: {
                        props: { eventKey },
                      },
                    } = even;
                    // 筛选出最底层的子集 集合
                    const checkedChildKeys = checkedNodes.reduce((arr, e) => {
                      if (e.props.children.length <= 0) {
                        arr.push(e.key);
                      }
                      return arr;
                    }, []);
                    if (_.length > 0) {
                      this.setState({ currTargetKeys: lodash.union(targetKeys, checkedChildKeys) });
                      onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
                      // 增加随机数 为了可以触发向右穿梭的按钮 触发后删除随机数
                      onItemSelect('DEL' + Math.random(), true);
                    } else {
                      this.setState({ currTargetKeys: targetKeys });
                    }
                  }}>
                  {generateTree(newDataSource, targetKeys, searchValue, disabled, 'left')}
                </Tree>
              ) : (
                <div></div>
              );
            }

右边的tree :

// 右边从纯展示变成了可更改 所以增加已选的操作
if (direction === 'right') {
              const checkedKeys = [...rightCurrTargetKeys];
              return newRightDataSource.length > 0 ? (
                <Tree
                  blockNode
                  showLine
                  checkable
                  defaultExpandAll={true}
                  disabled={disabled}
                  checkedKeys={checkedKeys}
                  onCheck={(_, even) => {
                    const {
                      checkedNodes,
                      node: {
                        props: { eventKey },
                      },
                    } = even;
                    // 筛选出最底层的子集 集合
                    const checkedChildKeys = checkedNodes.reduce((arr, e) => {
                      if (e.props.children.length <= 0) {
                        arr.push(e.key);
                      }
                      return arr;
                    }, []);
                    //  勾选后更改左侧已选定内容
                    this.setState({ currTargetKeys: lodash.xor(checkedChildKeys, targetKeys) });
                    // 设置右侧已勾选框
                    this.setState({ rightCurrTargetKeys: checkedChildKeys });
                    onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
                  }}>
                  {generateTree(newRightDataSource, targetKeys, searchValue, false, 'right')}
                </Tree>
              ) : (
                <div></div>
              );
            }

步骤三:generateTree展示的更新

目标一:左边没变

目标二:左边减少上次已穿梭的内容,右边增加新穿梭的内容,

// 不改变左边的原数组,采用隐藏的方式,已经被穿梭的或者子集全部被穿梭的不展示label
const generateTree = (treeNodes = [], checkedKeys = [], searchValue, disabled = false, type = 'left') => {
  return treeNodes.map(({ children, ...props }) => {
    if (type === 'left') {
      // 是否子元素都被选择了 如果是则父不展示了
      const isAll =
        children &&
        lodash.every(children, (e) => {
          return checkedKeys.includes(e.key);
        });
// 自己是否被穿梭了 穿梭了则不展示了 !checkedKeys.includes(props.key)
      return !isAll && !checkedKeys.includes(props.key) ? (
        <TreeNode
          {...props}
          disabled={disabled}
          key={props.key}
          title={
            <Tooltip placement='topLeft' title={props.label}>
              <span className='title-over'>{props.label}</span>
            </Tooltip>
          }>
          {generateTree(children, checkedKeys, searchValue, disabled, type)}
        </TreeNode>
      ) : (
        ''
      );
    } else {
// 右边的展示内容
      return (
        <TreeNode
          {...props}
          disabled={disabled}
          key={props.key}
          title={
            <Tooltip placement='topLeft' title={props.label}>
              <span className='title-over'>
                {props.label}
              </span>
            </Tooltip>
          }>
          {generateTree(children, checkedKeys, searchValue, disabled, type)}
        </TreeNode>
      );
    }
  });
};

TreeTransfer 整个组件代码

import React, { Component } from 'react';
import './index.less';
import { Transfer, Tree, Tooltip } from 'antd';
import lodash from 'lodash';
const { TreeNode } = Tree;
const isChecked = (selectedKeys, eventKey) => {
  return selectedKeys.indexOf(eventKey) !== -1;
};

const generateTree = (treeNodes = [], checkedKeys = [], searchValue, disabled = false, type = 'left') => {
  return treeNodes.map(({ children, ...props }) => {
    if (type === 'left') {
      // 是否子元素都被选择了
      const isAll =
        children &&
        lodash.every(children, (e) => {
          return checkedKeys.includes(e.key);
        });
      return !isAll && !checkedKeys.includes(props.key) ? (
        <TreeNode
          {...props}
          disabled={disabled}
          key={props.key}
          title={
            <Tooltip placement='topLeft' title={props.label}>
              <span className='title-over'>{props.label}</span>
            </Tooltip>
          }>
          {generateTree(children, checkedKeys, searchValue, disabled, type)}
        </TreeNode>
      ) : (
        ''
      );
    } else {
      return (
        <TreeNode
          {...props}
          disabled={disabled}
          key={props.key}
          title={
            <Tooltip placement='topLeft' title={props.label}>
              <span className='title-over' style={{ color: props.label.indexOf(searchValue) >= 0 ? 'red' : '' }}>
                {props.label}
              </span>
            </Tooltip>
          }>
          {generateTree(children, checkedKeys, searchValue, disabled, type)}
        </TreeNode>
      );
    }
  });
};

class TreeTransfer extends Component {
  constructor(props, context) {
    super(props, context);
    this.stores = this.props.UserMgtMod;
    this.state = {
      searchValue: null,
      transferDataSource: [],
      currTargetKeys: [],
      rightCurrTargetKeys: [],
      defaultExpandAll: true,
      newDataSource: [],
      newRightDataSource: [],
    };
  }
  componentDidMount() {
    const { dataSource, targetKeys, rightDataSource } = this.props;
    this.flatten(dataSource);
    this.setState({
      currTargetKeys: targetKeys,
      newDataSource: dataSource,
      newRightDataSource: rightDataSource,
    });
  }
  UNSAFE_componentWillReceiveProps(nextprops) {
    const { dataSource, targetKeys, rightDataSource } = nextprops;
    this.flatten(nextprops.dataSource);
    this.setState({
      currTargetKeys: targetKeys,
      newDataSource: dataSource,
      newRightDataSource: rightDataSource,
    });
  }
  flatten(list = []) {
    const dataSource = this.state.transferDataSource;
    list.forEach((item) => {
      dataSource.push(item);
      this.setState({ transferDataSource: dataSource });
      this.flatten(item.children);
    });
  }
  onChange(e) {
    this.setState({
      searchValue: e.target.value,
    });
  }
  onsearchDataSource(dataSource, val) {
    // 递归查找存在的父级
    const deepFilter = (i, val) => {
      return (
        i.children.filter((o) => {
          if (o.label.indexOf(val) > -1) {
            return true;
          }
          if (o.children && o.children.length > 0) {
            return deepFilter(o, val);
          }
        }).length > 0
      );
    };
    const filterMenu = (list, val) => {
      return list
        .filter((item) => {
          if (item.label.indexOf(val) > -1) {
            return true;
          }
          if (item.children && item.children.length > 0) {
            return deepFilter(item, val);
          }
          return false;
        })
        .map((item) => {
          item = Object.assign({}, item);
          if (item.children) {
            item.children = item.children.filter((res) => res.label.indexOf(val) > -1);
            filterMenu(item.children, val);
          }
          return item;
        });
    };
    return filterMenu(dataSource, val);
  }
  render() {
    const { dataSource, targetKeys, rightDataSource, disabled, ...restProps } = this.props;
    const { transferDataSource, searchValue, currTargetKeys, rightCurrTargetKeys, newDataSource, newRightDataSource } = this.state;

    return (
      <div>
        <Transfer
          {...restProps}
          disabled={disabled}
          targetKeys={currTargetKeys}
          dataSource={transferDataSource}
          className='tree-transfer'
          render={(item) => item.label}
          showSearch
          showSelectAll={false}
          onSearch={(dir, val) => {
            if (dir === 'left') {
              if (val !== '') {
                const newDeptList = this.onsearchDataSource(dataSource, val);
                this.setState({ newDataSource: newDeptList });
              } else {
                this.setState({ newDataSource: dataSource });
              }
            } else {
              if (val !== '') {
                const newDeptList = this.onsearchDataSource(rightDataSource, val);
                this.setState({ newRightDataSource: newDeptList });
              } else {
                this.setState({ newRightDataSource: rightDataSource });
              }
            }
          }}>
          {({ direction, onItemSelect, selectedKeys }) => {
            if (direction === 'left') {
              const checkedKeys = [...selectedKeys, ...currTargetKeys];
              return newDataSource.length > 0 ? (
                <Tree
                  blockNode
                  showLine
                  defaultExpandParent={true}
                  disabled={disabled}
                  checkable
                  checkedKeys={checkedKeys}
                  onCheck={(_, even) => {
                    const {
                      checkedNodes,
                      node: {
                        props: { eventKey },
                      },
                    } = even;
                    // 筛选出最底层的子集 集合
                    const checkedChildKeys = checkedNodes.reduce((arr, e) => {
                      if (e.props.children.length <= 0) {
                        arr.push(e.key);
                      }
                      return arr;
                    }, []);
                    if (_.length > 0) {
                      this.setState({ currTargetKeys: lodash.union(targetKeys, checkedChildKeys) });
                      onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
                      // 增加随机数 为了可以触发向右穿梭的按钮 触发后删除随机数
                      onItemSelect('DEL' + Math.random(), true);
                    } else {
                      this.setState({ currTargetKeys: targetKeys });
                    }
                  }}>
                  {generateTree(newDataSource, targetKeys, searchValue, disabled, 'left')}
                </Tree>
              ) : (
                <div></div>
              );
            }
            if (direction === 'right') {
              const checkedKeys = [...rightCurrTargetKeys];
              return newRightDataSource.length > 0 ? (
                <Tree
                  blockNode
                  showLine
                  checkable
                  defaultExpandAll={true}
                  disabled={disabled}
                  checkedKeys={checkedKeys}
                  onCheck={(_, even) => {
                    const {
                      checkedNodes,
                      node: {
                        props: { eventKey },
                      },
                    } = even;
                    // 筛选出最底层的子集 集合
                    const checkedChildKeys = checkedNodes.reduce((arr, e) => {
                      if (e.props.children.length <= 0) {
                        arr.push(e.key);
                      }
                      return arr;
                    }, []);
                    //  勾选后更改左侧已选定内容
                    this.setState({ currTargetKeys: lodash.xor(checkedChildKeys, targetKeys) });
                    // 设置右侧已勾选框
                    this.setState({ rightCurrTargetKeys: checkedChildKeys });
                    onItemSelect(eventKey, !isChecked(checkedKeys, eventKey));
                  }}>
                  {generateTree(newRightDataSource, targetKeys, searchValue, false, 'right')}
                </Tree>
              ) : (
                <div></div>
              );
            }
          }}
        </Transfer>
      </div>
    );
  }
}
export default TreeTransfer;

 组件引用案例:


        <Modal
          width={1000}
          title={'所属角色'}
          className='user-modal'
          visible={this.state.roleModal}
          onOk={() => {
            this.setState({ roleModal: false, rightDataSource: [] });
          }}
          onCancel={() => {
            this.setState({ roleModal: false, rightDataSource: [] });
          }}>
          <Spin spinning={roleLoading}> 
            {this.state.roleModal && (
              <TreeTransfer
                disabled={'' + title === 'detail' ? true : false}
                dataSource={roleList} // 原始树结构
                rightDataSource={rightDataSource}
                targetKeys={roleTargetKeys}
                onChange={this.handleChange.bind(this)}
              />
            )}
          </Spin>
        </Modal>

 关键函数

 handleChange = (newTargetKeys) => {
    const targetKeys = newTargetKeys.reduce((arr, e) => {
      // 增加随机数 为了可以触发向右穿梭的按钮 触发后删除随机数
      if (e.indexOf('DEL') < 0) {
        arr.push(e);
      }
      return arr;
    }, []);
    // 递归查找是否存在包含选中key的父级 
    const deepFilter = (i, arr) => {
      return (
        i.children.filter((o) => {
          if (arr.includes(o.key)) {
            return true;
          }
          if (o.children && o.children.length > 0) {
            return deepFilter(o, arr);
          }
        }).length > 0
      );
    };
  // 找到一个存在key的父级 然后遍历获取层级内容
    const filterMenu = (list, arr) => {
      return list
        .filter((item) => {
          if (arr.includes(item.key)) {
            return true;
          }
          if (item.children && item.children.length > 0) {
            return deepFilter(item, arr);
          }
          return false;
        })
        .map((item) => {
          item = Object.assign({}, item);
          if (item.children) {
            item.children = filterMenu(item.children, arr);
          }
          return item;
        });
    };
    if (this.state.roleModal) {
      const { roleList } = toJS(this.stores.state);
      this.setState({ roleTargetKeys: [...new Set(targetKeys)] }); // 去重
      const rightDataSource = filterMenu(roleList, targetKeys); // 查询组装已选树
      this.stores.saveInfoModal({ roleIds: targetKeys });
      this.props.form.setFieldsValue({ roleIds: targetKeys });
      this.setState({ rightDataSource: rightDataSource || [] });
    }
   
  };

 触发方法:

  <div style={{ display: 'flex' }}>
              <YxButton
                type='primary'
                style={{ marginRight: '10px' }}
                onClick={() => {
                  this.setState({ roleModal: true });
                  setTimeout(() => {
                    this.handleChange(this.state.roleTargetKeys);
                  }, 100);
                }}>
                {'' + title === 'detail' ? '查看' : '请选择'}
              </YxButton>
              已选{this.state.roleTargetKeys.length}项
            </div>

 目标二就完成了

 ​

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/527711.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java面试知识点(全)- DB mysql面试知识点

[Java面试知识点(全) 导航&#xff1a; https://nanxiang.blog.csdn.net/article/details/130640392 注&#xff1a;随时更新 SQL优化 r m y s q l q u e r y ( " S E L E C T u s e r n a m e F R O M u s e r W H E R E s i g n u p d a t e > ′ r mysql_query(…

美国原油CFD价格波动受到哪些因素影响?

经过多年的发展&#xff0c;石油技术已经从煤炭转向原油作为主要能源&#xff0c;这种商品用于各种产品&#xff0c;包括汽油、塑料、药品等。因此&#xff0c;它的价值很高&#xff0c;美国原油CFD价格变动时全世界都在关注。对于交易者来说&#xff0c;美国原油CFD价格波动性…

从零开始Vue3+Element Plus的后台管理系统(五)——尝试多种图标ICON方案iconify

iconfont是过去使用较多的图标方案&#xff0c;后来更倾向于使用SVG&#xff0c;因为SVG更灵活兼容性更好。在最近的几个Vue2项目中&#xff0c;因为强调功能弱化设计所以直接用Element UI自带的图标即可满足需求。 Element Plus的图标库相对Element UI更加丰富&#xff0c;然…

flac格式如何转mp3?这几种方法快收藏起来吧

将FLAC格式转换为MP3格式&#xff0c;可以使用一些转换工具&#xff0c;如优速音频处理器等&#xff0c;也可以使用其他专业音频转换软件。FLAC是一种无损音频编码格式&#xff0c;通常用于保留原始音频质量&#xff0c;但相应的文件大小较大。而MP3是一种有损压缩音频编码格式…

MFC类继承实现CEdit自绘文字颜色,边框,背景色

效果 新建一个继承于CEdit的类CMyEdit 在他的窗体OnNcPaint函数中实现绘制边框,它所响应的消息是WM_NCPAINT void CMyEdit::OnNcPaint() {// TODO: 在此处添加消息处理程序代码// 不为绘图消息调用 CEdit::OnNcPaint()////执行默认的窗体处理过程Default();

linux环境安装使用FastDFS,FastDHT详解

01-简介 GitHub&#xff1a;happyfish100 (YuQing) GitHub FastDFS高性能的分布式文件系统&#xff0c;主要功能包含文件的存储、同步、访问&#xff08;上传和下载&#xff09;&#xff0c;特别适用于以文件为主体的网络站点&#xff08;图片分享和视频分享&#xff09;。 Fa…

2023年Java面试正确姿势(1000+面试题附答案解析)

前言 2023 跳槽不迷茫&#xff0c;大家可以先收藏再看&#xff0c;后续跳槽都能用上的&#xff01; 一键获取最新java文档。 Java程序员绝大部分工作的时间都是增删改查&#xff0c;很多人觉得这项工作没什么技术含量&#xff0c;任何一件事情都要站在不同的角度去考虑&#xf…

shell的数组

数组定义方法 方法一&#xff1a;数组名&#xff08; value0 value1 value2 ...&#xff09; 方法二&#xff1a;数组名&#xff08;[0]value [1]value [2]value...&#xff09; 方法三&#xff1a;列表名"value0 value1 value2 ..." 数组名&#xff08;$列表名&…

【WLAN从入门到精通-基础篇】

WLAN定义和基本架构 本文参考https://forum.huawei.com/enterprise/zh/thread/580888898454831104 1. WLAN定义 WLAN的全称是Wireless Local Area Network&#xff0c;中文含义是无线局域网&#xff0c;WLAN的定义有广义和狭义两种&#xff1a;广义上讲WLAN是以各种无线电波…

使用Kotlin函数式编程技术构建强大的 Android 应用程序

使用Kotlin函数式编程技术构建强大的 Android 应用程序 Kotlin 是一种现代的多用途编程语言&#xff0c;在 Android 应用程序开发人员中迅速流行起来。Kotlin 有别于其他编程语言的关键特性之一是它对函数式编程的强大支持。Kotlin 函数式编程允许开发人员编写更清晰、更简洁、…

本地生活服务:老将、新秀同台竞技

配图来自Canva可画 本地生活服务领域又热闹起来了。 事实上&#xff0c;本地生活服务一直为各路玩家所看好。最近几年&#xff0c;互联网大厂频频布局本地生活服务领域&#xff0c;其中抖音、快手等短视频平台更是持续加大在本地生活服务领域的布局力度。 前不久&#xff0c…

Grafana系列-统一展示-10-Explore Jaeger

系列文章 Grafana 系列文章 Explore Jaeger 你可以通过Explore查询和显示 Jaeger 的 trace。有 3 种方法: Query by searchQuery by trace IDUpload a JSON trace file Query by search 要使用该方法: 从 Query 类型选择器中选择 Search。填写搜索表格&#xff1a;(和 J…

2023第十三届中国数字营销与电商创新峰会 嘉宾揭晓

2023第十三届中国数字营销与电商创新峰会将于7月6日-7日在上海召开。 本次峰会将通过七大热点主题帮助品牌主突破模式能力&#xff0c;回归初心、精耕细作&#xff0c;实现可持续增长&#xff1b;提升产品能力&#xff0c;实现可持续长期增长&#xff1b;优化营销能力&#xf…

HTTP第11讲——HTTP的特点

灵活可扩展 首先&#xff0c; HTTP 协议是一个“灵活可扩展”的传输协议。 HTTP 协议最初诞生的时候就比较简单&#xff0c;本着开放的精神只规定了报文的基本格式&#xff0c;比如用空格分隔单词&#xff0c;用换行分隔字段&#xff0c;“headerbody”等&#xff0c;报文里的…

分析车载蓝牙通话只有前喇叭声音,后面喇叭无声背后原因

车载蓝牙通话只有前喇叭声音&#xff0c;后面喇叭无声背后原因 大家有没有注意到车载蓝牙连接后通话的时候只有前喇叭的有声音&#xff0c;后面喇叭没声音呢&#xff1f;特别是后装的车载多媒体上基本都是这样&#xff0c;细思下为什么这样的原因&#xff0c; 采访后装车载技术…

【软考备战·五月模考】希赛网五月模考软件设计师上午题

文章目录 一、成绩报告二、错题总结第一题第二题第三题第四题第五题第六题第七题第八题第九题第十题第十一题第十二题 三、知识查缺 题目及解析来源&#xff1a;2023上半年软考-模考大赛 一、成绩报告 二、错题总结 第一题 解析&#xff1a; 瀑布模型 中各个活动按 线性顺序 连…

【Spring全家桶系列】AspectJ表达式的书写与SpringAOP下的五种通知类型

⭐️前面的话⭐️ 本文已经收录到《Spring框架全家桶系列》专栏&#xff0c;本文将介绍AspectJ表达式的书写与SpringAOP下的五种通知类型。 &#x1f4d2;博客主页&#xff1a;未见花闻的博客主页 &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4…

基于ArcGIS实现陕西省1:250000比例尺地形图分幅和编号

1地形图的分幅与编号原理 我国1:1000000地形图的分幅采用国际1:1000000地图分幅标准&#xff0c;而其他比例尺地形图分幅以1:1000000比例尺地形图为基准进行分幅。每幅1:1000000地形图范围是经差6、纬差4&#xff1b;纬度60~ 76之间经差12、纬差4&#xff1b;纬度76~ 88之间经…

数据结构之数组对栈的实现

目录 1.什么是栈 2.栈的基本操作 3.栈的实现 1.结构体与函数接口 2.初始化栈 3.销毁栈 4.入栈 5.出栈 6.返回栈元素数量大小 7.判空 8.打印栈 1.什么是栈 栈是一种特殊的线性表&#xff0c;其中只允许固定的一端进行插入与删除&#xff0c;进行输出插入删除的那一端我…

振幅调制器【Multisim】【高频电子线路】

目录 一、实验目的与要求 二、实验仪器 三、实验内容与测试结果 1、观测集电极调幅器输出信号波形&#xff0c;测量调幅度 2、观察集电极调幅器输出信号频谱&#xff08;Fourier analysis&#xff09; 3、改变V1幅度为0.8Vpk&#xff0c;观测输出波形&#xff0c;说明原…