超凡魔力

君子善思,善假于物,而不物于物。

0%

linux中find命令详解。对于使用各种条件来查找文件,该命令非常的重要,而且还能使用-exec参数,附加命令,(跟xargs很像),完成更多的功能。

类似于资源管理器中的查找功能。

阅读全文 »

swoole跟nginx配置

nginx的配置文件,关键点:请求的url不存在对应的文件,做跳转的判断。两种方式。

阅读全文 »

js的异步代码

js中的代码都是单线程的。遇到异步的代码,特别注意。因为调用getRoomOption过一次,再执行setRoomOption不会报错,如果没有执行的话,那么option就会出错。

initComponent:function(){//先执行
    var me = this;
    me.applyMeetingOrderMenu();
    me.responseToMessageHub();//所有消息绑定
    me.getRoomOption();//默认已经触发一次。
    me.callParent(); 
},

/***********
 * 2019年1月10日
 * 获取所有的会议室选项
 ***********/
getRoomOption:function(){
    var me=this;
    if(me.roomOption){
        return me.roomOption;
    }
    Ext.Ajax.request({
        url: SHINEVMSHTTP +'/admin/room/list/getroomoption',
        method:"GET",
        success: function(response, opts){
            //解码
            var obj = Ext.decode(response.responseText);
            //整理后的数组
            var ret={};
            Ext.each(obj,function(option){
                var id=option['conferenceroom_id'];
                if(!ret[id]){
                    ret[id]=[];
                }
                ret[id].push(option['option_value']);
            });
            me.roomOption=ret;
            return ret;
        }
    });
},
/***********
 * 2019年1月10日
 * 设置当前已选会议室的电话、视频会议选项
 ***********/
setRoomOption:function(roomId){
    var me=this;
    var option=me.getRoomOption();
    var cur=option[roomId];
    var vm=me.getViewModel();
    var v=vm.getData();
    //先设置全部不可见
    vm.set({
        'option1':true,
        'option2':true,
        'option3':true
    });
    //设置该会议室的可见选项
    Ext.each(cur,function(v){
        var o={};
        o['option'+v]=false;
        vm.set(o);
    });
    //默认选第一个可选项。
    for(var i=1;i<=3;i++){
        if(v['option'+i]===false){
            vm.set({meeting_video:''+i});
            return ;
        }
    }
}

shell综合使用例子

  • sudo docker image ls |grep none |awk ‘{print $3}’ | xargs -n 1 sudo docker rmi

删除 none标记的镜像,综合用了 grep awk xargs 工具。

shell

查看端口占用

netstat -tunlp |grep 端口号,用于查看指定的端口号的进程情况,如查看8000端口的情况,netstat -tunlp |grep 8000

-t (tcp) 仅显示tcp相关选项
-u (udp)仅显示udp相关选项
-n 拒绝显示别名,能显示数字的全部转化为数字
-l 仅列出在Listen(监听)的服务状态
-p 显示建立相关链接的程序名

ls的用法

ls -l |grep “^-“|wc -l或find ./company -type f | wc -l 查看某文件夹下文件的个数,包括子文件夹里的。

ls -lR|grep “^-“|wc -l 查看某文件夹下文件夹的个数,包括子文件夹里的。

ls -lR|grep “^d”|wc -l

说明:ls -l 长列表输出该目录下文件信息(注意这里的文件,不同于一般的文件,可能是目录、链接、设备文件等)

      grep "^-"  这里将长列表输出信息过滤一部分,只保留一般文件,如果只保留目录就是 ^d

      wc -l 统计输出信息的行数,因为已经过滤得只剩一般文件了,所以统计结果就是一般文件信息的行数,又由于一行信息对应一个文件,所以也就是文件的个数。 

du的用法

du命令用来查看目录或文件所占用磁盘空间的大小。常用选项组合为:du -sh

du常用的选项:
  -h:以人类可读的方式显示
  -a:显示目录占用的磁盘空间大小,还要显示其下目录和文件占用磁盘空间的大小
  -s:显示目录占用的磁盘空间大小,不要显示其下子目录和文件占用的磁盘空间大小
  -c:显示几个目录或文件占用的磁盘空间大小,还要统计它们的总和
  --apparent-size:显示目录或文件自身的大小
  -l :统计硬链接占用磁盘空间的大小
  -L:统计符号链接所指向的文件占用的磁盘空间大小  
du -sh : 查看当前目录总共占的容量。而不单独列出各子项占用的容量 

du -lh --max-depth=1 : 查看当前目录下一级子文件和子目录占用的磁盘容量。

du -sh * | sort -n 统计当前文件夹(目录)大小,并按文件大小排序
du -sk filename 查看指定文件大小

找不到对象me

以前的处理方式是,利用apply函数,将其放到其作用域中,然后能获取到作用域内的me变量。

定义upper

下面是另外一种方式,来为store这种对象增加upper属性,并指向当前的me对象。然后使其能获取到me对象。

afterrender: function (cmp, eOpts) {
    var me = this;
    var height = me.getHeight();
    var margin = (height - 150 - 200 * 2) / 4;
    if (margin > 50 || margin < 0) { //超出边界
        margin = margin > 50 ? 50 : 0;
    }
    me.dvMargin = margin;
    var dv = me.down('dataview');
    Ext.apply(dv.store, {//注意,在这里为其增加一个属性upper
        upper: me
    });
}

使用upper

下面是store的一个listeners,然后cmp拥有upper这个属性,获取到me对象。顺利的传递了upper属性。

listeners: {
    'load': function (cmp, records, successful, operation, eOpts) {
        var me = cmp.upper;
        var margin = me.dvMargin;
        Ext.each(records, function (rd) {
            rd.set({
                margin: margin
            });
            rd.commit();
        });
    }
}

说明

这个其实是之前,突发奇想,然后发现可以利用这种对象属性的方式,来传递变量,关键的属性等。这样,新增的属性即获取到了特定的对象。像store这样的组件,没有up函数,很难找到me变量。

更改

store这样的组件应该能获取到该组建绑定的组件的能力。这样更具有一般性。

NodeMCU

NodeMCU网站例子

网站地址

手册地址

wifi模块

wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
print(wifi.sta.getip())

-- wifi.sta.connect()

像Arduino一样操作IO

pin = 1
gpio.mode(pin,gpio.OUTPUT)
gpio.write(pin,gpio.HIGH)
gpio.mode(pin,gpio.INPUT)
print(gpio.read(pin))

简单的HTTP客户端

-- A simple http client
conn=net.createConnection(net.TCP, false) 
conn:on("receive", function(conn, pl) print(pl) end)
conn:connect(80,"121.41.33.127")
conn:send("GET / HTTP/1.1\r\nHost: www.nodemcu.com\r\n"
    .."Connection: keep-alive\r\nAccept: */*\r\n\r\n")

更简单的HTTP服务器

-- a simple http server
srv=net.createServer(net.TCP) 
srv:listen(80,function(conn) 
    conn:on("receive",function(conn,payload) 
    print(payload) 
    conn:send("<h1> Hello, NodeMcu.</h1>")
    end) 
end)

PWM操作

function led(r,g,b) 
    pwm.setduty(1,r) 
    pwm.setduty(2,g) 
    pwm.setduty(3,b) 
end
pwm.setup(1,500,512) 
pwm.setup(2,500,512) 
pwm.setup(3,500,512)
pwm.start(1) 
pwm.start(2) 
pwm.start(3)
led(512,0,0) -- red
led(0,0,512) -- blue

闪烁LED

tmr.alarm 是定时器,会周期的执行回调函数。四个参数。按顺序为:

0 任务id。结束定时器的时候,需要用到。

1000 即1000毫秒,每1000毫秒执行一次回调。

1 不知道什么作用,常为1.

function ,即回调函数。

lighton=0
tmr.alarm(0,1000,1,function()
if lighton==0 then 
    lighton=1 
    led(512,512,512) 
    -- 512/1024, 50% duty cycle
else 
    lighton=0 
    led(0,0,0) 
end 
end)

启动文件

--init.lua will be excuted
file.open("init.lua","w")
file.writeline([[print("Hello World!")]])
file.close()
node.restart()  -- this will restart the module.

用定时器来循环执行

tmr.alarm(1,5000,1,function() print("alarm 1") end)
tmr.alarm(0,1000,1,function() print("alarm 0") end)
tmr.alarm(2,2000,1,function() print("alarm 2") end)
-- after sometime
tmr.stop(0)

纯Lua写的telnet服务器

-- a simple telnet server
s=net.createServer(net.TCP,180) 
s:listen(2323,function(c) 
    function s_output(str) 
      if(c~=nil) 
        then c:send(str) 
      end 
    end 
    node.output(s_output, 0)   
    -- re-direct output to function s_ouput.
    c:on("receive",function(c,l) 
      node.input(l)           
      --like pcall(loadstring(l)), support multiple separate lines
    end) 
    c:on("disconnection",function(c) 
      node.output(nil)        
      --unregist redirect output function, output goes to serial
    end) 
    print("Welcome to NodeMcu world.")
end)

与传感器接口

-- read temperature with DS18B20
t=require("ds18b20")
t.setup(9)
addrs=t.addrs()
-- Total DS18B20 numbers, assume it is 2
print(table.getn(addrs))
-- The first DS18B20
print(t.read(addrs[1],t.C))
print(t.read(addrs[1],t.F))
print(t.read(addrs[1],t.K))
-- The second DS18B20
print(t.read(addrs[2],t.C))
print(t.read(addrs[2],t.F))
print(t.read(addrs[2],t.K))
-- Just read
print(t.read())
-- Just read as centigrade
print(t.read(nil,t.C))
-- Don't forget to release it after use
t = nil
ds18b20 = nil
package.loaded["ds18b20"]=nil

禁止自动填充

最近一周,都是做会议预约的代码改进工作。大部分都是一些没有含量的但是枯燥的操作。下面记录了两个改进。如下:

谷歌浏览器的自动填充功能

不明白其中的原理,网上也找不到好的解决方式。自己按下面处理,效果还不错,暂未发现其他问题。在change函数中,重新复制,防止会造成死循环。通过计数的方式。

change:function(cmp, newValue, oldValue, eOpts){
                var me = this.up('selectusergrid');
                if(me.resetValue&&!this.hasFocus){
                    me.resetValue=false;
                    this.setValue('');
                }
                me.searchValue = newValue;
            },

过滤掉admin字段

思维过程:最开始想在后台进行过滤,但是发现,后台的api接口在多个地方调用,不太方便过滤,有的地方还需要显示admin用户。后来就想,直接在store的load事件中,进行过滤。刚想使用Ext.each的时候发现filter函数更好用,然后就想用filter函数。然后突然发现,其实直接使用store的filter不是更好吗?而且总条数也好了。以下是代码:

store:{
                fields:[
                    { name: 'login_name', type:'string'},
		           //注意下面的类型转换。
                    { name: 'user_id', type:'int'},
                    { name: 'role_name', type:'string'},
                    { name: 'employee_name', type:'string'},
                    { name: 'department_name', type:'string' }
                    //{ name: 'create_time', type:'string' }
                ],
                pageSize:100,
                proxy: {
                    type: 'ajax',
                    method:"POST",
                    url: SHINEVMSHTTP+'/admin/role/user/getuserinfo',
                    reader: {
                        type: 'json',
                        totalProperty:'count',
                        rootProperty:'result'
                    }
                },
                autoLoad: true,
                //下面是增加的代码。
                filters: [
                    function(item) {
                        //item实际上是record,最好用item.get来获取,
                        //至于此出的函数有没有经过类型转换,还不清楚
                        return parseInt(item.get('user_id')) > 1;
                        //return item.role_id > 1;  //最好不要这样用。
                    }
                ],

Ext中表单验证问题

Ext中自带表单,但是表单在复用过程中,即只隐藏,下次需要的时候,再次show出来。表单本身可以通过setValues、getValues来操作,但是由于前期写代码的时候,并不知道表单也有这两个方法,加之之前人的代码也是使用了viewModel来进行传递值,所以呢,前期的代码就使用了viewModel进行更改表单的值。这样做,其实有两个不好的地方,其一就是,需要增加绑定的代码,增加了代码,使代码看上去更复杂,不简洁;其二,表单通过viewModel来更改值,即getViewModel().setData() ,这个函数操作后,实际上有一定的延时。而且如何设置了空值,则会引起表单进行验证,有红色的框,看起来不够好看。所以呢,不太建议使用viewModel来与表单进行绑定。

下面的代码,是我预约项目中使用到的。如下:

方式一是有问题的,问题是:在添加模式跟编辑模式,使用了两种不同的方式进行传递值。结果就是,方式一,setViewModel之后,导致了前后绑定不正确的原因。

而方式二,好像就没有这个问题。

//添加医生窗口
        me.addDoctorWin = Ext.create('ShineECallView.view.nursing.AddDoctorWin',{
			//添加事件监听器
			listeners:{
				'show':function(c,o){
                    var rds = me.getSelectionModel().getSelection();
                    var form=c.down('form');
                    if(c.actionType!=1){//编辑 
                        var data=Ext.clone(rds[0]['data']);
                        console.log(data);
                        console.log(Ext.encode(data));
                        // window.cmp=c;
                        //方式一:
                        c.getViewModel().setData(data);   
                        //方法二:
                        // form.getForm().setValues(data);
					}else{//添加
                        form.getForm().setValues({
                            "Doctor_ID":'0',
                            'Doctor_Name':'',
                            'Doctor_Title': '',
                            'Doctor_Image':'',
                            'Doctor_Sex': '1',
                            'Department':me.groupIdList[0],
                        });
					}
                },
                'hide':function(c,o){
                    c.down('form').reset();
                }
            }
        });