花田土著

花田土著 查看完整档案

北京编辑  |  填写毕业院校北京安托软件技术有限公司  |  java工程师 编辑 rebey.cn 编辑
编辑

希望加入有意思的开发团队!
QQ:251601797

个人动态

花田土著 关注了用户 · 10月7日

Lison @lison16

多吃些学习的苦,少受些生活的累

关注 232

花田土著 关注了问题 · 1月21日

scss中使用calc属性无效

我在vue的scss中使用calc属性无效(计算符号间有空格),请问这是怎么回事(使用element-ui),如下如:image.png
image.png

关注 3 回答 1

花田土著 赞了文章 · 1月11日

element transfer 不使用render-content方法给每一行加title的一种思路

原文地址:https://segmentfault.com/a/1190000020956789

问题描述

最近在使用element-uiel-transfer时候遇到一问题:
穿梭框一行显示一条数据,但是有的数据比较长,一行显示不下,那就要把超出的部分用...展示,鼠标放上去的时候展示完整内容。
一般的做法呢,就是通过css控制...显示,同时元素的title属性,这样鼠标放上去的时候可以悬浮展示完整数据。
放在el-transfer的场景下就是通过组件提供的render-content来自定义每行内容的渲染,给每行元素加一个title属性。
但是呢,render-content的返回内容得是JSX语法。
官方文档demo code是这么写的:

renderFunc(h, option) {
    return <span>{ option.key } - { option.label }</span>;
}

还有一些注释:

注意:由于 jsfiddle 不支持 JSX 语法,所以使用 render-content 自定义数据项的例子在 jsfiddle 中无法运行。但是在实际的项目中,只要正确地配置了相关依赖,就可以正常运行。

简单说就是要用render-content这个方法需要额外安装一些依赖。我丢,为了这么个小玩意儿我还要装一些依赖!不能忍,不能装,一定要想办法解决。于是我开始琢磨解决方法。

尝试方法

css方案

一开始我想用css来解决。利用:hover:after或者:beforecontentattr()这些东西来自己实现一个title悬浮效果。但是翻遍了各种文档没找到怎么通过atrr()来获取元素文本值。然后这个方案就进行不下去了,只能换方法。

js方案

从js层面看,其实这个问题的核心就是给元素设置title属性嘛,我手动给他加一个不就完了。我的做法是这样的:通过监听元素的onmouseover事件,当鼠标移动到元素上面时,获取元素的文本值设置给元素的title属性。
示例代码如下:

<el-transfer @mouseover.native="addTitle"></el-transfer>
addTitle (e) {
    // 手动给鼠标滑过的元素加一个title
    let target_el = e.target;
    if (target_el.title) return;
    if (/*满足一定条件时候*/) {
        target_el.title = target_el.innerText;
    }
}

这样这个问题就解决了。

小思考

做完这个东西,我有了一点小思考。
在我们使用框架的时候,思维有时候很容易被框架绑架,反而忘记了一些原生的东西,而这些原生的东西有时候解决起来问题反倒是更简单、更直接。所以,虽然我们在使用框架做东西,但是解决问题的时候不要局限在框架内,有时候不妨跳出框架看看有没有更直接、更简单的方法。

2019.11.19更新

跟公司的大牛讨论了一下,发现可以使用vue的渲染函数实现这个需求,写法更优雅。其实还是使用render-content方法,只不过不用JSX写法,也不用引入额外的依赖。具体demo code如下:

<el-transfer :render-content="renderContent"></el-transfer>
renderContent (h, option) {
    return h('span', {domProps: {title: option.label}}, option.label);
}

这个写法和iviewrender方法一个道理,推荐使用此种写法

查看原文

赞 8 收藏 4 评论 1

花田土著 发布了文章 · 2019-06-23

jodconvert的亚子

简介

引入jodconverter相关jar,配合libreOffice、openOffice两款软件,只需进行简单编码可以实现各种文档转换。

应用

目前已在两个项目中应用:

  • F项目需要滚动播放视频、文档(Excel/Word...)功能,使用jodconverter将文档转成pdf,结合pdfjs实现。由于个人独立开发,只要结果,故选型自由。后端Spring boot,前端阿里飞冰。可以直接使用jodconverter的starter:
<!-- jodconverter newer 4.2 -->
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-core</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-local</artifactId>
    <version>4.2.0</version>
</dependency>
<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-spring-boot-starter</artifactId>
    <version>4.2.0</version>
</dependency>

使用也非常方便,注入可用:

import java.io.File;
import javax.annotation.Resource;
import org.jodconverter.DocumentConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.foton.common.Constants;

@Component
public class DocumentConverterUtil {
    
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
//    @Value("${office.home}")
//    String officeHome;
    @Resource
    private DocumentConverter  documentConverter;
    
    public String convert(File in, File out) {
//        DocumentFormat pdf = documentConverter.getFormatRegistry().getFormatByExtension("pdf");

        try {
            String fileName=in.getName();
            String fileType=fileName.substring(fileName.lastIndexOf(".")+1,fileName.length()); 

            // Excel尺寸控制
            if(fileType.equals("xls"))
                ConverterUtil.setXlsFitToWidth(in);
            long startTime = System.currentTimeMillis();
            documentConverter.convert(in).to(out).execute();
            long conversionTime = System.currentTimeMillis() - startTime;
            logger.info(String.format("successful conversion: %s to %s in %dms",in.getName(), "pdf", conversionTime));

        } catch (Exception e) {
            e.printStackTrace();
            return Constants.FAIL;
        }

        return Constants.SUCCESS;
    }
}
  • H项目应审查要求,原本开发的导出Excel功能需调整为导出pdf,因此在原来基础功能上用jodconvert额外增加一次转换。由于公司要求限制,该项目在jdk1.7下开发,非maven,因此需要传统jar方式引入相关依赖jar包。值得注意的是,jodconvert在4.1.0不支持jdk7,而4.1.0版本仅会吃libreOffice 5(libreOffice升级到6后目录变更,作者在4.2.0版本中调整,但该版本不支持jdk7)。此外,convert的启动与结束需要自己控制。
import com.eos.runtime.core.IRuntimeListener;
import com.eos.runtime.core.RuntimeEvent;

public class JodConverterStartupListener implements IRuntimeListener {

    @Override
    public void start(RuntimeEvent arg0) {
        DocumentConverterUtil.start(); // 项目启动时调用
    }

    @Override
    public void stop(RuntimeEvent arg0) {
        DocumentConverterUtil.stop(); // 结束时关闭
    }

}
import java.io.File;

import org.jodconverter.DocumentConverter;
import org.jodconverter.LocalConverter;
import org.jodconverter.office.LocalOfficeManager;
import org.jodconverter.office.OfficeException;
import org.jodconverter.office.OfficeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DocumentConverterUtil {
    private static final Logger logger = LoggerFactory.getLogger(DocumentConverterUtil.class);
    public static DocumentConverter  documentConverter;
    public static OfficeManager officeManager;
    
    public static void start() {
        officeManager = LocalOfficeManager.builder().build();
        documentConverter = LocalConverter.make(officeManager);

        try {
            officeManager.start();
            logger.info(">>> office转换服务启动成功!");
        } catch (OfficeException e) {
            e.printStackTrace();
        }
    }
    
    public static void converter(String inputFilePath, String outputFilePath) throws Exception {
        File inputFile = new File(inputFilePath);
        if (inputFile.exists()) {// 找不到源文件, 则返回  
            File outputFile = new File(outputFilePath);
            if (!outputFile.getParentFile().exists()) { // 假如目标路径不存在, 则新建该路径  
                outputFile.getParentFile().mkdirs();
            }
            
            String fileType = inputFilePath.substring(inputFilePath.lastIndexOf(".")+1,inputFilePath.length()); 

            if(fileType.equals("xls"))
                ConverterUtil.setXlsFitToWidth(inputFile);
            
            documentConverter.convert(inputFile)
                    .to(outputFile)
                    .execute();
        }
            
    }
    
    
    public static void stop() {
        if (officeManager.isRunning()) {
            try {
                officeManager.stop();
            } catch (OfficeException e) {
                e.printStackTrace();
            }
            logger.info(">>> office转换服务完成。");
        }
    }
}

关于我

rebey.cn

查看原文

赞 1 收藏 0 评论 0

花田土著 关注了问题 · 2019-06-17

jodConvert4.1.0 excel转pdf 怎么设置pageSize

最近遇到需求需要excle转pdf决定使用JodConvert来做, 转pdf的时候类库默认使用pdf的pageSize 是 A4,当excel列过多,总宽度过大时会右边的部分会显示不出来,此时需要设置更大的pageSize,尝试过后未找到解决办法

final LocalOfficeManager officeManager = LocalOfficeManager
        .builder()
        .portNumbers(2002)
        .officeHome("/Applications/LibreOffice.app/Contents")
        .install()
        .build();

@Test
public void test() throws OfficeException {
    officeManager.start();
    JodConverter
            .convert(inputFile)
            .to(outputFile)
            .as(DefaultDocumentFormatRegistry.PDF)
            .execute();
    officeManager.stop();
}

java代码比较简单,但是不知道类库提供了哪些扩展,是否有扩展参数可以控制pdf的pageSize大小

看了写其他人的解答(好像使用了旧版本的jodConvert):

clipboard.png
图片来源网页: 地址

我未在新版本中找到相关设置的代码

关注 2 回答 0

花田土著 赞了问题 · 2019-06-17

jodConvert4.1.0 excel转pdf 怎么设置pageSize

最近遇到需求需要excle转pdf决定使用JodConvert来做, 转pdf的时候类库默认使用pdf的pageSize 是 A4,当excel列过多,总宽度过大时会右边的部分会显示不出来,此时需要设置更大的pageSize,尝试过后未找到解决办法

final LocalOfficeManager officeManager = LocalOfficeManager
        .builder()
        .portNumbers(2002)
        .officeHome("/Applications/LibreOffice.app/Contents")
        .install()
        .build();

@Test
public void test() throws OfficeException {
    officeManager.start();
    JodConverter
            .convert(inputFile)
            .to(outputFile)
            .as(DefaultDocumentFormatRegistry.PDF)
            .execute();
    officeManager.stop();
}

java代码比较简单,但是不知道类库提供了哪些扩展,是否有扩展参数可以控制pdf的pageSize大小

看了写其他人的解答(好像使用了旧版本的jodConvert):

clipboard.png
图片来源网页: 地址

我未在新版本中找到相关设置的代码

关注 2 回答 0

花田土著 发布了文章 · 2019-05-26

weblogic12.2.1+EOS7.6部署记

> weblogic12.2.1安装

  • java -jar fmw_12.2.1.0.0_wls.jar时需要jdk1.7
  • 安装后,配置向导选jdk1.8且版本152(以上)

> EOS Server 7.6安装

  • weblogic需要处于启动状态!
  • bea home:D:OracleMiddlewareOracle_Home
  • weblogic home: D:OracleMiddlewareOracle_Homewlserver
  • domain: D:OracleMiddlewareuser_projectsdomainsbase_domain
  • server: AdminServer
  • 如需修改默认端口7001,需先修改后再安装EOS,否则workspace登录存在问题

> 部署包上传大小限制

  • 修改D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domainapplicationsgovernor.warWEB-INF_srvconfig下user_config.xml
<group name="FileUpload">
    <configValue key="TempDir">upload</configValue>
    <configValue key="MaxSize">184857600</configValue>
    <configValue key="InMemorySize">10240</configValue>
    <!--files with specified ext names are not accespted when uploading  -->
    <configValue key="Exclude">exe,java,jsp,html,htm,class,jar</configValue>
</group>

> jar冲突

解决方案

排查过程

  • 查看应用日志contribution.log得知:
[2019-05-24
16:26:52,178]ERROR[Line:166]
loadAuthService[IAuthManagerService=org.gocom.components.coframe.auth.DefaultAuthManagerService]
error. java.lang.LinkageError: loader constraint violation: when
resolving interface method
"javax.xml.stream.XMLStreamReader.getName()Ljavax/xml/namespace/QName;"
the class loader (instance of
weblogic/utils/classloaders/ChangeAwareClassLoader) of the current
class, com/primeton/spring/parser/SpringConfigFileParser, and the
class loader (instance of <bootloader>) for the method's defining
class, javax/xml/stream/XMLStreamReader, have different Class objects
for the type javax/xml/namespace/QName used in the signature
  • 通过findClass工具查找com/primeton/spring/parser/SpringConfigFileParser对应jar,出现在普元的哪个jar中:

F:primeton6for3276ideeclipsejrebinjava -cp ant.jar;. FindClass com.primeton.spring.parser.SpringConfigFileParser F:primeton6for3276ideeclipse
(上述例子就是在F:primeton6for3276ideeclipse目录下,搜索com.primeton.spring.parser.SpringConfigFileParser所在位置)
结果是eos-server-spring开头的jar

  • 善用github,查到eos-server-spring的package-name
<groupId>bps.simbest</groupId>
<artifactId>eos-server-spring</artifactId>
<version>7.1.3.0</version>
<?xml version="1.0" encoding="UTF-8"?> 
<weblogic-web-app xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-app_3.0.xsd 
http://xmlns.oracle.com/weblogic/weblogic-web-app 
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.8/weblogic-web-app.xsd"> 
  <container-descriptor>
    <prefer-web-inf-classes>false</prefer-web-inf-classes>
    <prefer-application-packages>
        <package-name>bps.simbest.*</package-name>
    </prefer-application-packages>
 
    <prefer-application-resources>
      <resource-name>bps.simbest.*</resource-name>
    </prefer-application-resources>
  </container-descriptor>
</weblogic-web-app>

> 常用路径

  • 应用代码:D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domainapplicationsdefault.eardefault.war
  • 应用日志:D:OracleMiddlewareOracle_Homeuser_projectsdomainsmes_work_default_6200logs
  • weblogic日志:D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domainserversAdminServerlogs
  • 服务启动:D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domain startWebLogic.cmd
  • 应用缓存:D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domainserversAdminServertmp_WL_user[可删]
  • 数据库配置:D:OracleMiddlewareOracle_Homeuser_projectsdomainsbase_domainconfigjdbc

> 关于我

rebey.cn

查看原文

赞 0 收藏 0 评论 0

花田土著 赞了问题 · 2018-08-17

解决web前端如何实现根据url生成网站缩略图

前端是否可以实现根据网站url生成缩略图的功能?

======================
后来的解决办法是:需要缩略图的页面通过html2canvas截图上传服务器,需要展示的页面上查询对应的图片。
办法有点low,如果后端愿意尝试,可以参考下:
https://github.com/juliangrub...
http://phantomjs.org/

关注 2 回答 2

花田土著 关注了问题 · 2018-07-04

解决git commit -m 与 git commit -am 的区别

麻烦解答下 git commit -m 与 git commit -am 的区别

关注 6 回答 4

花田土著 关注了问题 · 2018-04-17

正交投影照相机为什么视景体水平方向的距离减少了而显示的物体水平方向被拉长了?

最近刚开始研究three.js,了解到视景体就是下图中的大长方体

clipboard.png
之前的代码是这样的:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script data-original="js/three.js"></script>
    <script type="text/javascript">
        // 定义一个渲染器
        var renderer = new THREE.WebGLRenderer();
        renderer.setSize(400,300);
        document.getElementsByTagName('body')[0].appendChild(renderer.domElement);
        renderer.setClearColor(0x000000);
        // 定义一个场景
        var scene = new THREE.Scene();
        // 定义一个相机
        var camera = new THREE.OrthographicCamera(-2,2,1.5,-1.5,1,1024);
        camera.position.set(0,0,5);
        scene.add(camera);
        // 定义一个长方体,颜色设置为红色
        var cube = new THREE.Mesh(new THREE.CubeGeometry(1,1,1),
                new THREE.MeshBasicMaterial({
                    color:0xff0000,
                    wireframe:true
                })
        );
        scene.add(cube);
        // 渲染场景和照相机
        renderer.render(scene,camera);
    </script>
</body>
</html>

效果是这样的:

clipboard.png

现在把相机的参数进行修改为var camera = new THREE.OrthographicCamera(-1, 1, 1.5, -1.5, 1, 10);
结果是原来的正方体被水平方向被拉长了(如下图),而不是缩小,这是为什么?

clipboard.png

关注 2 回答 0

花田土著 收藏了文章 · 2018-04-17

Three.js 初探 - 微场景制作

最近在捣鼓 Three.js 相关, 觉得做一个微场景是一个很不错的选择,结果做下来发现效果还可以。

下面放几张不同角度的效果图

微场景-斜视
微场景-正面
微场景-背面

预览地址

源码地址

配置较差的设备上预览效果不是很理想, 待优化中

实现过程

接下来大致说明一下实现过程

准备工作

首先你要清楚自己想实现的效果, 就需要一张效果图, 然后才能根据效果图来建模。
我在网上找到一张自己喜欢的风格的建筑图做参考,明确自己大概要实现的效果,但结果不一定要一模一样。

效果图

然后根据效果图,画出自己想要的模型的平面图,方便模型中物体的精确定位

平面图

开发

Three.js来构建一个类似的微场景, 还是比较简单的。基本上就是在 场景打好灯光摄像机位置, 然后往 场景 添加各种几何图形,通过几个图形和材质的组合,构建出不同的模型和场景。对开发者的空间想象力有一定的要求。

新建一个空场景与设置

var scene, camera
    var renderer
    var width, width

    var cars = []
    // var stats

    var config = {
      isMobile: false,
      background: 0x282828
    }

    width = window.innerWidth
    height = window.innerHeight

    scene = new THREE.Scene() // 新建一个场景
    camera = new THREE.PerspectiveCamera(45, width / height, 1, 5000) // 新建一个透视摄像机, 并设置 视场, 视野长宽比例, 可见远近范围
    camera.position.set(330,330,330)  // 设置摄像机的位置
    camera.lookAt(scene.position)  // 设置摄像机观察的方向
    scene.add(camera)  

    renderer = new THREE.WebGLRenderer({antialias: true}) // 新建一个渲染器, 渲染器用来输出最终结果
    renderer.setSize(width, height) // 设置渲染的尺寸, 在这里是浏览器尺寸
    renderer.setClearColor(config.background) // 设置背景的颜色
    renderer.shadowMap.enabled = true // 设置是否开启投影, 开启的话, 光照会产生投影
    renderer.shadowMap.type = THREE.PCFSoftShadowMap  // 设置投影类型, 这边的柔和投影
    document.body.appendChild(renderer.domElement) // renderer.domElement 是渲染器用来显示结果的 canvas 标签

    // checkUserAgent()

    // buildAuxSystem()
    // buildLightSystem()
    // buildbuilding()
    // buildRoad()
    // buildStaticCars()
    // buildMovingCars()

    loop()
    
    function loop () {
      cars.forEach(function(car){
        carMoving(car) 
      })
      renderer.render(scene, camera) // 渲染器开始渲染, scene 和 camera 是必须参数, 因为场景里有动画, 所以放在 loop 里循环
      requestAnimationFrame(loop)
    }

设置一下光照系统

在3D世界里, 是非常重要的元素, 直接影响到场景内物体的显示效果, 通常会通过组合使用几种不同的 来调出自己满意的效果。在我的案例中,我分别在PC端和非PC端使用了不同的 光, 主要是出于性能考虑
if (!config.isMobile) {
  // PC端
  var directionalLight = new THREE.DirectionalLight( 0xffffff , 1.1); // 新建一个平行光, 平行光照射到的每个点的强度都一样
  directionalLight.position.set( 300, 1000, 500 );
  directionalLight.target.position.set( 0, 0, 0 );
  directionalLight.castShadow = true; // 开启平行光的投影
 
  // 下面是设置投影的效果
  var d = 300;
  directionalLight.shadow.camera = new THREE.OrthographicCamera( -d, d, d, -d,  500, 1600 ); // 投影的可视范围
  directionalLight.shadow.bias = 0.0001;
  directionalLight.shadow.mapSize.width = directionalLight.shadow.mapSize.height = 1024; // 投影的精度
  scene.add(directionalLight)
  
  // 再添加一个环境光, 目的是为了调和平行光的投影区域, 防止投影过度黑
  var light = new THREE.AmbientLight( 0xffffff, 0.3 ) 
  scene.add( light )
}else{
 // 非PC端
 // 只添加一个天空光, 天空光从正上方往下照, 可以照出明暗对比, 但是不产生阴影
  var hemisphereLight = new THREE.HemisphereLight( 0xffffff, 1.6)
  scene.add( hemisphereLight)
}

添加场景中的物体

Three.js中,通过 几何体(geometry) 和 材质(material) 来生成一个可视物体,我举2个例子简单说明一下

树

在我的案例中, 树围绕在建筑周围, 所以需要一个 单体树, 还有树的坐标(可以通过平面图得出), 然后根据坐标,在每个位置放置一个树
// 种树函数
function addTrees () {
  // 树的坐标
  var treesPosition = [
    [-110, -110], [-90, -110],[-70, -110],[-50, -110],[-30, -110],[ -10, -110],[10, -110],[30, -110],[50, -110],[70, -110],[90, -110],
    [-110,  110], [-110, 90],[-110, 70],[-110, 50],[-110, 30],[ -110, 10],[-110, -10],[-110, -30],[-110, -50],[-110, -70],[-110, -90],
    [ 110,  110], [90, 110], [70, 110], [50, 110], [30, 110],[-30, 110], [-50, 110], [-70, 110], [-90, 110],
    [ 110, -110], [ 110, -90], [ 110, -70], [ 110, -50], [ 110, -30], [ 110, -10], [ 110, 10], [ 110, 30], [ 110, 50], [ 110, 70],  [ 110, 90],
  ]
  treesPosition.forEach(function (elem) {
    var x = elem[0],
        y = 1,
        z = elem[1]
    var tree = createTree(x, y, z)
    scene.add(tree)
  })
}

// 单体树
function createTree (x, y, z) {
  var x = x || 0
  var y = y || 0
  var z = z || 0

  var tree = new THREE.Object3D()  // 新建一个空对象用来放 树干 和 树叶 部分
 
  var treeTrunkGeometry = new THREE.BoxGeometry(2,16,2) // 树干
  var treeTrunk = utils.makeMesh('lambert', treeTrunkGeometry, 0x8a613a)
  treeTrunk.position.y = 8 // 树干 y 轴位置
  tree.add(treeTrunk) // 树干添加到空对象中

  var treeLeafsGeometry = new THREE.BoxGeometry(8, 8, 8) // 树叶
  var treeLeafs = utils.makeMesh('lambert', treeLeafsGeometry, 0x9c9e5d)
  treeLeafs.position.y = 13 // 树叶 y 轴的位置
  tree.add( treeLeafs) // 树叶添加到空对象中

  tree.position.set(x, y, z)

  return tree // 返回 树 = 树干 + 树叶 对象
}
汽车

汽车

汽车是场景中唯一运动的元素, 也是相对复杂的物体, 除了车身的构建, 还需要开放 前进 , 后退, 转弯 等方法, 方便以后实现运动效果, 所以我单独封装
function Car (color) {
  // 可以自定义车身的颜色, 默认随机
  var colors = [0x2cbab2, 0x47a700, 0xd60000, 0x087f87, 0x37ad0e, 0x4d4d4d, 0xce7e00, 0xe0a213, 0x87bcde]
  var index = Math.floor(Math.random() * colors.length)

  this.color = color || colors[index]
  this.mesh = new THREE.Object3D()
  this.wheels = []
  this.startAngle = 0
  
  var that = this
  addBody() // 添加车身到 this.mesh
  addWindows() // 添加车窗到 this.mesh
  addLights() // 添加车灯到 this.mesh
  addWheels() // 添加车轮到 this.mesh
  ...
}
Car.prototype = {
  // 设置车的位置
  setPosition: function (x,y,z) {
    this.mesh.position.set(x,y,z)
  },
  // 前进, 实现不管车旋转的角度怎样, 车都能按车头的方向前进
  forward: function  (speed) {
    var speed = speed || 1
    this._moving(speed, true)
  },
  // 后退, 实现不管车旋转的角度怎样, 车都能按车尾的方向后退
  backward: function  (speed) {
    var speed = speed || 1
    this._moving(speed, false)
  },
  // 左转
  turnLeft: function (angle, speed) {
      this._turn(angle, true, speed)
  },
  // 右转
  turnRight: function (angle, speed) {
    this._turn(angle, false, speed)
  },
  _turn: function (angle, direction, speed) {
      var direction = direction ? 1 : -1
      if (speed) {
      if(this.startAngle < angle) {
          this.mesh.rotation.y += speed
        this.startAngle += speed
        if (angle - this.startAngle < speed) {
          var originAngle = this.mesh.rotation.y - this.startAngle
          this.mesh.rotation.y = originAngle + angle
          this.startAngle = 0
          return
        }
      }
      } else {
      this.mesh.rotation.y += angle * direction
      }
  },
  _moving: function (speed, direction) {
    var rotation = this.mesh.rotation.y
    var direction = direction ? 1 : -1
    var xLength = speed * Math.cos(rotation) * direction,
        zLength = speed * Math.sin(rotation) * direction
    this.mesh.position.x +=  xLength
    this.mesh.position.z -= zLength
    this._rotateWheels(speed)
  },
  _rotateWheels: function (speed) {
    this.wheels.forEach(function (elem) {
      elem.rotation.z -= 0.1*speed
    })
  }
}
 // 生成汽车
 function buildStaticCars () {
   var carsPosition = [
     [-84, 82, 1.5], [-58, 82, 1.5], [-32, 82, 1.5] , [84, 82, 1.5]
   ]
   carsPosition.forEach(function (elem) {
     var car = new Car()
     var x = elem[0],
         z = elem[1],
         r = elem[2]
     car.setPosition(x, 0, z)
     car.mesh.rotation.y = r * Math.PI
     scene.add(car.mesh)
   })
 }

最后

作为自己入门Three.js的一个案例, 还是以实现基本效果为目标, 最终效果和期望的还是有一定的差距, 所以未来还将不断探索Three.js的一些高级技巧。

大概就到这里了, 欢迎star

查看原文

花田土著 发布了文章 · 2018-03-12

ice design 入门手札(一)

icework 新建页面

  • src/nav.js 中修改菜单显示名字,此外可通过该文件配置首页左侧菜单。
const autoGenAsideNavs = [
  {
    text: "可视化文件管理",
    to: "/visualFileTable1",
    icon: 'home'
  }
];

请求数据CORS 后端处理(spring boot)

细粒度处理(类、方法)加注解:

@CrossOrigin(origins = "http://localhost:4444")

全局处理:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                    .allowedOrigins("http://localhost:4444");
    //              .allowedMethods("PUT", "DELETE")
    //              .allowedHeaders("header1", "header2", "header3")
    //              .exposedHeaders("header1", "header2")
    //              .allowCredentials(false).maxAge(3600);
            }
        };
    }
}

tips:此处配置的是“localhost”,如果您访问的是127.0.0.1的话还是跨域失败的,聪明的你应该知道怎么解决。

修改页面baseURL及url,method默认为get,data-binder中对应params。如果是post改为data

@DataBinder({
  tableData: {
    // 详细请求配置请参见 https://github.com/axios/axios
    baseURL: 'http://localhost:8080/',
    url: 'complex-tab-table-list.json',
    params: {
      page: 1,
    },
    defaultBindingData: {
      list: [],
      total: 100,
      pageSize: 10,
      currentPage: 1,
    },
  },
})

@DataBinder({
  tableData: {
    baseURL: 'http://localhost:8080/',
    url: 'user/listUserByCriteria',
    method: 'post',
    data: {},
    //headers: {
    //  Accept: 'application/json',
    //  'Content-Type': 'multipart/form-data'
    //}
    defaultBindingData: {
      list: [],
      total: 100,
      pageSize: 3,
    },
  },
})

data-binder入门传送,听说近期会开源,坐等。

post form数据

默认post的Content-Type是application/json,习惯了application/x-www-form-urlencoded的话,可以npm install qs来包装下,

import qs from 'qs';

// TODO
componentDidMount() {
this.queryCache.pageIndex = 1;
this.queryCache.pageSize = 3;

this.data = qs.stringify({
  ...this.queryCache
});

this.fetchData();
}

// data存放查询参数
fetchData = () => {
this.props.updateBindingData('tableData', {
  data: this.data,
});
};

关于Pagination current

demo依赖mock数据中currentPage来更新current,改成实际后台数据后,不建议这么照搬。可参照官方Paginationdemo修改current到state里。

Icon

ice中提供了icon、FoundationSymbol两套图标。同时支持自定义图标DynamicIcon。css从iconfont获取(找到需要的图标添加到项目->选择Font class->生成地址)。注:目前采用fontclass引入字体图标,故不支持多色。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import DynamicIcon from 'dynamic-icon';

// 使用 custom 生成自定义 ICON 组件
const CustomIcon = DynamicIcon.create({
  fontFamily: 'iconfont',
  prefix: 'icon',
  css: 'https://at.alicdn.com/t/font_1472628097_7496383.css'
});
export default CustomIcon;

其他页面使用

import CustomIcon from '../../../../components/CustomIcon';

...

<CustomIcon type="dingding" />

webpack path

node_modulesice-scriptslibconfigwebpack.config.dev.js
node_modulesice-scriptslibconfigwebpack.config.prod.js

关于作者

查看原文

赞 0 收藏 0 评论 0

花田土著 发布了文章 · 2018-03-12

ice design 入门手札(一)

icework 新建页面

  • src/nav.js 中修改菜单显示名字,此外可通过该文件配置首页左侧菜单。
const autoGenAsideNavs = [
  {
    text: "可视化文件管理",
    to: "/visualFileTable1",
    icon: 'home'
  }
];

请求数据CORS 后端处理(spring boot)

细粒度处理(类、方法)加注解:

@CrossOrigin(origins = "http://localhost:4444")

全局处理:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                    .allowedOrigins("http://localhost:4444");
    //              .allowedMethods("PUT", "DELETE")
    //              .allowedHeaders("header1", "header2", "header3")
    //              .exposedHeaders("header1", "header2")
    //              .allowCredentials(false).maxAge(3600);
            }
        };
    }
}

tips:此处配置的是“localhost”,如果您访问的是127.0.0.1的话还是跨域失败的,聪明的你应该知道怎么解决。

修改页面baseURL及url,method默认为get,data-binder中对应params。如果是post改为data

@DataBinder({
  tableData: {
    // 详细请求配置请参见 https://github.com/axios/axios
    baseURL: 'http://localhost:8080/',
    url: 'complex-tab-table-list.json',
    params: {
      page: 1,
    },
    defaultBindingData: {
      list: [],
      total: 100,
      pageSize: 10,
      currentPage: 1,
    },
  },
})

@DataBinder({
  tableData: {
    baseURL: 'http://localhost:8080/',
    url: 'user/listUserByCriteria',
    method: 'post',
    data: {},
    //headers: {
    //  Accept: 'application/json',
    //  'Content-Type': 'multipart/form-data'
    //}
    defaultBindingData: {
      list: [],
      total: 100,
      pageSize: 3,
    },
  },
})

data-binder入门传送,听说近期会开源,坐等。

post form数据

默认post的Content-Type是application/json,习惯了application/x-www-form-urlencoded的话,可以npm install qs来包装下,

import qs from 'qs';

// TODO
componentDidMount() {
this.queryCache.pageIndex = 1;
this.queryCache.pageSize = 3;

this.data = qs.stringify({
  ...this.queryCache
});

this.fetchData();
}

// data存放查询参数
fetchData = () => {
this.props.updateBindingData('tableData', {
  data: this.data,
});
};

关于Pagination current

demo依赖mock数据中currentPage来更新current,改成实际后台数据后,不建议这么照搬。可参照官方Paginationdemo修改current到state里。

Icon

ice中提供了icon、FoundationSymbol两套图标。同时支持自定义图标DynamicIcon。css从iconfont获取(找到需要的图标添加到项目->选择Font class->生成地址)。注:目前采用fontclass引入字体图标,故不支持多色。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import DynamicIcon from 'dynamic-icon';

// 使用 custom 生成自定义 ICON 组件
const CustomIcon = DynamicIcon.create({
  fontFamily: 'iconfont',
  prefix: 'icon',
  css: 'https://at.alicdn.com/t/font_1472628097_7496383.css'
});
export default CustomIcon;

其他页面使用

import CustomIcon from '../../../../components/CustomIcon';

...

<CustomIcon type="dingding" />

webpack path

node_modulesice-scriptslibconfigwebpack.config.dev.js
node_modulesice-scriptslibconfigwebpack.config.prod.js

关于作者

查看原文

赞 0 收藏 0 评论 0

花田土著 回答了问题 · 2018-03-01

解决properties配置文件改写为yml格式问题

找到一篇文章来答疑我的问题,数组内包含hash:

cas:
  authn:
    attribute-repository:
      jdbc:
        - single-row: true
          order: 0
        - single-row: true
          order: 1

关注 2 回答 1

花田土著 发布了文章 · 2018-01-30

Springboot 多模块 jsp

项目结构

module1(如:封装好的一套组织机构、权限、角色、用户管理模块)包含jsp页面,module2(具体业务应用场景开发)依赖module1,结构图如下:

parent
│       
└── module1
│   │── ...
│   └── src/main/resources
│       │── mapper
│       │── public
│       │   ...
│       src/main/webapp
│       └── WEB-INF
│            └── jsp
│
└── module2
    │   ...

解决方案

  • module1和module2的packaging均为jar。
  • src/main/resources下静态资源,及src/main/webapp/WEB-INF/jsp通过==resources==打包到META-INF目录下。这里的META-INF指打成jar后,jar里的META-INF。值得注意的是,如果您的mapper位于src/main/resources下,也需要打包出来哦。


module1's pom.xml的build标签内中添加resources:

<resources>
    <!-- 打包时将jsp文件拷贝到META-INF目录下-->
    <resource>
        <!-- 指定resources插件处理哪个目录下的资源文件 -->
        <directory>src/main/webapp</directory>
        <!-- 注意必须要放在此目录下才能被访问到-->
        <targetPath>META-INF/resources</targetPath>
        <includes>
            <include>**/**</include>
        </includes>
    </resource>
    <resource>
        <directory>src/main/resources/public</directory>
        <targetPath>META-INF/resources</targetPath>
        <includes>
            <include>**/**</include>
        </includes>
    </resource>
    <resource>
        <directory>src/main/resources</directory>
        <includes>
            <include>**/**</include>
        </includes>
        <filtering>false</filtering>
    </resource>
</resources>
  • 普通项目直接在application.yml中配置即可,多模块项目无效。采用WebConfig.java:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("/");
    }
    /**
     * 多模块的jsp访问,默认是src/main/webapp,但是多模块的目录只设置yml文件不行
     * @return
     */
    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(org.springframework.web.servlet.view.JstlView.class);
        // jsp目录
        resolver.setPrefix("/WEB-INF/jsp/");
        // 后缀
        resolver.setSuffix(".jsp");
        return resolver;
    }
}

展望

  • 是否支持module1热部署;

关于作者

查看原文

赞 1 收藏 0 评论 1

花田土著 提出了问题 · 2018-01-03

有什么软件能画这种 立体结构图 吗

类似这种:
图片描述

图片描述

关注 4 回答 1

花田土著 发布了文章 · 2017-12-30

SSO CAS服务端篇

一些芝士

SSO的技术的几种技术方案

  • 基于cookies实现

适合同父域(将domain设置为rebey.cn,则a.rebey.cn与b.rebey.cn共享cookie)

  • 基于session共享来实现

Session中所涉及的类型必须是子系统中共同拥有的(即程序集、类型都需要一致),不同语言互通相对麻烦

  • 基于票据ticket来实现(CAS)

支持跨域,支持多语言客户端

请求过程

pac4j

image

图一来自pac4j,图二来自网络(哪篇博客存的图在下忘了- -)。很透彻的两张图。

image

图三为本人手绘。描述了先访问A系统再访问B系统。记录下过程中一些重要点和问题:
一直纠结4认证成功后为什么要进行5,6步。暂且理解为为了解决跨域问题。

初始构建

cas-management-overlay下载官方提供的maven overlay(省去下载源码通过gradle去构建环节)。

根据实际情况调整pom.xml;如:依赖的war包通过ali库无法下载,需要手动下载。

cmd运行build.cmd run启动(前提是需要安装maven,配置环境变量)。这种启动方式不太友好,是否能直接通关eclipse启动希望赐教。

启动后默认地址:http://localhost:8443/cas

默认用户名/密码为:casuser/Mellon

修改为oracle数据库jdbc验证

#cas.authn.accept.users=casuser::Mellon

cas.authn.jdbc.query[0].sql=select password from cap_user where user_id=?
cas.authn.jdbc.query[0].healthQuery=SELECT 1 from dual
cas.authn.jdbc.query[0].isolateInternalQueries=false
cas.authn.jdbc.query[0].url=jdbc:oracle:thin:@127.0.0.1:1521/ORCL
cas.authn.jdbc.query[0].failFast=true
cas.authn.jdbc.query[0].isolationLevelName=ISOLATION_READ_COMMITTED
cas.authn.jdbc.query[0].dialect=org.hibernate.dialect.OracleDialect
cas.authn.jdbc.query[0].leakThreshold=10
cas.authn.jdbc.query[0].propagationBehaviorName=PROPAGATION_REQUIRED
cas.authn.jdbc.query[0].batchSize=1
cas.authn.jdbc.query[0].user=iamsuser
cas.authn.jdbc.query[0].ddlAuto=create-drop
cas.authn.jdbc.query[0].maxAgeDays=180
cas.authn.jdbc.query[0].password=iamsuser
cas.authn.jdbc.query[0].autocommit=false
cas.authn.jdbc.query[0].driverClass=oracle.jdbc.driver.OracleDriver
cas.authn.jdbc.query[0].idleTimeout=5000
cas.authn.jdbc.query[0].fieldPassword=password

自定义加密匹配

cas.authn.jdbc.query[0].passwordEncoder.type= com.che.ChePasswordEncoder
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;

import sun.misc.BASE64Encoder;

public class ChePasswordEncoder implements PasswordEncoder {
    // 盐值(加密混淆)
    private final static String slat = "diasj29er2ur734tuei89u34efdfi30q7u5834tdphf056=-251758";
    
    /**
     * 利用MD5进行加密
     * 
     * @param str 待加密的字符串
     * @return 加密后的字符串
     * @throws NoSuchAlgorithmException 没有这种产生消息摘要的算法
     * @throws UnsupportedEncodingException
     */
    @Override
    public String encode(CharSequence rawPassword) {
        if (rawPassword == null) {
            return null;
        }
        String newstr = null;
        rawPassword = rawPassword + "/" + slat;
        // 确定计算方法
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
            BASE64Encoder base64en = new BASE64Encoder();
            // 加密后的字符串
            newstr = base64en.encode(md5.digest(rawPassword.toString().getBytes("utf-8")));
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        System.out.println("==========================="+newstr);
        return newstr;
    }

    @Override
    public boolean matches(CharSequence rawPassword, String encodedPassword) {
        String encodeedRawPassword = StringUtils.isNotBlank(rawPassword) ? this.encode(rawPassword.toString()) : null;
        boolean matched = StringUtils.equals(encodeedRawPassword, encodedPassword);
        return matched;
    }
}

可返回(用户表)更多属性配置

cas.authn.attributeRepository.jdbc[0].singleRow=true
cas.authn.attributeRepository.jdbc[0].order=0
cas.authn.attributeRepository.jdbc[0].url=jdbc:oracle:thin:@127.0.0.1:1521/ORCL
cas.authn.attributeRepository.jdbc[0].username=user_id
cas.authn.attributeRepository.jdbc[0].user=iamsuser
cas.authn.attributeRepository.jdbc[0].password=iamsuser
cas.authn.attributeRepository.jdbc[0].sql=select * from cap_user where user_id=?
cas.authn.attributeRepository.jdbc[0].dialect=org.hibernate.dialect.OracleDialect
cas.authn.attributeRepository.jdbc[0].ddlAuto=none
cas.authn.attributeRepository.jdbc[0].driverClass=oracle.jdbc.driver.OracleDriver
cas.authn.attributeRepository.jdbc[0].leakThreshold=10
cas.authn.attributeRepository.jdbc[0].propagationBehaviorName=PROPAGATION_REQUIRED
cas.authn.attributeRepository.jdbc[0].batchSize=1
cas.authn.attributeRepository.jdbc[0].healthQuery=SELECT 1 from dual
cas.authn.attributeRepository.jdbc[0].failFast=true

这里很多相同的参数配置两遍应该不太友好的,有待推敲;

jdbc[0]这种 转 yml格式搜不到可行写法,希望有缘人赐教。

不允许使用CAS来认证您访问的目标应用。

src/main/resources下添加services文件夹,添加HTTPSandIMAPS-10000001.json(文件名有规则,暂时未知):

{
    "@class": "org.apereo.cas.services.RegexRegisteredService",
    "serviceId": "^(http|https|imaps)://.*",
    "name": "HTTPS and IMAPS",
    "id": 10000001,
    "description": "This service definition authorizes all application urls that support HTTPS and IMAPS protocols.",
    "evaluationOrder": 10000,
    "attributeReleasePolicy": {
        "@class": "org.apereo.cas.services.ReturnAllAttributeReleasePolicy"
    }
}

啰嗦几句

本意springboot+shiro集成cas,需要一个cas server,发现相关资料很少,尤其中文好资料。因为大公司都用自己的开发的cas吗。。

待续...

更多有意思的内容,欢迎访问笔者小站:rebey.cn

一些链接

本文github:点这里

官方软文:cas5-gettingstarted-overlay

@yuchanghui搭建的server与client:buyi-sso

系列博客:CAS单点登录

查看原文

赞 1 收藏 5 评论 0

花田土著 提出了问题 · 2017-12-30

解决properties配置文件改写为yml格式问题

cas.authn.attributeRepository.jdbc[0].singleRow=true
cas.authn.attributeRepository.jdbc[0].order=0

如何改写成yml形式?

关注 2 回答 1

花田土著 关注了问题 · 2017-12-24

解决cas登录的问题

CAS登录过程是这样的:

  1. 登录http://a.alibaba.com/,

  2. 重定向到:http://cas.alibaba.com?url=ht...

  3. 登录页面输入用户名密码登录成功,跳转到http://a.alibaba.com?ticket=xxxx

  4. cas server 认证ticket合法之后,set cookie到浏览器内存中一个cookie;

  5. 以后所有到访问都会带着这个cookie来访问,当然cookie是放在内存中到,浏览器关闭,cookie失效,要重新登录;并且cookie是有失效期的,失效之后,需要重新登录。

我的问题是:

输入用户名密码之后,cas server可以直接set cookie到浏览器,为什么还要多一步校验ticket的过程呢?为什么?感觉有点儿多此一举的啊?

求解答,拜谢~~~

关注 7 回答 4

花田土著 关注了问题 · 2017-11-29

大家是用什么方式生成 CSS sprites 的?

公司原先是手动合并的, 一个是效率低, 前端和美工工作都比较麻烦,
另一个是图片位置通过手工调整难以保证位置完全正确..
然后我做了两次尝试

  • Spritesmith

用了 Grunt 插件, 可以定义 CSS 模版. 合并基本是完成.
问题是不支持 Retina, 每次合并又不一样, 比较麻烦.

  • glue

解决了 Retina 合并的问题, 但是有两个问题,
一个定制性, Grunt 插件文档不清晰, 另外生成的 CSS 可能需要手工定制.
致命的是 Retina 生成的小图片图标质量不过关,
据说说 0.9 可以解决, 但需要手动安装, 我现在还没有尝试.

后面也开始找其他方案,

有推荐 peach, 但文档稍微找了下还没弄明白,
又有找 Fireworks 插件导出 CSS, 目前不熟悉工具也没有尝试..

不知道大家试过的方案有哪些好的?

可能要考虑进去的问题

  • Grunt 支持或者其他的脚本支持
  • CDN 部署的文件名和直接合并的不一致, 可能用模版去解决
  • Retina 的支持, 能生成 backgroupd-position.
  • Retina 下自动缩放图片而且保持清晰度
  • 工具需要跨平台, 在 OS X 和 Windows 上进行使用

关注 8 回答 12