菜单目录-行转树

listProjectVOSForFeishu:
    @Override
    public List<DashMenuTreeNodeVO> listProjectVOSForFeishu() {
        List<ProjectDashboardTabChartVO> projectDashboardTabChartVOList = dashboardMapper.listProjectDashboardTabChart(true);
        if (CollectionUtils.isEmpty(projectDashboardTabChartVOList)) {
            return Collections.emptyList();
        }
        DashMenuTreeNodeVO root = new DashMenuTreeNodeVO();
        for (int i = 0; i < projectDashboardTabChartVOList.size(); i++) {
            ProjectDashboardTabChartVO vo = projectDashboardTabChartVOList.get(i);
            root.add(vo);
        }
        return new LinkedList<>(root.getChildren());
    }
DashMenuTreeNodeVO:
package com.soyoung.ztdata.bi.core.vo.report;

import com.soyoung.ztdata.bi.core.enums.DashMenuTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.*;

/**
 */
@Slf4j
public class DashMenuTreeNodeVO {
    private String id;
    private String name;
    /**
     * 当前节点类型
     */
    String type;
    /**
     * 排序字段
     */
    private Integer sortNum;
    /**
     * 是否可编辑
     */
    private Boolean edit = false;
    /**
     * 是否可删除
     */
    private Boolean del = false;
    /**
     * 子节点
     */
    private Set<DashMenuTreeNodeVO> children = new TreeSet<>((o1, o2) -> {
        if (null == o1.sortNum || null == o2.sortNum) {
            return -1;
        }
        if (Objects.equals(o1.sortNum, o2.sortNum)) {
            if (Objects.equals(o1.getId(), o2.getId())) {
                return -1;
            }
            return o1.getId().compareTo(o2.getId());
        }
        return o1.sortNum.compareTo(o2.sortNum);
    });

    public DashMenuTreeNodeVO() {
    }

    public DashMenuTreeNodeVO(String type) {
        this.type = type;
    }


    private static final ThreadLocal<Finder> finder = new ThreadLocal<>();


    /**
     * 状态模式
     * type == null, // 说明是 根 root 节点, 获取菜单探测器探测结果(DashMenuTreeNodeVO),探测结果作为 子树 root 继续添加节点(node)
     * <p>
     * type == project("文件夹") && level == 0, // 说明是第一级菜单, 不可能出现此状态(type == null时,已经把level = 0 和 level = 1 两级节点关联了)
     * <p>
     * type == project("文件夹") && level == 1, // 说明是第二级菜单, 获取仪表盘探测器探测结果(DashMenuTreeNodeVO),探测结果作为root继续添加节点(node)
     * <p>
     * // type == dashboard("看板"), // 说明是看板节点,从页签探测器中获取页签引用,作为 子树 root 继续添加节点(node)
     * <p>
     * // type == tab("页签"), // 说明是页签节点,从图表探测器中获取图表引用,作为 子树 root 继续添加节点(node)
     * <p>
     * // type == chart("图表"); // 说明是图表节点(叶子节点),将 子树集合 置为 null
     *
     * @param node
     */
    public void add(ProjectDashboardTabChartVO node) {
        if (null == finder.get() || (null == type && this.children.size() == 0)) {
            finder.set(new Finder());
        }
        DashMenuTreeNodeVO root;
        String uniquePId = uniquePId(node);
        String uniqueProjId = uniqueProjId(node);
        String uniqueDashId = uniqueDashId(node);
        String uniqueTabId = uniqueTabId(node);
        String uniqueChartId = uniqueChartId(node);
        if (null == type) { // this == root
            if (Objects.equals("0", uniquePId)) { // node == 一级
                root = finder.get().getProjectFinder().computeIfAbsent(uniqueProjId,
                        key -> {
                            DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.project.name()).setId(node.getProjId()).setName(node.getProjName()).setSortNum(node.getProjectSortNum());
                            this.children.add(dashMenuTreeNodeVO);
                            return dashMenuTreeNodeVO;
                        });
                root.add(node);
            } else { // node == 二级
                // pid
                DashMenuTreeNodeVO rootPid = finder.get().getProjectFinder().computeIfAbsent(uniquePId,
                        key -> {
                            DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.project.name()).setId(node.getPid()).setName(node.getPname()).setSortNum(node.getPSortNum());
                            this.children.add(dashMenuTreeNodeVO);
                            return dashMenuTreeNodeVO;
                        });

                // projId
                root = finder.get().getProjectFinder().computeIfAbsent(uniqueProjId,
                        key -> {
                            final DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.project.name()).setId(node.getProjId()).setName(node.getProjName()).setSortNum(node.getProjectSortNum());
                            rootPid.getChildren().add(dashMenuTreeNodeVO);
                            return dashMenuTreeNodeVO;
                        });
                root.add(node);
            }
        } else if (Objects.equals(DashMenuTypeEnum.project.name(), this.type)) {
            root = finder.get().getDashboardFinder().computeIfAbsent(uniqueDashId,
                    key -> {
                        final DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.dashboard.name()).setId(node.getDashId()).setName(node.getDashName()).setSortNum(node.getDashSortNum());
                        this.children.add(dashMenuTreeNodeVO);
                        return dashMenuTreeNodeVO;
                    });
            root.add(node);
        } else if (Objects.equals(DashMenuTypeEnum.dashboard.name(), this.type)) {
            root = finder.get().getTabFinder().computeIfAbsent(uniqueTabId,
                    key -> {
                        final DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.tab.name()).setId(node.getTabId()).setName(node.getTabName());
                        this.children.add(dashMenuTreeNodeVO);
                        return dashMenuTreeNodeVO;
                    });

            root.add(node);
        } else if (Objects.equals(DashMenuTypeEnum.tab.name(), this.type)) {
            if (StringUtils.isBlank(uniqueChartId)) {
                this.children = null;
                return;
            }
            root = finder.get().getChartFinder().computeIfAbsent(uniqueChartId,
                    key -> {
                        final DashMenuTreeNodeVO dashMenuTreeNodeVO = new DashMenuTreeNodeVO(DashMenuTypeEnum.chart.name()).setId(node.getChartId()).setName(node.getChartName());
                        this.children.add(dashMenuTreeNodeVO);
                        return dashMenuTreeNodeVO;
                    });
            root.add(node);
        } else if (Objects.equals(DashMenuTypeEnum.chart.name(), this.type)) {
            this.children = null;
        }
    }

    private String uniqueChartId(ProjectDashboardTabChartVO node) {
        return node.getChartId();
    }

    private String uniqueTabId(ProjectDashboardTabChartVO node) {
        return uniqueDashId(node) + ":" + node.getTabId();
    }

    private String uniquePId(ProjectDashboardTabChartVO node) {
        return node.getPid();
    }

    private String uniqueDashId(ProjectDashboardTabChartVO node) {
        return node.getDashId();
    }

    private String uniqueProjId(ProjectDashboardTabChartVO node) {
        return node.getProjId();
    }

    public String getId() {
        return id;
    }

    public DashMenuTreeNodeVO setId(String id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public DashMenuTreeNodeVO setName(String name) {
        this.name = name;
        return this;
    }

    public String getType() {
        return type;
    }

    public DashMenuTreeNodeVO setType(String type) {
        this.type = type;
        return this;
    }

    public Boolean getEdit() {
        return edit;
    }

    public void setEdit(Boolean edit) {
        this.edit = edit;
    }

    public Boolean getDel() {
        return del;
    }

    public void setDel(Boolean del) {
        this.del = del;
    }

    public Integer getSortNum() {
        return sortNum;
    }

    public DashMenuTreeNodeVO setSortNum(Integer sortNum) {
        this.sortNum = sortNum;
        return this;
    }

    public Set<DashMenuTreeNodeVO> getChildren() {
        return children;
    }

    public void setChildren(Set<DashMenuTreeNodeVO> children) {
        this.children = children;
    }

    private static final class Finder {
        Map<String, DashMenuTreeNodeVO> projectFinder = new HashMap<>();
        Map<String, DashMenuTreeNodeVO> dashboardFinder = new HashMap<>();
        Map<String, DashMenuTreeNodeVO> tabFinder = new HashMap<>();
        Map<String, DashMenuTreeNodeVO> chartFinder = new HashMap<>();

        public Map<String, DashMenuTreeNodeVO> getProjectFinder() {
            return projectFinder;
        }

        public Map<String, DashMenuTreeNodeVO> getDashboardFinder() {
            return dashboardFinder;
        }

        public Map<String, DashMenuTreeNodeVO> getTabFinder() {
            return tabFinder;
        }

        public Map<String, DashMenuTreeNodeVO> getChartFinder() {
            return chartFinder;
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
J2eeFAST是一个Java EE企业级快速开发平台,基于经典技术组合(Spring Boot、Spring MVC、Apache Shiro、MyBatis-Plus、Freemarker、Bootstrap、AdminLTE)采用经典开发模式,让初学者能够更快的入门并投入到团队开发中去。在线代码生成功能,包括核心模块如:组织机构、角色用户、菜单及按钮授权、数据权限、系统参数、内容管理、license认证,BPM工作流等。采用松耦合设计;界面无刷新,一键换肤;众多账号安全设置,密码策略;在线定时任务配置;支持多数据源;支持读写分离、分库分表。 J2eeFAST功能: 1、用户管理:用户是系统操作者,该功能主要完成系统用户配置。 2、部门管理:配置系统组织机构(公司、部门),树结构展现支持数据权限。 3、岗位管理:配置系统用户所属担任职务。 4、菜单管理:配置系统菜单,操作权限,按钮权限标识等。 5、角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 6、字典管理:对系统中经常使用的一些较为固定的数据进行维护。 7、参数管理:对系统动态配置常用参数。 8、操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 9、登录日志:系统登录日志记录查询包含登录异常。 10、在线用户:当前系统中活跃用户状态监控。 11、定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 12、代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 13、服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 14、在线构建器:拖动表单元素生成相应的HTML代码。 15、连接池监视:监视当前系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 16、产品许可: 对项目进行许可证书控制,防止程序拷贝运行。 17、公告通知: 针对项目升级重要情况出通知公告直接生成静态页面,可以实现延迟推送,设置时效性,实时。 J2eeFAST软件架构: 核心框架:Spring Boot 2.2.5.RELEASE 安全框架:Apache Shiro 1.4.2 模板引擎:Freemarker 前端:AdminLTE 2.3.8, Bootstrap 3.3.7, Bootstrap-Table 1.11.0, JQuery 3.3.1 持久层框架:MyBatis-Plus 3.3.1 定时任务: Quartz 数据库连接池:Druid 1.10.1 数据库: Mysql5.7 分布式缓存数据库: Redis 4.0.9 工具类:Hutool 4.5.8 工作流引擎:flowable 6.4.2 J2eeFAST安装教程: 1、需要准备环境Mysql5.7以上、JDK1.8、Maven3.3、Redis4.X以上、开发工具eclipse或者IEDA。 2、下载源码git clone https://gitee.com/zhouhuanOGP/J2EEFAST.git。 3、编译代码找到根目录下pom.xml,执行mvn clean install命令编译一键打包。一般来说不会有什么问题,如果还是编译不成功,可以按照优先级逐个编译试一试。 4、导入数据库db目录里initDb.sql有建库建表语句按步骤执行即可。 5、将代码导入开发工具fast-admin启动模块- 执行FastApplication类即可 注意:fast-admin模块,资源目录application-Test.yml中修改连接数据库和链接地址;如果你是按照initDb.sql建库,test.sql导入初始数据,则账号密码用户名都不需要修改。 6、搭建文档。 最大管理员账号:admin 密码:admin。其他账户密码都是123456 演示地址的账号 :admin 密码:admin   J2eeFAST企业级快速开发平台 v2.2.1 更新日志: 升级mybatisplus到最新版本3.4.2 新增数据库脚本自动升级 适配恶心的IE浏览器最低适配IE10 修复添加SQLServer数据库源问题 修复多源数据JTA事务问题 新增多源数据支持Mapper接口注解 修复表格显示图片点击事件问题 优化适配移动端 linux环境升级、启动脚本备份文件无目录问题 修复多源数据库代码生成切换数据库问题 修复oracle兼容问题 修复代码生成器生成头像问题 修复适配数据库执行语句问题 新增金额转换中文通用方法 修复代码生成div标签问题 调整文件上传考虑事务问题、不删除文件 移除项目pom文件多余配置 新增系统默认配置文件 简化配置文件 移除代码默认密码字段 新增base64字符判断公用方法 优化图片上传支持直接Base64字符 新增表格通过id获取行
PL/SQL Developer是一个集成开发环境,专门面向Oracle数据库存储程序单元的开发。如今,有越来越多的商业逻辑和应用逻辑转向了Oracle Server,因此,PL/SQL编程也成了整个开发过程的一个重要组成部分。PL/SQL Developer侧重于易用性、代码品质和生产力,充分发挥Oracle应用程序开发过程中的主要优势。     PL/SQL Developer v8.0主要特性: PL/SQL编辑器,功能强大&mdash;&mdash;该编辑器具有语法加强、SQL和PL/SQL帮助、对象描述、代码助手、编译器提示、PL/SQL完善、代码内容、代码分级、浏览器按钮、超链接导航、宏库等许多智能特性,能够满足要求性最高的用户需求。当您需要某个信息时,它将自动出现,至多单击即可将信息调出。 集成调试器(要求Oracle 7.3.4或更高)&mdash;&mdash;该调试器提供您所需要的全部特性:跳入(Step In)、跳过(Step Over)、跳出(Step Out)、异常时停止运行、断点、观察和设置变量、观察全部堆栈等。基本能够调试任何程序单元(包括触发器和Oracle8 对象类型),无需作出任何修改。 PL/SQL完善器&mdash;&mdash;该完善器允许您通过用户定义的规则对SQL和PL/SQL代码进行规范化处理。在编译、保存、打开一个文件时,代码将自动被规范化。该特性提高了您编码的生产力,改善了PL/SQL代码的可读性,促进了大规模工作团队的协作。 SQL 窗口&mdash;&mdash;该窗口允许您输入任何SQL语句,并以栅格形式对结果进行观察和编辑,支持按范例查询模式,以便在某个结果集合中查找特定记录。另外,还含有历史缓存,您可以轻松调用先前执行过的SQL语句。该SQL编辑器提供了同PL/SQL编辑器相同的强大特性。 命令窗口&mdash;&mdash;使用PL/SQL Developer 的命令窗口能够开发并运行SQL脚本。该窗口具有同SQL*Plus相同的感观,另外还增加了一个内置的带语法加强特性的脚本编辑器。这样,您就可以开发自己的脚本,无需编辑脚本/保存脚本/转换为SQL*Plus/运行脚本过程,也不用离开PL/SQL Developer集成开发环境。 报告&mdash;&mdash;PL/SQL Developer提供内置的报告功能,您可以根据程序数据或Oracle字典运行报告。PL/SQL Developer本身提供了大量标准报告,而且您还可以方便的创建自定义报告。自定义报告将被保存在报告文件中,进而包含在报告菜单内。这样,运行您自己经常使用的自定义报告就非常方便。 您可以使用Query Reporter免费软件工具来运行您的报告,不需要PL/SQL Developer,直接从命令行运行即可。 工程&mdash;&mdash;PL/SQL Developer内置的工程概念可以用来组织您的工作。一个工程包括源文件集合、数据库对象、notes和选项。PL/SQL Developer允许您在某些特定的条目集合范围之内进行工作,而不是在完全的数据库或架构之内。这样,如果需要编译所有工程条目或者将工程从某个位置或数据库移动到其他位置时,所需工程条目的查找就变得比较简单, To-Do条目&mdash;&mdash;您可以在任何SQL或PL/SQL源文件中使用To-Do条目快速记录该文件中那些需要进行的事项。以后能够从To-Do列表中访问这些信息,访问操作可以在对象层或工程层进行。 对象浏览器&mdash;&mdash;可配置的树形浏览能够显示同PL/SQL开发相关的全部信息,使用该浏览器可以获取对象描述、浏览对象定义、创建测试脚本以便调试、使能或禁止触发器或约束条件、重新编译不合法对象、查询或编辑表格、浏览数据、在对象源中进行文本查找、拖放对象名到编辑器等。 此外,该对象浏览器还可以显示对象之间的依存关系,您可以递归的扩展这些依存对象(如包参考检查、浏览参考表格、图表类型等)。 性能优化&mdash;&mdash;使用PL/SQL Profiler,可以浏览每一执行的PL/SQL代码行的时序信息(Oracle8i或更高),从而优化您SQL和PL/SQL的代码性能。 更进一步,您还可以自动获取所执行的SQL语句和PL/SQL程序统计信息。该统计信息包括CPU使用情况、块I/O、记录I/O、表格扫描、分类等。 HTML指南&mdash;&mdash;Oracle目前支持HTML格式的在线指南。您可以将其集成到PL/SQL Developer工作环境中,以便在编辑、编译出错或运行时出错时提供内容敏感帮助。 非PL/SQL对象&mdash;&mdash;不使用任何SQL,您就可以对表格、序列、符号、库、目录、工作、队列、用户和角色进行浏览、创建和修改行为。PL/SQL Developer提供了一个简单易用的窗体,只要将信息输入其中,PL/SQL Developer就将生成相应的SQL,从而创建或转换对象。 模板列表&mdash;&mdash;PL/SQL Developer的模板列表可用作一个实时的帮助组件,协助您强制实现标准化。只要点击相应的模板,您就可以向编辑器中插入标准的SQL或PL/SQL代码,或者从草稿出发来创建一个新程序。 查询构建器&mdash;&mdash;图形化查询构建器简化了新选择语句的创建和已有语句的修改过程。只要拖放表格和视窗,为区域列表选择专栏,基于外部键约束定义联合表格即可。 比较用户对象&mdash;&mdash;对表格定义、视图、程序单元等作出修改后,将这些修改传递给其他数据库用户或检查修改前后的区别将是非常有用的。这也许是一个其他的开发环境,如测试环境或制作环境等。而比较用户对象功能则允许您对所选对象进行比较,将不同点可视化,并运行或保存应用必要变动的SQL脚本。 导出用户对象&mdash;&mdash;该工具可以导出用户所选对象的DDL(数据定义语言)语句。您可以方便的为其他用户重新创建对象,也可以保存文件作为备份。 工具&mdash;&mdash;PL/SQL Developer为简化日常开发专门提供了几种工具。使用这些工具,您可以重新编译全部不合法对象、查找数据库源中文本、导入或导出表格、生成测试数据、导出文本文件、监控dbms_alert和dbms_pipe事件、浏览会话信息等。 授权&mdash;&mdash;大多数开发环境中,您不希望所有数据库都具备PL/SQL Developer的全部功能性。例如,数据库开发中您可以允许PL/SQL Developer的全部功能性,而数据库测试中您可以仅允许数据查询/编辑和对象浏览功能,而数据库制作中您甚至根本不希望PL/SQL Developer访问。利用PL/SQL Developer授权功能,您可以方便的定义特定用户或规则所允许使用的功能。 插件扩展&mdash;&mdash;可以通过插件对PL/SQL Developer功能进行扩展。Add-ons页面提供插件可以免费下载。Allround Automations或其他用户均可提供插件(如版本控制插件或plsqldoc插件)。如果您具备创建DLL的编程语言,您还可以自己编写插件。 多线程IDE&mdash;&mdash;PL/SQL Developer是一个多线程IDE。这样,当SQL查询、PL/SQL程序、调试会话等正在运行时,您依然可以继续工作。而且,该多线程IDE还意味着出现编程错误时不会中止:您在任何时间都可以中断执行或保存您的工作。 易于安装&mdash;&mdash;不同于SQL*Net,无需中间件,也无需数据库对象安装。只需点击安装程序按钮,您就可以开始安装从而使用软件了。
##KodExplorer (http://kalcaddle.com/) ###ver2.61(2014.7.12) `商业版授权请联系:kalcaddle#qq.com` #### 1.是什么: - Kodexplorer为千帆网络工作室开发的一款服务器文件管理程序。 - 完美取代FTP管理:可用于服务器文件管理,zip解压缩 备份还原、支持图片、音乐、视频预览、office、pdf等格式在线预览。文件夹拖拽上传……。 - 在线编程:支持几乎所有编程语言的在线编辑(高亮,多光标编辑.堪比本地的sublime) - 极佳的操作体验:及其便捷的快捷键支持,让你拥有本地化的体验 - 中文等多语言支持:中文编码全面兼容,文件编辑自动适配。 - 超快的速度:全面采用Ajax+Json进行数据通信,毫秒级的响应速度; - 全平台兼容性:Win Linux Mac (Apache、Nginx、IIS) #### 2.使用场景: - 取代FTP,服务端、客户端软件等复杂的安装配置。kod可以一键安装随处使用. - 你可以用它来管理你的服务器(备份,在线解压缩,版本发布....) - 你可以把他当做管理linux的一个操作系统界面 - 可以用来作为私有云存储系统,存储你的文件... - 当然你也可以用来分享文件 - Web IDE / browser code editor awesomeness - 更多场景等你来挖掘!…… #### 3.使用说明 管理员: admin/admin 普通用户:demo/demo 游客用户:guest/guest [如何使用] 下载程序,解压上传到你的服务器路径下,data目录设置777权限。访问体验超便捷的服务吧! (data目录没有写权限会导致配置修改不能保存、不能新建用户等) [关于上传问题] 程序没有做任何限制,如果需要上传大文件,则修改 php.ini:`upload_max_filesize = 1000M post_max_size = 1000M` [关于解压缩问题] 程序不做任何限制,如若失败请设置php内存限制。memory_limit 1000M [关于兼容性] 建议使用chrome firefox ie9+ 体验更完整。ie8以下基本上不做兼容处理。chrome支持文件夹拖拽上传。 [文件打开] office文件在线预览功能,服务器必须在公网(外部能访问该服务器) [忘记密码] 修改data/system/member.php 密码为明文的md5值 例如将admin密码重设为admin 则修改第一行:"name":"admin","password":"21232f297a57a5a743894a0e4a801fc3" ![](https://cloud.githubusercontent.com/assets/3761968/2583304/764f562a-b9cf-11e3-8e59-afdbdffc20eb.png) ###ver2.61 `2014/7/12` ---- ####update: - 实时搜索,根据搜索框内容变化,实时选中匹配到的结果; - 弹出搜索框遍历子文件夹递归搜索 - session key 加入kod_前缀 避免和其他系统key冲突 - 编辑器选中优化 选择鼠标到窗口外事件处理 ####fix bug:(bug解决和程序优化) - backspace后退截获浏览器事件,作为后退前一次访问的文件夹; - 搜索首字母不匹配问题 - 弹出层中的弹出层关闭,父窗口失去焦点问题。 - 代码中grunt部分代码拆分开,放到程序外面;提交到git、osc - 桌面:删除alert enter快捷键删除 - install 检测 加入跳过,(只判断用到的函数) 加入多语言 - zip压缩没有权限 提示红色,false 统一查找 - 登录成功后 验证码输错清除 - 非root用户拖拽到文件夹问题 - 非root解压问题 不能解压 - list oexe 图标问题 - 用户目录不存在判断 - fileCahe 互斥锁 reset 不用 - ie 8~10样式问题调整 ###ver2.6 `2014/7/6` ---- ####update: - 完全性优化;加入严格的校验机制 - 首次运行环境检测[data目录检测,必须的函数支持提示] - 上传已存在处理&mdash;&mdash;创建副本(另外包括粘贴,解压) - 选中优化 ctrl选中拖拽 - 键盘快捷键选中文件,多个字符

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值