我的ASP.NET之旅(四):IIS网站部署步骤及常见错误 - Luke Zhang - 博客园

mikel阅读(913)

来源: 我的ASP.NET之旅(四):IIS网站部署步骤及常见错误 – Luke Zhang – 博客园

ASP.NET程序已经有几年了,可是每每将网站或者Web应用程序部署到IIS上的时候,还总是出错。每次都需要查看错误信息,甚至搜索网络找到处理方法,于是这一次来了个全程记录,把步骤和遇到的问题都记下来,与同道共享:)

1、在IIS中创建虚拟目录(WebSite)或者应用程序(WebApp);

注意:发布的程序必须创建应用程序,否则出错如下:

Parser Error Message: Could not load the assembly ‘App_Web_nqebt6fg’. Make sure that it is compiled before accessing the page.

Source Error:

Line 1:  <%@ page language="C#" autoeventwireup="true" inherits="_Default, App_Web_nqebt6fg" %>

2、给IIS_IUSRS和IUSR赋予虚拟目录读写权限,否则出错如下:

HTTP Error 500.19 – Internal Server Error

The requested page cannot be accessed because the related configuration data for the page is invalid.

3、设置“认证”属性,启用“仿冒”,否则出错如下:

HTTP Error 401.3 – Unauthorized

You do not have permission to view this directory or page because of the access control list (ACL) configuration or encryption settings for this resource on the Web server.

4、设置应用程序池为“经典模式”(如果需要的话),否则出错如下:

HTTP Error 500.24 – Internal Server Error

An ASP.NET setting has been detected that does not apply in Integrated managed pipeline mode.

5、在连接字符串中不要使用集成安全,而是使用用户名/密码(如果不是Windows认证的话),否则出错如下:

  Exception Details: System.Data.SQLClient.SQLException: Login failed for user ‘NT AUTHORITY\IUSR’.

layui 重载传参以及加载两次问题

mikel阅读(1684)

来源: layui 重载传参以及加载两次问题

layui.use([‘table‘,‘layer‘], function () {
var $ = layui.JQuery, layer = layui.layer;
var table = layui.table;
var txtRet = document.getElementById(“<%= txt_RegName.ClientID %>”);
var tableIns = table.render({
elem: ‘#idTest‘
, height: 500
, url: ‘/Hander/VehicleReport.ashx‘ //数据接口
//, data: { “vehicleId”: vehicleId }
//,where:{
// RegName: txtRet.value
//}
, page: true //开启分页
, id: ‘testReload‘
, cols: [[ //表头
{ title: ‘序号‘, field: ‘rownumber‘ }
, { field: ‘RegName‘, title: ‘车牌号‘}
, { field: ‘DriverName‘, title: ‘司机‘ }
, { field: ‘StatusStr‘, title: ‘状态‘ }
, { field: ‘InStationTime‘, title: ‘进站时间‘ }
, { field: ‘OutStationTime‘, title: ‘出站时间‘}
, { field: ‘StationName‘, title: ‘中转站名称‘ }
, { field: ‘InFactoryTime‘, title: ‘进厂时间‘}
, { field: ‘OutFactoryTime‘, title: ‘出厂时间‘ }
, { field: ‘FactoryName‘, title: ‘工厂名称‘}

]]
});
$(‘.layui-btn‘).on(‘click‘, function () {
var type = $(this).data(‘type‘);
active[type] ? active[type].call(this) : ‘‘;
});
var active = {
reload: function () {
//执行重载
tableIns.reload({
page: {
curr: 1 //重新从第 1 页开始
}
, where: {
RegName: txtRet.value
}
});
}
};

代码是这样,传参使用一般处理程序接收,接收不到是因为此页面引用母版页,获取不到真实的ID,需要document.getElementById(“<%= txt_RegName.ClientID %>”).value去赋值

重载两次是因为搜索用的是button,改成<a class=”layui-btn” data-type=”reload”>搜索</a>就可以了,虽然不知道是什么原因

自动售货机控制系统 - CSDN博客

mikel阅读(1726)

来源: 自动售货机控制系统 – CSDN博客

设计说明

根据要求可自动出售两种货物,这里的自动售货机可销售cola和pepsi两种饮料:售货机可识别1元和0.5元两种货币,在一次购买过程中,可购买一个或者多个商品,系统会自动计算所需钱数和找零的钱数并自动找零。另外有3个发光二极管、6个LCD数码管:两个用来显示所需金额,两个用来显示已付金额,两个用来显示找零数。


流程说明

这里设计的自动售货机当通电时,表示一次销售的开始。顾客选择一种商品或多种商品后就进入投币状态。若不投币,则自动返回初始状态。投币后,系统自动计算所投钱数。若投币够,则出货并找零。若投币不够,如果顾客没有继续投币,则退币并回到初始状态。本系统的投币销售流程图如图所示:
流程图


各模块说明

本文设计的自动售货机总体分四个模块:总控模块、二进制译码模块、BCD码译码模块和顶层模块。

总控模块:总控模块是本系统最重要的模块,该模块大体有5个输入端口和6个输出端口。其输入端口包括clk、coin1(投入一元货币)、coin5(投入0.5元货币)、cola(选择cola)、pepsi(选择pepsi),输出端口有paid(已投入多少钱)、needed(还需多少钱)moneyout(找零)、success(灯亮表示交易成功)、failure(灯亮表示交易失败)、showmoneyout(灯亮表示正在找零)。该模块实现了本系统最重要的交易过程,包括选择商品、投入货币,计算剩余金额,找零出货等。

二进制译码模块:该模块有一个输入端口和两个输出端口。输入端口是一个8位的二进制数输出端口bcd0、bcd1是两个4位的BCD码。该模块的主要的功能是实现将主控模块输出的二进制数(paid、needed、moneyout)转换成BCD码,以便输出到七段数码管上显示出来。该模块的原理是将一个8位的二进制转换成2个4位的BCD码,分为高四位和低四位。

BCD码译码模块:该模块有一个输入端口和一个输出端口

顶层模块:该模块有五个输入和九个输出端口。其输入口包括clk1、P2(选择pepsi)、P1_5(选择cola)、C5(投入5毛)、C1(投入1块),输出端口有shuwout(退币指示灯)、s(交易成功指示灯)、f(交易失败指示灯)、paid_lcd0、paid_lcd1(已付金额)、needed_lcd0、needed_lcd1(需付金额)、mout__lcd0、mout_lcd1(退币金额)。


程序设计

主控模块完整程序
BCD译码模块完整程序
顶层模块完整程序
具体的代码见我的github网站(1自动售货机文档).

各模块连接

售货机主控系统和译码器模块图:
售货机主控系统和译码器模块图

售货机顶层模块:
顶层模块

波形仿真

主控模块的波形方真

这里写图片描述
上图表示顾客选择了pepsi饮料后,且投了2个一元的硬币。Success为高电平,代表售货机有饮料售出。且余额为0.

这里写图片描述
上图表示顾客选择了cola饮料后,且投2个一元的硬币。Success为高电平,代表有饮料售出,且找回顾客0.5元。

BCD译码仿真

这里写图片描述
上图表示自动售货机的译码系统,上图表示将8位数字转换成4位BCD码。

TOP文件的仿真

这里写图片描述
上图表示顾客选择了pepsi饮料后,且投了2个一元的硬币。Success为高电平,代表售货机有饮料售出。且余额为0。

以上是我的一些仿真图,希望对您有帮助。更全面文档点这里

总结

其实这个自动售货机控制系统老师很早之前就要我弄了,我自己一直拖,直到老师要考核才重视起来。
这个项目很多都是在网上找资料借鉴的别人的东西,自己就是把别人的代码读懂了,再将整个的流程走了一遍。收货还是很多的。自己为了第二天老师考核(答辩)的时候能够顺利通过,前一天晚上熬夜到三点。也算是体会到了做项目的艰辛。
在答辩的过程中,老师的一些问题,一些话语也是让我受益匪浅。做项目真的是让我收益很多。这里也希望这篇博客能给大家带来帮助,但是希望只是作为一个参考,更多的部分还是要自己去做,这才您才能真正学习到知识。

大型架构之科普工具篇

mikel阅读(1111)

大型架构之科普工具篇

 

 

 

底部更多详情图….

 

 

I.1 Java Spring Boot

适合构建微服务系统

  • 使用 Spring 项目引导页面可以在几秒构建一个项目
  • 方便对外输出各种形式的服务,如 REST API、WebSocket、Web、Streaming、Tasks
  • 非常简洁的安全策略集成
  • 支持关系数据库和非关系数据库
  • 支持运行期内嵌容器,如 Tomcat、Jetty
  • 强大的开发包,支持热启动
  • 自动管理依赖
  • 自带应用监控
  • 支持各种 IED,如 IntelliJ IDEA 、NetBeans

其它语言:  .net core 、 Go 等

 

I.2 Jenkins

自动CI程序,持续集成

  • 开源免费
  • 跨平台,支持所有的平台(本人是安装在Ubuntu14.04上的,使用jenkins docker镜像没有成功)
  • master/slave支持分布式的build
  • web形式的可视化的管理页面
  • 安装配置超级简单
  • tips及时快速的帮助
  • 已有的几百个插件

 

I.3 GitLab

  • 一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目安装。
    它拥有与GitHub类似的功能,能够浏览源代码,管理缺陷和注释。可以管理团队对仓库的访问,它非常易于浏览提交过的版本并提供一个文件历史库。
    团队成员可以利用内置的简单聊天程序(Wall)进行交流。它还提供一个代码片段收集功能可以轻松实现代码复用,便于日后有需要的时候进行查找。
  • Dokcer
  • Docker是一个开源的引擎,可以轻松的为任何应用创建一个轻量级的、可移植的、自给自足的容器。开发者在笔记本上编译测试通过的容器可以批量地在生产环境中部署,包括VMs(虚拟机)、bare metal、OpenStack 集群和其他的基础应用平台。
  • Docker通常用于如下场景:
  • web应用的自动化打包和发布;
  • 自动化测试和持续集成、发布;
  • 在服务型环境中部署和调整数据库或其他的后台应用;
  • 从头编译或者扩展现有的OpenShift或Cloud Foundry平台来搭建自己的PaaS环境。

 

I.4 Kubernetes

  • Kubernetes是容器集群管理系统,是一个开源的平台,可以实现容器集群的自动化部署、自动扩缩容、维护等功能。
  • 通过Kubernetes你可以:
  • 快速部署应用
  • 快速扩展应用
  • 无缝对接新的应用功能
  • 节省资源,优化硬件资源的使用

 

 

I.5 MQ

当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消息队列,作为抽象层,弥合双方的差异。“ 消息 ”是在两台计算机间传送的数据单位。消息可以非常简单,例如只包含文本字符串;也可以更复杂,可能包含嵌入对象。消息被发送到队列中,“ 消息队列 ”是在消息的传输过程中保存消息的容器 。

  • 解耦
  • 冗余
  • 扩展性
  • 灵活性 & 峰值处理能力
  • 可恢复性
  • 送达保证
  • 排序保证
  • 缓冲
  • 理解数据流
  • 异步通信

 

 

 

 

I.6 SQL DB

  • 数据库(Database)是按照数据结构来组织、存储和管理数据的建立在计算机存储设备上的仓库。
  • 简单来说是本身可视为电子化文件柜——存储电子文件的处所,用户可以对文件中的数据进行新增、截取、更新、删除等操作。
  • 经济管理的日常工作中,常常需要把某些相关的数据放进这样的“仓库”,并根据管理的需要进行相应的处理。

MySQL/PostgreSQL是传统关系型数据库的代表。

HBase是Big Tables技术的代表(行索引,列存储)。

Neo4j(http://www.neo4j.org/)是图数据库代表,用来存储复杂、多维度的图结构数据。

Redis是基于Key-Value的NoSQL代表,有Redis-to-go提供存储服务。

MongoDB/CouchDB是基于Document的NoSQL代表,Couchbase是Document/Key-Value技术的融合。

VoltDB是NewSQL的代表,具备数据一致性和良好的扩展性,性能宣称是MySQL的数十倍以上。

TiDB 是国内 PingCAP 团队开发的一个分布式 SQL 数据库。其灵感来自于 Google 的 F1 和 Google spanner, TiDB 支持包括传统 RDBMS 和 NoSQL 的特性。

 

I.7 TICK stack

InfluxDB

时序数据库工具。

Telegraf

是一个数据收集和入库的工具。提供了很多 input 和 output 插件,比如收集本地的 cpu、load、网络流量等数据,然后写入 InfluxDB 或者 Kafka 等。

Chronograf

绘图工具

Kapacitor

Kapacitor 是 InfluxData 家的告警工具,通过读取 InfluxDB 中的数据,根据 DLS 类型配置 TickScript 来进行告警。

I.8 Keepalived

keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于heartbeat,用来防止单点故障。

keepalived是以VRRP协议为实现基础的,VRRP全称Virtual Router Redundancy Protocol,即虚拟路由冗余协议

虚拟路由冗余协议,可以认为是实现路由器高可用的协议,即将N台提供相同功能的路由器组成一个路由器组,这个组里面有一个master和多个backup,master上面有一个对外提供服务的vip(该路由器所在局域网内其他机器的默认路由为该vip),master会发组播,当backup收不到vrrp包时就认为master宕掉了,这时就需要根据VRRP的优先级选举一个backup当master。这样的话就可以保证路由器的高可用了。

keepalived主要有三个模块,分别是core、check和vrrp。core模块为keepalived的核心,负责主进程的启动、维护以及全局配置文件的加载和解析。check负责健康检查,包括常见的各种检查方式。vrrp模块是来实现VRRP协议的

 

I.9  Harbor

Harbor是一个用于存储和分发Docker镜像的企业级Registry服务器。

I.10  Ignite  /  Redis

Apache Ignite 内存数据组织框架是一个高性能、集成化和分布式的内存计算和事务平台,用于大规模的数据集处理,比传统的基于磁盘或闪存的技术具有更高的性能,同时他还为应用和不同的数据源之间提供高性能、分布式内存中数据组织管理的功能。

序号 对比项目 Apache Ignite Redis
1 JCache (JSR 107) Ignite完全兼容JCache(JSR107)缓存规范 不支持
2 ACID事务 Ignite完全支持ACID事务,包括乐观和悲观并发模型以及READ_COMMITTED, REPEATABLE_READ和SERIALIZABLE隔离级别。 Redis提供了客户端乐观事务的有限支持,在并发更新情况下,客户端需要手工重试事务。
3 数据分区 Ignite支持分区缓存,类似于一个分布式哈希,集群中的每个节点都存储数据的一部分,在拓扑发生变化的情况下,Ignite会自动进行数据的再平衡。 Redis没有提供分区,但是提供了副本的分片,使用分片非常死板,并且不管是客户端还是服务端,每当拓扑发生变化时都需要一系列相当复杂的手工步骤。
4 全复制 Ignite支持缓存的复制,集群中的每个节点的每个键值对都支持。 Redis不提供对全复制的直接支持。
5 原生对象 Ignite允许用户使用自己的领域对象模型并且提供对任何Java/Scala, C++和.NET/C#数据类型(对象)的原生支持,用户可以在Ignite缓存中轻易的存储任何程序和领域对象。 Redis不允许用户使用自定义数据类型,仅支持预定义的基本数据结构集合,比如Set、List、Array以及一些其他的。
6 客户端侧(近)缓存 Ignite提供对于最近访问数据的客户端侧缓存的直接支持。 不支持
7 (服务端侧)并置处理 Ignite支持在服务器端靠近数据以并置的方式直接执行任何Java, C++和.NET/C#代码。 Redis通常没有任何并置处理的能力,服务器端基本只支持LUA脚本语言,服务器端不直接支持Java, .NET,或者C++代码执行。
8 SQL查询 Ignite支持完整SQL(ANSI-99)语法以查询内存中的数据。 Redis不支持任何查询语言,只支持客户端缓存API。
9 持续查询 Ignite提供对客户端和服务器端持续查询的支持,用户可以设置服务器端的过滤器来减少和降低传输到客户端的事件数量。 Redis提供客户端基于键的事件通知的支持,但是他不提供服务器端的过滤器,因此造成了在客户端和服务器端中更新通知网络流量的显著增加。
10 数据库集成 Ignite可以自动集成外部的数据库-RDBMS, NoSQL,和HDFS。 Redis无法与外部数据库集成。

 

I.11  ELK

ELK由Elasticsearch、Logstash和Kibana三部分组件组成;

Elasticsearch是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

Logstash是一个完全开源的工具,它可以对你的日志进行收集、分析,并将其存储供以后使用

kibana 是一个开源和免费的工具,它可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助您汇总、分析和搜索重要数据日志。

 

I.12  Kong(Nginx)

Kong是一款基于Nginx_Lua模块写的高可用,易扩展由Mashape公司开源的API Gateway项目。由于Kong是基于Nginx的,所以可以水平扩展多个Kong服务器,通过前置的负载均衡配置把请求均匀地分发到各个Server,来应对大批量的网络请求。

Kong主要有三个组件:

Kong Server :基于nginx的服务器,用来接收API请求。

Apache Cassandra/PostgreSQL :用来存储操作数据。

Kong dashboard:官方推荐UI管理工具,当然,也可以使用 restfull 方式 管理admin api。

Kong采用插件机制进行功能定制,插件集(可以是0或n个)在API请求响应循环的生命周期中被执行。插件使用Lua编写,目前已有几个基础功能:HTTP基本认证、密钥认证、CORS( Cross-origin Resource Sharing,跨域资源共享)、TCP、UDP、文件日志、API请求限流、请求转发以及nginx监控。

 

I.13  Openstack

OpenStack  +  KVM

OpenStack:开源管理项目

OpenStack是一个旨在为公共及私有云的建设与管理提供软件的开源项目。它不是一个软件,而是由几个主要的组件组合起来完成一些具体的工作。OpenStack由以下五个相对独立的组件构成:

OpenStack Compute(Nova)是一套控制器,用于虚拟机计算或使用群组启动虚拟机实例;

OpenStack镜像服务(Glance)是一套虚拟机镜像查找及检索系统,实现虚拟机镜像管理;

OpenStack对象存储(Swift)是一套用于在大规模可扩展系统中通过内置冗余及容错机制,以对象为单位的存储系统,类似于Amazon S3;

OpenStack Keystone,用于用户身份服务与资源管理以及

OpenStack Horizon,基于Django的仪表板接口,是个图形化管理前端。

这个起初由美国国家航空航天局和Rackspace在2010年末合作研发的开源项目,旨在打造易于部署、功能丰富且易于扩展的云计算平台。OpenStack项目的首要任务是简化云的部署过程并为其带来良好的可扩展性,企图成为数据中心的操作系统,即云操作系统。

KVM:开放虚拟化技术

KVM(Kernel-based Virtual Machine)是一个开源的系统虚拟化模块,它需要硬件支持,如Intel VT技术或者AMD V技术,是基于硬件的完全虚拟化,完全内置于Linux。

2008年,红帽收购Qumranet获得了KVM技术,并将其作为虚拟化战略的一部分大力推广,在2011年发布RHEL6时支持KVM作为唯一的hypervisor。KVM主打的就是高性能、扩展性、高安全,以及低成本。

 

I.14  Disconf

专注于各种「分布式系统配置管理」的「通用组件」和「通用平台」, 提供统一的「配置管理服务」。

I.15  Apollo

Apollo是携程框架部门研发的配置管理平台,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。

服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。

 

I.16  gRPC

gRPC 是一个高性能、开源和通用的 RPC 框架,面向移动和 HTTP/2 设计。目前提供 C、Java 和 Go 语言版本,分别是:grpc, grpc-java, grpc-go. 其中 C 版本支持 C, C++, Node.js, Python, Ruby, Objective-C, PHP 和 C# 支持.

gRPC 基于 HTTP/2 标准设计,带来诸如双向流、流控、头部压缩、单 TCP 连接上的多复用请求等特。这些特性使得其在移动设备上表现更好,更省电和节省空间占用。

 

I.17  Canal 

canal是阿里巴巴旗下的一款开源项目,纯Java开发。基于数据库增量日志解析,提供增量数据订阅&消费,目前主要支持了MySQL(也支持mariaDB)。

基于日志增量订阅&消费支持的业务:

  • 数据库镜像
  • 数据库实时备份
  • 多级索引 (卖家和买家各自分库索引)
  • search build
  • 业务cache刷新
  • 价格变化等重要业务消息

 

 

I.18  Spark streaming

Spark Streaming 是Spark核心API的一个扩展,可以实现高吞吐量的、具备容错机制的实时流数据的处理。支持从多种数据源获取数据,包括Kafk、Flume、Twitter、ZeroMQ、Kinesis 以及TCP sockets,从数据源获取数据之后,可以使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。

 

I.19  SonarQube

Sonar是一个用于代码质量管理的开源平台,用于管理源代码的质量,可以从七个维度检测代码质量

通过插件形式,可以支持包括java,C#,C/C++,PL/SQL,Cobol,JavaScrip,Groovy等等二十几种编程语言的代码质量管理与检测

I.20  DataX

 DataX 是一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL、Oracle等)、HDFS、Hive、ODPS、HBase、FTP等各种异构数据源之间稳定高效的数据同步功能。

I.21  禅道管理 / Jira

禅道功能
1)产品管理:产品、需求、计划、发布、路线图等功能。
2)项目管理:项目、任务、团队、build、燃尽图等功能。
3)质量管理:bug、测试用例、测试任务、测试结果等功能。
4)文档管理:产品文档库、项目文档库、自定义文档库等功能。
5)事务管理:todo管理,我的任务、我的Bug、我的需求、我的项目等个人事务管理功能。
6)组织管理:部门、用户、分组、权限等功能。
7)统计功能:丰富的统计表。
8)搜索功能:通过搜索找到相应的数据。

JIRA功能
1)问题追踪和管理(问题类型包括New Feature-新功能、Bug-缺陷、Task-任务、 Improvement-改进 四种);
2)问题跟进情况的分析报告;
3)项目类别管理功能;
4)组件/模块负责人功能;
5)项目email地址功能;
6)无限制的工作流。

 

I.22  XXJOB

XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。

  • 简单:支持通过Web页面对任务进行CRUD操作,操作简单,一分钟上手;
  • 动态:支持动态修改任务状态、暂停/恢复任务,以及终止运行中任务,即时生效;
  • 调度中心HA(中心式):调度采用中心式设计,“调度中心”基于集群Quartz实现并支持集群部署,可保证调度中心HA;
  • 执行器HA(分布式):任务分布式执行,任务”执行器”支持集群部署,可保证任务执行HA;
  • 注册中心: 执行器会周期性自动注册任务, 调度中心将会自动发现注册的任务并触发执行。同时,也支持手动录入执行器地址;
  • 弹性扩容缩容:一旦有新执行器机器上线或者下线,下次调度时将会重新分配任务;
  • 路由策略:执行器集群部署时提供丰富的路由策略,包括:第一个、最后一个、轮询、随机、一致性HASH、最不经常使用、最近最久未使用、故障转移、忙碌转移等;
  • 故障转移:任务路由策略选择”故障转移”情况下,如果执行器集群中某一台机器故障,将会自动Failover切换到一台正常的执行器发送调度请求。
  • 失败处理策略;调度失败时的处理策略,策略包括:失败告警(默认)、失败重试;
  • 失败重试:调度中心调度失败且启用”失败重试”策略时,将会自动重试一次;执行器执行失败且回调失败重试状态时,也将会自动重试一次;
  • 阻塞处理策略:调度过于密集执行器来不及处理时的处理策略,策略包括:单机串行(默认)、丢弃后续调度、覆盖之前调度;
  • 分片广播任务:执行器集群部署时,任务路由策略选择”分片广播”情况下,一次任务调度将会广播触发集群中所有执行器执行一次任务,可根据分片参数开发分片任务;
  • 动态分片:分片广播任务以执行器为维度进行分片,支持动态扩容执行器集群从而动态增加分片数量,协同进行业务处理;在进行大数据量业务操作时可显著提升任务处理能力和速度。
  • 事件触发:除了”Cron方式”和”任务依赖方式”触发任务执行之外,支持基于事件的触发任务方式。调度中心提供触发任务单次执行的API服务,可根据业务事件灵活触发。
  • 任务进度监控:支持实时监控任务进度;
  • Rolling实时日志:支持在线查看调度结果,并且支持以Rolling方式实时查看执行器输出的完整的执行日志;
  • GLUE:提供Web IDE,支持在线开发任务逻辑代码,动态发布,实时编译生效,省略部署上线的过程。支持30个版本的历史版本回溯。
  • 脚本任务:支持以GLUE模式开发和运行脚本任务,包括Shell、Python、NodeJS等类型脚本;
  • 任务依赖:支持配置子任务依赖,当父任务执行结束且执行成功后将会主动触发一次子任务的执行, 多个子任务用逗号分隔;
  • 一致性:“调度中心”通过DB锁保证集群分布式调度的一致性, 一次任务调度只会触发一次执行;
  • 自定义任务参数:支持在线配置调度任务入参,即时生效;
  • 调度线程池:调度系统多线程触发调度运行,确保调度精确执行,不被堵塞;
  • 数据加密:调度中心和执行器之间的通讯进行数据加密,提升调度信息安全性;
  • 邮件报警:任务失败时支持邮件报警,支持配置多邮件地址群发报警邮件;
  • 推送maven中央仓库: 将会把最新稳定版推送到maven中央仓库, 方便用户接入和使用;
  • 运行报表:支持实时查看运行数据,如任务数量、调度次数、执行器数量等;以及调度报表,如调度日期分布图,调度成功分布图等;
  • 全异步:系统底层实现全部异步化,针对密集调度进行流量削峰,理论上支持任意时长任务的运行;

 

I.23 Salt stack

一种全新的基础设施管理方式,部署轻松,在几分钟内可运行起来,扩展性好,很容易管理上万台服务器,速度够快,服务器之间秒级通讯。

salt底层采用动态的连接总线, 使其可以用于编配, 远程执行, 配置管理等等.

I.24  Istio

Istio 作为用于微服务服务聚合层管理的新锐项目,是 Google、IBM、Lyft(海外共享出行公司、Uber劲敌) 首个共同联合开源的项目,提供了统一的连接,安全,管理和监控微服务的方案。

目前首个测试版是针对 Kubernetes 环境的,社区宣称在未来几个月内会为虚拟机和 Cloud Foundry 等其他环境增加支持。 Istio 将流量管理添加到微服务中,并为增值功能(如安全性,监控,路由,连接管理和策略)创造了基础。

  • HTTP、gRPC 和 TCP 网络流量的自动负载均衡;
  • 提供了丰富的路由规则,实现细粒度的网络流量行为控制;
  • 流量加密、服务间认证,以及强身份声明;
  • 全范围(Fleet-wide)的策略执行;
  • 深度遥测和报告。

 

 

 

 

架构篇

 

 

 

 

 

 

 

 

安全篇

 

 

基础篇

Salt Stack + OpenStack + KVM + Kubernetes + Istio

使用LayUI操作数据表格 - 井传红 - 博客园

mikel阅读(3545)

来源: 使用LayUI操作数据表格 – 井传红 – 博客园

接着 上一篇 继续完善我们的demo,这次我们加一个搜索按钮

搜索

 

在table标签的上方,加入这样一组html

 

<div class="demoTable">
    搜索商户:
    <div class="layui-inline">
        <input class="layui-input" name="keyword" id="demoReload" autocomplete="off">
    </div>
    <button class="layui-btn" data-type="reload">搜索</button>
</div>

 

在js加入初始化代码和定义加载方法

layui.use('table', function(){
    var table = layui.table;

    //方法级渲染
    table.render({
        elem: '#LAY_table_user'
        ,url: 'UVServlet'
        ,cols: [[
            {checkbox: true, fixed: true}
            ,{field:'id', title: 'ID', width:80, sort: true, fixed: true}
            ,{field:'aid', title: '商户', width:80, sort: true}
            ,{field:'uv', title: '访问量', width:80, sort: true,edit:true}
            ,{field:'date', title: '日期', width:180}
            ,{field:'datatype', title: '日期类型', width:100}

        ]]
        ,id: 'testReload'
        ,page: true
        ,height: 600
    });

    var $ = layui.$, active = {
        reload: function(){
            var demoReload = $('#demoReload');

            table.reload('testReload', {
                where: {
                    keyword: demoReload.val()
                }
            });
        }
    };
)};

 

绑定click点击事件

$('.demoTable .layui-btn').on('click', function(){
    var type = $(this).data('type');
    active[type] ? active[type].call(this) : '';
});

此时点击查询按钮,会将keyword这个关键字传到后端,接下来就是自己处理查询关键字业务了。

到目前为止,搜索也有了,分页也有了,对了,分页会自动传到后端page,limit2个值到后台,相当于(pageindex,pagesize)

预览下效果

看看请求的参数

 

从参数可以看出,数据表格默认是get请求,返回的数据结构是这样的 

给表格增加操作按钮

首先加入一组html,放到table标签下面,代码如下

<table class="layui-hide" id="LAY_table_user" lay-filter="useruv"></table>
<script type="text/html" id="barDemo">
    <a class="layui-btn layui-btn-primary layui-btn-mini" lay-event="detail">查看</a>
    <a class="layui-btn layui-btn-mini" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-danger layui-btn-mini" lay-event="del">删除</a>
</script>

然后在js中指定工具条

 //方法级渲染
        table.render({
            elem: '#LAY_table_user'
            ,url: 'UVServlet'
            ,cols: [[
                {checkbox: true, fixed: true}
                ,{field:'id', title: 'ID', width:80, sort: true, fixed: true}
                ,{field:'aid', title: '商户', width:80, sort: true}
                ,{field:'uv', title: '访问量', width:80, sort: true,edit:true}
                ,{field:'date', title: '日期', width:180}
                ,{field:'datatype', title: '日期类型', width:100}
                ,{field:'right', title: '操作', width:177,toolbar:"#barDemo"}
            ]]
            ,id: 'testReload'
            ,page: true
            ,height: 600
        });

界面效果如下

 

接下来需要给按钮绑定事件,来完成功能操作

在LayUI里面,一般采用table.on()来表示事件,例如这个

 

//监听表格复选框选择
        table.on('checkbox(useruv)', function(obj){
            console.log(obj)
        });

 

我勾选一个复选框,就打印一个日志

加入以下js代码,来绑定工具条事件

//监听工具条
  table.on('tool(demo)', function(obj){
    var data = obj.data;
    if(obj.event === 'detail'){
      layer.msg('ID:'+ data.id + ' 的查看操作');
    } else if(obj.event === 'del'){
      layer.confirm('真的删除行么', function(index){
        obj.del();
        layer.close(index);
      });
    } else if(obj.event === 'edit'){
      layer.alert('编辑行:<br>'+ JSON.stringify(data))
    }
  });

这时候,点击按钮就会有反应了。这里说明一下

接下来就是把数据传递到后端,直接将js改造如下

 

 View Code

 

 

预览效果

 

至此,数据表格的绑定、展示、分页、搜索、查看、编辑、删除、排序 功能都已经完成,是不是很简单?

此处粘贴出完整的页面代码

 

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>layui</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <link rel="stylesheet" href="../Assets/css/layui.css">


    <!-- 注意:如果你直接复制所有代码到本地,上述css路径需要改成你本地的 -->
</head>
<body>
<div style="margin-bottom: 5px;">

    <!-- 示例-970 -->
    <ins class="adsbygoogle" style="display:inline-block;width:700px;height:700px" data-ad-client="ca-pub-6111334333458862" data-ad-slot="3820120620"></ins>

</div>
<div class="demoTable">
    搜索商户:
    <div class="layui-inline">
        <input class="layui-input" name="keyword" id="demoReload" autocomplete="off">
    </div>
    <button class="layui-btn" data-type="reload">搜索</button>
</div>

<table class="layui-hide" id="LAY_table_user" lay-filter="useruv"></table>
<script type="text/html" id="barDemo">
    <a class="layui-btn layui-btn-primary layui-btn-mini" lay-event="detail">查看</a>
    <a class="layui-btn layui-btn-mini" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-danger layui-btn-mini" lay-event="del">删除</a>
</script>


<script src="../Assets/layui.js"></script>
<script>
    layui.use('table', function(){
        var table = layui.table;

        //方法级渲染
        table.render({
            elem: '#LAY_table_user'
            ,url: 'UVServlet'
            ,cols: [[
                {checkbox: true, fixed: true}
                ,{field:'id', title: 'ID', width:80, sort: true, fixed: true}
                ,{field:'aid', title: '商户', width:80, sort: true}
                ,{field:'uv', title: '访问量', width:80, sort: true,edit:true}
                ,{field:'date', title: '日期', width:180}
                ,{field:'datatype', title: '日期类型', width:100}
                ,{field:'right', title: '操作', width:177,toolbar:"#barDemo"}
            ]]
            ,id: 'testReload'
            ,page: true
            ,height: 600
        });

        var $ = layui.$, active = {
            reload: function(){
                var demoReload = $('#demoReload');

                table.reload('testReload', {
                    where: {
                        keyword: demoReload.val()
                    }
                });
            }
        };



        //监听表格复选框选择
        table.on('checkbox(useruv)', function(obj){
            console.log(obj)
        });
        //监听工具条
        table.on('tool(useruv)', function(obj){
            var data = obj.data;
            if(obj.event === 'detail'){
                layer.msg('ID:'+ data.id + ' 的查看操作');
            } else if(obj.event === 'del'){
                layer.confirm('真的删除行么', function(index){
                    console.log(data);
                    $.ajax({
                        url: "UVServlet",
                        type: "POST",
                        data:{"uvid":data.id,"memthodname":"deleteuv","aid":data.aid},
                        dataType: "json",
                        success: function(data){

                            if(data.state==1){
                                obj.del();
                                layer.close(index);
                                layer.msg("删除成功", {icon: 6});
                            }else{
                                layer.msg("删除失败", {icon: 5});
                            }
                        }

                    });
                });
            } else if(obj.event === 'edit'){

                layer.prompt({
                    formType: 2
                    ,title: '修改 ID 为 ['+ data.id +'] 的访问量'
                    ,value: data.uv
                }, function(value, index){
                    EidtUv(data,value,index,obj);
                   


                });



            }
        });

        $('.demoTable .layui-btn').on('click', function(){
            var type = $(this).data('type');
            active[type] ? active[type].call(this) : '';
        });

        function  EidtUv(data,value,index,obj) {
            $.ajax({
                url: "UVServlet",
                type: "POST",
                data:{"uvid":data.id,"memthodname":"edituv","aid":data.aid,"uv":value},
                dataType: "json",
                success: function(data){

                    if(data.state==1){

                        layer.close(index);
                        //同步更新表格和缓存对应的值
                        obj.update({
                            uv: value
                        });
                        layer.msg("修改成功", {icon: 6});
                    }else{
                        layer.msg("修改失败", {icon: 5});
                    }
                }

            });
        }


    });
</script>
</body>
</html>

 

应大家要求,将servlet代码贴出来,其中用到了json.jar

import com.weimob.models.Pagination;
import com.weimob.models.QueryResult;
import com.weimob.models.UvData;
import com.weimob.uv.dao.WeiMobUvDao;
import org.json.JSONArray;
import org.json.JSONObject;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@WebServlet(name="UVServlet",
        urlPatterns={"/WebApp/UVServlet"},
        loadOnStartup=0)
public class UVServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String memthodname = request.getParameter("memthodname");
        if(memthodname!=null){
            switch (memthodname){
                case "queryList":
                    break;
                case "deleteuv":
                    deleteUv(request,response);
                    break;
                case "edituv":
                    edituv(request,response);
                    break;
                default:
                    queryList(request, response);
            }

        }else {
            queryList(request, response);

        }


    }

    private void queryList(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {


        String str = request.getParameter("keyword");
        String pindex = request.getParameter("page");
        String limit = request.getParameter("limit");
        response.setStatus(200);
        int aid = 0;
        int pagesize=15;
        int index = 0;
        int total = 0;
        if (str != null && str.length() > 0) {
            aid = Integer.valueOf(str);

        }
        if (pindex != null) {
            index = Integer.parseInt(pindex);
            pagesize=Integer.parseInt(limit);
        }


        WeiMobUvDao dao = new WeiMobUvDao();

        StringBuffer sbtotal = new StringBuffer();
        sbtotal.append("SELECT count(1) as count FROM WpMulShopDataUv_1 ");
        if (aid > 0) {
            sbtotal.append(" where aid=");
            sbtotal.append(aid);

        }
        total = dao.GetCount(sbtotal.toString());
        if (total > 0) {

            StringBuffer sb = new StringBuffer();
            sb.append("SELECT Id,AId,Uv,DataType,Date FROM WpMulShopDataUv_1 ");
            if (aid > 0) {
                sb.append(" where aid=");
                sb.append(aid);

            }
            if (total > pagesize) {
                sb.append(" Limit ");
                int start = (index - 1) * pagesize;
                if (start < 0) {
                    start = 0;

                }
                sb.append(start);
                sb.append(",");
                sb.append(pagesize);
            }

            List<UvData> list = dao.QueryUv(sb.toString());

            QueryResult<UvData> result = new QueryResult<UvData>(total, list);

            String jsonstr= ConvertListToPageJson(list,total);
            System.out.println(jsonstr);
           request.setAttribute("result", jsonstr);
            response.getWriter().print(jsonstr);

        }else {
            QueryResult<UvData> result = new QueryResult<UvData>(total, null);
            JSONObject obj = new JSONObject(result);
            response.getWriter().print(obj);

        }





}

    private void deleteUv(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {


        String str = request.getParameter("aid");
        String uvid = request.getParameter("uvid");
        String limit = request.getParameter("limit");
        response.setStatus(200);
        int aid = 0;
        int uv_id=0;
        int index = 0;
        int total = 0;
        if (str != null && str.length() > 0) {
            aid = Integer.valueOf(str);

        }
        if (uvid != null) {
            uv_id = Integer.parseInt(uvid);
        }
       if(uv_id<=0){
           response.getWriter().print("参数无效");
       }

        WeiMobUvDao dao = new WeiMobUvDao();

        List list=new ArrayList<Integer>();
        list.add(uv_id);
        int res_count= dao.DeleteByIds(aid,list);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("state",res_count>0?true:false);
        jsonObject.put("code",0);
        jsonObject.put("msg","null");
        response.getWriter().print(jsonObject);







    }

    private void edituv(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {


        String str = request.getParameter("aid");
        String uvid = request.getParameter("uvid");
        String uvstr = request.getParameter("uv");
        response.setStatus(200);
        JSONObject jsonObject = new JSONObject();
        int aid = 0;
        int uv_id=0;
        int uv = 0;
        if (str != null && str.length() > 0) {
            aid = Integer.valueOf(str);

        }
        if (uvid != null) {
            uv_id = Integer.parseInt(uvid);
            uv= Integer.parseInt(uvstr);
        }
        if(uv_id<=0){
            response.setStatus(500);
            jsonObject.put("state",-1);
            jsonObject.put("msg","参数无效");
            response.getWriter().print(jsonObject);

        }
        if(uv<0){
            response.setStatus(500);
            jsonObject.put("state",-1);
            jsonObject.put("msg","参数无效");
            response.getWriter().print(jsonObject);
        }
        WeiMobUvDao dao = new WeiMobUvDao();

        List list=new ArrayList<Integer>();
        list.add(uv_id);
        UvData res= dao.getByIds(aid,uv_id);
        if(res==null){
            response.setStatus(500);
            jsonObject.put("state",-1);
            jsonObject.put("msg","参数无效,对象不存在");
            response.getWriter().print(jsonObject);
            return;
        }
         int res_count= dao.modifyEntity(res);

        jsonObject.put("state",res_count>0?true:false);
        jsonObject.put("code",0);
        jsonObject.put("msg","null");
        response.getWriter().print(jsonObject);
    }
    public  String ConvertListToPageJson(List<?> list, int countList) {
        // 新建一个json数组
        JSONArray jsonArray = new JSONArray();
        // 新建一个json对象
        JSONObject jsonObject = null;
        // 遍历泛型集合
        for (Object object : list) {
            jsonObject = new JSONObject(object);
            jsonArray.put(jsonObject);
        }
        // 转换数据格式
        String json = jsonArray.toString();
        // 拼接字符串
        StringBuffer sb = new StringBuffer();
        sb.append("{\"count\":");
        sb.append(countList);
        sb.append(",\"code\":");
        sb.append(0);
        sb.append(",\"msg\":");
        sb.append("null");
        sb.append(",\"data\":");
        sb.append(json);
        sb.append("}");
        String jsonString = sb.toString();
        return jsonString;
    }
}

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.example.demo.data.models;
import com.alibaba.fastjson.annotation.JSONField;
public class Uv {
    private int id;
    @JSONField(name="aid")
    public long getaId() {
        return aId;
    }
    public void setAId(long aId) {
        this.aId = aId;
    }
    private long aId;
    @JSONField(name="shopid")
    public long getShopId() {
        return shopId;
    }
    public void setShopId(long shopId) {
        this.shopId = shopId;
    }
    private long shopId;
    @JSONField(name="date")
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }
    private String date;
    @JSONField(name="uv")
    public int getUv() {
        return uv;
    }
    public void setUv(int uv) {
        this.uv = uv;
    }
    private int uv;
    @JSONField(name="id")
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @JSONField(name="datetype")
    public String getDataType() {
        return dataType;
    }
    public void setDataType(String dataType) {
        this.dataType = dataType;
    }
    private String dataType;
}

 

静态文件下载地址

不少同学不知道怎么绑定数据源,欢迎看我上一篇。表格数据源格式:http://www.layui.com/demo/table/user/?page=1&limit=30

总结:

LayUI为我们提供了强大丰富的类库组件,完善的文档,学习成本和开发成本相对低廉,具有快速,扁平化等优点。

关于数据表格的介绍就到这里。官方文档

Layui数据表格之获取表格中所有的数据 - CSDN博客

mikel阅读(1855)

来源: Layui数据表格之获取表格中所有的数据 – CSDN博客

  • 数据表格中的数据是通过直接赋值的方式。这里实际上思想是反过来的,将拿数据表格中的所有数据,转换为Layui数据表格拿原始数据去渲染数据表格
    1. 创建一个作用域合适的JS对象数组用来保存数据表格中的原始数据
    2. 将上一步创建的JS对象数组也就是原始数据赋给table.render()的data参数
    3. 获取表格中的所有数据其实直接获取第一步中创建的JS对象数组即可,参照下面的代码,获取表格中的所有数据就是获取tableContent中的数据。
// 存放数据表格中的数据的对象数组tableContent
var tableContent = new Array();

table.render({
    elem : '#viewTable',
    height : 325,
    even: true,
    text: {
        none: '您没有选中任何字段!'
    },
    // 拿对象数组tableContent中的数据作为原始数据渲染数据表格
    data : tableContent, 
    page : {
        layout: ['count', 'prev', 'page', 'next', 'limit', 'skip']
    },
    limit : 5,
    limits : [5, 10, 15, 20, 25],
    cellMinWidth: 80,
    cols:[[
        {type:'checkbox',fiexd : 'left'},
        {title : '序号',type:'numbers'},
        {field : 'column',title : '列',align:'center'},
        {field : 'alias',title : '别名',align:'center',edit : 'text'},
        {title : '操作',fiexd : 'right',align:'center', toolbar: '#viewBar'}
    ]],
    done : function(res, curr, count){
        // do something...
    }
});
  • 数据表格中的数据是通过异步请求的方式
    直接通过table.render()的done参数即可获得,该参数的值是一个数据渲染完的回调,无论是直接赋值还是异步请求数据,在渲染完之后都会触发该回调。注意:使用直接赋值方式给Laytable原始数据时,该方法获取到的是数据表格中当前页的数据,并不是表格中的所有数据,想获取表格中所有数据必须按照上面“数据表格中的数据是通过直接赋值的方式”的方法
table.render({ //其它参数在此省略
    done: function(res, curr, count){
    //如果是异步请求数据方式,res即为你接口返回的信息。
    //如果是直接赋值的方式,res即为:{data: [], count: 99} data为当前页数据、count为数据总长度
    console.log(res);
    //得到当前页码
    console.log(curr);
    //得到数据总量
    console.log(count);
    }
});

Layui给数据表格动态添加一行并跳转到添加行所在页 - CSDN博客

mikel阅读(3618)

来源: Layui给数据表格动态添加一行并跳转到添加行所在页 – CSDN博客

Layui数据表格动态添加一行问题

Layui是一个前端 UI 框架,该框架风格优雅,但由于发布时间较短,很多功能并没有提供实现。
笔者在使用Layui的数据表格的时候,需求是这样的:当点击添加按钮的时候,就在数据表格最后动态添加一行。上述功能官方并没有给出实现,需要自己手动解决。

解决思路及方案

  • 简单分析:根据需求——动态添加一行,首先想到的是利用JS/JQuery操作DOM对象实现在数据表格table中手动添加一个tr,但由于数据表格的每一行的每一个单元格都有其样式,因此,要想动态添加的一行与Layui数据表格渲染出来的每一行样式及功能一样,就必须给tr设置和渲染出来的每一行一样的样式,利用JQuery去完成这个添加这样一个tr工程量实在太大了,因此需要换一种方案。
  • 数据表格中的原始数据:查看Layui官方文档,采用方法渲染或者自动渲染的方式去生成数据表格时,数据表格中的数据是通过直接赋值的方式或者异步加载的方式获得原始的数据。
    • 直接赋值方式原始的数据其实就是一个对象数组,如[{}, {}, {}, {}, …]
    • 异步加载方式原始的数据发请求从后端取,然后后端返回给前端的一个json对象,这里要求后端返回给前端的json对象要符合Layui数据表格能渲染的格式,Layui数据表格默认支持的后端返回给前端的json对象格式如下,各个属性具体描叙参照官方文档:
 {
     code: 0, 
     msg: "", 
     count: 1000, 
     data: [] 
 } 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 数据表格的重载:数据表格重载可以将新拿到的原始数据重新渲染到数据表格中,Layui提供的是方法是table.reload(ID, options)
    • ID:table的id属性值
    • options:为Layui数据表格的基础参数,具体参照官方文档
  • 下面给出针对原始数据是通过直接赋值的方式、采用方法渲染的数据表格动态添加一行的思路及解决方法
    • 思路:通过上述讲解,动态添加一行其实可以转换为:
      1. 拿到数据表格中的所有数据后,也就是拿到一个对象数组,在那个对象数组最后添加一个与拿到的对象数组中对象相同、但其所有属性的属性值为空的一个空对象。(那数据表格中所有数据可参照我的另一篇Layui数据表格之获取表格中所有的数据
      2. 利用table.reload(ID, options)方法将添加了一个“空对象”的数组重新加载渲染到数据表格即可。
      3. 跳转到动态添加行所在页,只要设置table.reload(ID, options)optionspage基础参数即可,将page参数的curr属性值设置为动态添加行所在页页码(页码根据数据表格每页显示的记录数以及添加了一行后数据表格中总的记录数自己算)即可。2、3步代码如下():
//获取每页显示的记录数、当前记录总数,计算新添加的记录在第几页
var totalRecord = tableContent.length;
var pageSize = $(".layui-laypage-limits").find("select").val();
if($.type(pageSize) == "string"){
    pageSize = parseInt(pageSize);
}

var currPageNo = Math.ceil(totalRecord / pageSize);
console.log("每页显示的记录数:"+pageSize+"  类型:"+$.type(pageSize)+"   总的记录数:"+totalRecord+"  类型:"+$.type(totalRecord)
     +"   新增行所在页码:"+currPageNo+"  类型:"+$.type(currPageNo));

// 重载表格并跳转到最后修改或者添加数据的那一页
table.reload('viewTable', {
      page : {
         curr : currPageNo
      },
      data : tableContent
});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

最终效果图:
动态添加一行前(请将图片保存到本地查看大图)
这里写图片描述

动态添加一行后(请将图片保存到本地查看大图)
这里写图片描述

  • 下面给出针对原始数据是通过异步加载的方式、采用方法渲染的数据表格动态添加一行的思路及方法
    思路:异步加载方式实现动态添加一行思路和直接赋值方式类似,主要区别在于在数据表格中所有数据的来源不同,直接赋值方式数据来源自页面上自定义的一个js变量,异步加载方式数据来源自后台查询数据库传到前台。当从数据库查出来记录以后,在封装为table支持的数据对象时,添加一条空的记录,然后传回前端渲染即可实现。

【table】--分享封装的table各种数据操作,欢迎指正 - Fly社区

mikel阅读(1191)

以前easyUI用习惯了 换成layUI 的确好看了很多,但是table现目前还没有datagrid用起来方便快捷,于是封装了关于table的处理类。欢迎大家指正,我及时修改。包含:1、获取选中行 getSelect()2、获取所有行 AllRows

来源: 【table】–分享封装的table各种数据操作,欢迎指正 – Fly社区

以前easyUI用习惯了 换成layUI 的确好看了很多,但是table现目前还没有datagrid用起来方便快捷,于是封装了关于table的处理类。欢迎大家指正,我及时修改。
包含:
1、获取选中行 getSelect()
2、获取所有行 AllRows()
3、通过静态数据渲染 load(data)
4、通过options重新渲染 reload()
5、获取载入参数供修改后渲染 getOptions()
6、获取table上下文 getTableContent()
7、通过字段类型和字段的值选中某些行 selected(filed,resourse)
8、通过索引获取数据 getByIndex(index)
9、通过索引选中一行 selectedByIndex(index)
10、通过索引取消选中的一行 unselectedByIndex(index)
11、选中所有 selectedAll()
12、取消选中所有 unselectedAll()
13、更新索引所在的行 updateRow(index,data)
14、在最前面插入一行 appendAfterRow(data)
15、在最后面插入一行 appendBeforeRow(data)
16、在索引后插入一行 insertRow(index)
17、通过索引删除一行 deleteRow(index)

这些是我常用到的情况,下面是封装的table

<script type="text/javascript" src="${pageContext.request.contextPath}/modules/plugins/jquery/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/modules/plugins/layui/layui.js"></script>
<link rel="stylesheet" href="${pageContext.request.contextPath}/modules/plugins/layui/css/layui.css">
<script type="text/javascript">

//列表类封装
function HYtablelist(tableoption){
	var _this = this;
	var options = tableoption;
	var table;
	var tableuse;
	var tableIns;
	this.romance = function(){
		tableuse =layui.use('table', function(){
				  table = layui.table;
				  tableIns = table.render(options);
			});
		}
	this.getSelect=function(){ //获取选中的行
		var check = [];
		var allData = _this.AllRows();
		$.each(allData, function(){
			if(this.LAY_CHECKED){
				check.push(this);
			}
		});
		return check;		
	}
	this.AllRows=function(){//获取所有行 返回数组对象
		return tableuse.table.cache[options.id];
	}
	this.load=function(data){//通过数组对象,重新刷新列表  会清空table的url避免刷新table导致修改的数据还原为url数据
		var tmpurl = options.url;
		options.url = null;
		options.data = data;
		table.render(options);	
	}
	this.reload=function(){ //重载
		tableIns.reload(options);
	}
	this.getOptions=function(){//获取载入参数
		return options;
	}
	this.getTableContent=function(){//获取table上下文
		return tableIns;
	}
	this.selected=function(filed,resourse){//选中某些行 filed判断字段 resourse需要选中行的数组对象
		if(filed&&resourse&&resourse.length>0){
			var allData = _this.AllRows();
			$.each(allData, function(){
				var datadefine = this;
				var _value = eval('(datadefine.'+filed+')');
				for(var _m = 0;_m<resourse.length;_m++){
					if(_value==resourse[_m]){
						datadefine.LAY_CHECKED=true;
					}
				}
			});
			_this.load(allData);	
		}
	}
	this.getByIndex=function(index){//通过索引获取数据
		if(index!=undefined&&index!='undefined'){
	    	var allData = _this.AllRows();
	    	
	    	for(var _m = 0;_m<allData.length;_m++){
				if(index==allData[_m].LAY_TABLE_INDEX){
					return allData[_m];
				}
			}
		}
	}
	this.selectedByIndex=function(index){//通过索引选中一行
		if(index!=undefined&&index!='undefined'){
	    	var allData = _this.AllRows();
	    	$.each(allData, function(p1, p2){
	    		if(this.LAY_TABLE_INDEX==index){
	    			this.LAY_CHECKED=true;
	    		}
			});
	    	_this.load(allData);
		}
	}
	this.unselectedByIndex=function(index){//通过索引取消选中一行
		if(index!=undefined&&index!='undefined'){
	    	var allData = _this.AllRows();
	    	$.each(allData, function(p1, p2){
	    		if(this.LAY_TABLE_INDEX==index){
	    			this.LAY_CHECKED=false;
	    		}
			});
	    	_this.load(allData);
		}
	}
	this.selectedAll=function(){//选中所有
    	var allData = _this.AllRows();
    	$.each(allData, function(p1, p2){
    		this.LAY_CHECKED=true;
		});
    	_this.load(allData);
	}
	this.unselectedAll=function(){//取消选中所有
    	var allData = _this.AllRows();
    	$.each(allData, function(p1, p2){
    		this.LAY_CHECKED=false;
		});
    	_this.load(allData);
	}
	this.updateRow=function(index,data){//更新索引所在的行
		if(index!=undefined&&index!='undefined'&&data){
			var allData = _this.AllRows();
			var loadData=[];
	    	$.each(allData, function(){
	    		if(this.LAY_TABLE_INDEX==index){
	    			loadData.push(data);
	    		}else{
	    			loadData.push(this);
	    		}
			});
	    	_this.load(loadData);
		}
	}
	this.appendAfterRow=function(data){//在最后面插入一行
		if(data){
			var allData = _this.AllRows();
			allData.push(data);
			_this.load(allData);
		}
		
	}
	this.appendBeforeRow=function(data){//在最前面插入一行
		if(data){
			var allData = _this.AllRows();
			var loadData=[];
			loadData.push(data);
			$.each(allData, function(){
				loadData.push(this);
			});
			_this.load(loadData);
		}
	}
	this.insertRow=function(index,data){//在索引后插入一行
		if(index!=undefined&&index!='undefined'&&data){
			var allData = _this.AllRows();
			var loadData=[];
			$.each(allData, function(){
				loadData.push(this);
				if(this.LAY_TABLE_INDEX==index){
					loadData.push(data);
				}
			});
			_this.load(loadData);
		}
	}
	this.deleteRow=function(index){//通过索引删除一行
		if(index!=undefined&&index!='undefined'){
			var allData = _this.AllRows();
			var loadData=[];
	    	$.each(allData, function(){
	    		if(this.LAY_TABLE_INDEX!=index){
	    			loadData.push(this);
	    		}
			});
	    	_this.load(loadData);
		}
	}
}



function clone(obj) {
	var o;
	if (typeof obj == "object") {
		if (obj === null) {
			o = null;
		} else {
			if (obj instanceof Array) {
				o = [];
				for (var i = 0, len = obj.length; i < len; i++) {
					o.push(clone(obj[i]));
				}
			} else {
				o = {};
				for ( var j in obj) {
					o[j] = clone(obj[j]);
				}
			}
		}
	} else {
		o = obj;
	}
	return o;
}
</script>

这下面是测试页面:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
	<div class="layui-btn-group hybtngroup">
	  <button class="layui-btn" onclick="testFun();">测试按扭</button>
	</div>
	<table class="layui-hide layuitable" id="user_datagrid"></table>
</div>
</body>

<script type="text/javascript">
var data = [{"updateBy":"4028803d4dbdd065014dbdd0ef0d000f","createTime":"2017-01-11 15:36:23","phone":"","updateTime":"2017-11-20 19:49:43","remarks":"","isDeleted":false,"password":"e10adc3949ba59abbe56e057f20f883e","createBy":"4028803d4dbdd065014dbdd0ef0d000f","version":18,"id":"4028806a598c71c801598c74d25f005b","createOrgCd":null,"organization":"太平洋公司","username":"zhangsan","rolename":"管理员1","OrgID":"4028806a598c71c801598c7418570058","email":"","updateOrgCd":null,"gender":"Male","locked":false,"fullName":"张三","deleteTime":null},{"updateBy":"4028803d4dbdd065014dbdd0ef0d000f","createTime":"2017-01-11 15:37:01","phone":"","updateTime":"2017-11-20 19:46:21","remarks":"","isDeleted":false,"password":"e10adc3949ba59abbe56e057f20f883e","createBy":"4028803d4dbdd065014dbdd0ef0d000f","version":4,"id":"4028806a598c71c801598c75675d005c","createOrgCd":null,"organization":"北冰洋公司","username":"badmin","rolename":"管理员2","OrgID":"4028806a598c71c801598c7418570058","email":"","updateOrgCd":null,"gender":"Male","locked":true,"fullName":"北冰洋公司管理员","deleteTime":null}];
var tableoption = {
			id:'user_datagrid',
	    	elem: '#user_datagrid'
		    ,cols: [[
		      {type:'checkbox'}
		      ,{field:'username',title: '账户名'}
		      ,{field:'fullName',title: '用户名'}
		      ,{field:'organization',title: '所属机构'}
		      ,{field:'locked',title: '是否锁定',templet: '#lockedHandle'}
		      ,{field:'rolename',title: '拥有角色'}
		    ]]
		    ,page: true
}



var hytable = new HYtablelist(tableoption);
hytable.romance();//渲染
hytable.load(data);//测试通过静态数据加载,也可以option中加url加载数据,也可以option中加入data加载数据。


//测试方法
function testFun(){
   	alert(JSON.stringify(hytable.getSelect()));//测试选中 包含索引号 是否选中字段 
//     	alert(JSON.stringify(hytable.AllRows()));//获取所有数据
    	
// 		alert(JSON.stringify(hytable.AllRows()));//获取所有数据
    	
//     	hytable.selected('username',['zhangsan','badmin']);//选中行name中值为数组的行
    	
// 		hytable.selectedByIndex(0);//索引选中
    	
//     	hytable.unselectedByIndex(0);//取消索引选中

//     	hytable.selectedAll();//选中所有

//     	hytable.unselectedAll();//取消选中所有


// 		alert(JSON.stringify(hytable.getByIndex(0)));//通过索引获取一行


// 		var data = hytable.getByIndex(1);
// 		data.fullName="测试更新";
//     	hytable.updateRow(data.LAY_TABLE_INDEX,data);//更新所在行


// 		var data = hytable.getByIndex(1);
// 		var newData = clone(data);
// 		newData.fullName="测试添加最后一行";
//     	hytable.appendAfterRow(newData);//最后面添加一行数据

// 		var data = hytable.getByIndex(1);
// 		var newData = clone(data);
// 		newData.fullName="测试添加第一行";
//     	hytable.appendBeforeRow(newData);//第一行添加一行数据


// 		var data = hytable.getByIndex(1);
// 		var newData = clone(data);
// 		newData.fullName="第一行后面插入一行";
//     	hytable.insertRow(0,newData);//索引后面添加一行


//     	hytable.deleteRow(1);//通过索引删除一行
    }
</script>
</html>

微信用户提现不能到账,显示NO_AUTH | 产品权限验证失败,请查看您当前是否具有该产品的权限(企业付款到零钱) - CSDN博客

mikel阅读(3038)

来源: 微信用户提现不能到账,显示NO_AUTH | 产品权限验证失败,请查看您当前是否具有该产品的权限(企业付款到零钱) – CSDN博客

企业付款到零钱

一、开通条件

需同时满足两个条件,才有开通该功能入口:
1、T+0 (T日结算至基本账户),结算商户需满足两个条件:

1、入驻满90天,

2、截止今日往回推30天连续不间断保持有交易。
2、其余结算周期的商户无限制,可立即前往【商户平台】->【产品中心】申请开通。
注:连续30天交易无金额限制,请保持正常交易。

今天做分销商城时,当微用户提现  显示NO_AUTH | 产品权限验证失败,请查看您当前是否具有该产品的权限。

出现这个问题是因为我们的微信商户平台没有开通“企业付款到用户”功能。

微信商户产品中心里并没有“企业付款到用户”这个功能,如下图,那怎么办呢?很简单,直接进入这个链接https://pay.weixin.qq.com/index.php/public/product/detail?pid=5

另外还遇到个问题,就是登陆微信商户平台时,需要安全插件才能登陆,试了几次,发觉只能用QQ浏览器才能登陆。

引用:http://blog.csdn.net/linchaoren66/article/details/76068233

二、开通了后,提现还是失败

看看商户帐户上余额是为:0

充钱后再试

请注意,是余额有钱,基本帐户上有转,要转到运营帐户中

三、转入运营帐号

ASP.NET MVC异步上传图片和富文本编辑器的使用详解 - Kencery - 博客园

mikel阅读(897)

来源: ASP.NET MVC异步上传图片和富文本编辑器的使用详解 – Kencery – 博客园

  前言:在我们做任何网站项目的时候都避免不了要使用到这两个技术,而且应用也是非常的广泛,所以我写了这篇博客,喜欢能帮到大家,也顺便给我自己坐一下笔记,方便我以后的使用,废话不多说了,先说图片上传吧,图片上传我使用的是异步上传,下来再说富文本编辑器的使用

1. 图片上传

  (1)第一步:准备工作

  因为我做的是异步上传图片,所以大家肯定知道啦,需要一些准备工作的,首先我们给我们的项目添加两个引用,第一个引用想必大家都知道的,第二个引用是实现异步上传图片的一个JS脚本,我们需要引入,如果没有的话可以去网上下载或者在我的项目里面也能找到,代码如下:

    <script src=”http://www.cnblogs.com/Scripts/JQuery-1.7.1.js”></script>

    @*实现异步上传图片的功能*@

    <script src=”http://www.cnblogs.com/Scripts/MyAjaxForm.js”></script>

  (2)第二步:设置上传图片的控件和HTML的主要代码,如下所示:

    

  注释:大家看到了Form表单里面的那几个属性了吗?enctype我们必须设置成后面的属性才允许我们上传图片,anction的请求地址就是我们在控制器中的操作方法,一会会说到,至于其它的代码想必大家都一定很清楚了。

  (3)第三步:发送异步请求,当我们准备完这些的时候我们就需要发送异步请求向后台传递参数了,代码截图如下:

    

  注释,在这段代码里面我们可以看到我定义了一个var imgFileName,这是干什么的呢?其实大家一看注释就知道了,因为我会从后台传递过来图片的路径,所以这个变量就是保存图片的路径的,当我们将图片路径保存到这个变量的时候,在下面我们可以看到它的调用方式,想必大家一看就清楚了

  (4)第四步:控制器里面的代码如下:这段代码也很简单吧,就是将图片保存到磁盘上面并且返回图片的路径就OK了。

     //异步上传图片

     public ActionResult FileUpload()

  {

      //保存上传的图片

      HttpPostedFileBase imgFile = Request.Files[0];

      //返回图片地址

      imgFile.SaveAs(Server.MapPath(“../photo/” + imgFile.FileName));

      return Content(“/photo/” + imgFile.FileName);

   }

  (5) 第五步:注意事项:

  注意当我们上传图片到磁盘的时候,不要在Views文件夹下面建立文件夹存放图片。

  (6)效果展示

    

2. 富文本编辑器的使用

  注释:这个我还是和前面图片上传一样,通过步骤一步一步的来说吧。如果哪里写的模糊不清大家可以给我提出来!

  (1)第一步:准备工作,首先我们从网上下载到我们所需要的富文本编辑器的JS代码等文件,

  我遇到很多人将下载下来的东西不完全的放到项目里面,导致有时候一些功能不能用,调试大半天才找到,我的建议就是,当我们使用别人的东西的时候,我们刚开始先将人家的东西全部放到里面,然后当我们项目完成的时候我们在慢慢的删掉那些没用的东西,反正这样我是很少遇到问题,不知道大家都是怎么解决的?将所有的富文本编辑器的东西放到我们的项目里面去,如图所示:

    

  然后我们在项目中引入我们所需要的富文本编辑器的JS代码来使用它,注意路径一定要正确,代码如下:

     @*引入富文本编辑器的使用*@

     <script src=”http://www.cnblogs.com/kindeditor-4.1.3/kindeditor.js”></script>

     <script src=”http://www.cnblogs.com/kindeditor-4.1.3/lang/zh_CN.js”></script>

    <script src=”http://www.cnblogs.com/kindeditor-4.1.3/plugins/code/prettify.js”></script>

  (2)第二步:HTML文本框的代码书写,这个也很简单的,我们直接使用TextBox文本框就行了,代码如下:

     <tr>

         <td>内容:</td>

         <td>

             <textarea id=”txtMainContent” name=”AddNewsContent” style=”width: 550px; height: 300px; visibility: hidden;” runat=”server”>

              </textarea>

          </td>

   </tr>

  (4)第三步:JS脚本的编写

    

  注释:里面我认为比较模糊的地方我都已经加了注释,如果大家认为哪里还不清楚的话,可以给我留言,我们共同研究。

  (5)第四步:如何获取富本框的值和修改富文本框的值,在上面的截图中虽然已经有了那两个方法,但是因为我们使用富文本编辑器就是为了能够读取富文本编辑器中的值添加到数据库或者将数据库中的值读取出来现世在富文本编辑器中,下面我就简单的介绍一下哈。

    //获取添加文本框内容

    function getEditorAddData() {

       return editorUpdate.html();     //使用上面定义的window.editorAdd的方法的HTML代码   韩迎龙注释

    }

   //给富文本框赋值

   function setEditorUpdateData(data) {

        editorUpdate.html(data);   //富文本框的使用方法:window.editorUpdate   韩迎龙注释

     }

  当我们使用的时候我们如何来使用呢? txtMainContent: getEditorAddData();只需要给异步参数传递这个方法即可实现得到文本框中值,详细的代码可以参考我的代码。

  (6)第五步:效果展示

  1)添加效果

    

  2)修改效果

    

  至此:图片上传和富文本编辑器的使用功能就完成了,如果大家有什么疑惑或者还有什么不懂的,可以到我们的博客园小组“青春代码”,网址是:http://home.cnblogs.com/group/heimaThree/,给我们留言,我们共同解决,也可以在下面留言,那样只有我一个人回信息了!希望大家能够支持我们的博客园小组,将博客圆小组打造成一个交流技术的天堂。

项目下载地址:http://download.csdn.net/detail/hanyinglong/4789850