Timor

Timor 查看完整档案

上海编辑  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑



               console.warn("Never give up!")

个人动态

Timor 发布了文章 · 10月21日

练习SQL之汇总机构下面的医生总数

背景:练习sql.机构表和医生表.汇总每个机构下面的医生总数.去除机构下为0的医生行,倒序展示.


sql语句
select DISTINCT b.InstitutionID,InstitutionName,COUNT(ClientID) ClientSum 
from b_Institution b
left join  b_Client c on c.InstitutionID = b.InstitutionID 
group by b.InstitutionID , InstitutionName
having COUNT(ClientID) != 0
order by ClientSum desc

记录一下每一句sql的意思:
(1): select DISTINCT b.InstitutionID,InstitutionName,COUNT(ClientID) ClientSum

  • 查询出来的结果列为三列.
  • 第一列为去重后的InstitutionID
  • 第二列为InstitutionName
  • 第三列为客户总数列名为ClientSum

(2):from b_Institution b

  • 查询主表为机构表 并取别名为b

(3):left join b_Client c on c.InstitutionID = b.InstitutionID

  • 左联医生表(取别名为c)里面的机构ID和机构表的机构ID相等的数据

(4):group by b.InstitutionID , InstitutionName

  • 对机构表的ID和Name进行分组(分组后就可以计算医生数量)

(5):having COUNT(ClientID) != 0

  • 去除医生数量为0的数据

(6):order by ClientSum desc

  • 对医生数量进行倒序排序

最后附上结果图:
image.png

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 10月16日

学习.net第一天,写个接口根据人员id获取数据库里的岗位列表

背景:复宏汉霖项目尝试自己写接口.根据人员id获取数据库里的岗位列表.找后端要了复宏汉霖的项目包.安装环境运行起来后开始写接口.

数据库: sqlserver
语言: c#
框架: .net-framework


第一步先添加控制器Controllers

(1):鼠标移到WebApiControllers文件夹下,右键选择添加控制器
image.png
(2):选择 Web API 2 控制器 -空 (每家公司用的可能不一样)
image.png
(3):定义你的控制器名字
image.png
image.png
(4):新建好的控制器默认打开的样子
image.png

第二步添加model实体类

(1):新增model实体类
image.png
(2):定义model名字
image.png

第三步新建services逻辑层

(1):新增services逻辑层
image.png
(2):定义services名字
image.png

第四步 在控制器里面定义好接口地址返回值

TestStaffController.cs代码内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebApi.Infrastructure.Filters;
using Business.Models;
using Business.Services;

namespace WebApi.Controllers
{
    /// <summary>
    /// 测试获取岗位列表
    /// </summary>
    [Token]
    [RoutePrefix("api/TestStaff")]
    public class TestStaffController : ApiController
    {
        /// <summary>
        /// 根据人员id获取岗位列表
        /// </summary>
        /// <param name="OwnerID"></param>
        /// <returns></returns>
        [HttpGet]
        [Route("GetTestStaffList/{OwnerID}")]
        
        public IList<staffItem> GetTestStaffList(string OwnerID)
        {
            var business = new TestStaff();
            return business.GetTestStaffList(OwnerID);
        }

    }
}

解释:

  • using : 引用 (和前端的import用法一样)
  • namespace : 文件夹所在位置
  • /// : 注释
  • [Token] :授权过滤器,里面是否包含token.验证信息等.授权.
  • [RoutePrefix("api/TestStaff")] : 接口前缀
  • [HttpGet] : 定义请求类型
  • [Route("GetTestStaffList/{OwnerID}")] : 请求地址(接口后缀)
  • IList<staffItem> :返回值类型list类型
  • GetTestStaffList :方法名
  • (string OwnerID) :传参类型及参数名
  • var business = new TestStaff() 把services对象实例化
  • business.GetTestStaffList(OwnerID) 调用services层的方法
第五步 在实体类model里面定义所需字段

TestStaff.cs代码内容:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Business.Models
{
    public class staffItem
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public staffItem()
        {
            TerritoryID = "";
            TerritoryCode = "";
            TerritoryName = "";
            TerritoryLevel= "";
            OwnerID = "";
            OwnerName = "";
            RepName = "";
        }
        /// <summary>
        /// 岗位id
        /// </summary>
        public string TerritoryID { get; set; }
        /// <summary>
        /// 岗位编码
        /// </summary>
        public string TerritoryCode { get; set; }
        /// <summary>
        /// 岗位名称
        /// </summary>
        public string TerritoryName { get; set; }
        /// <summary>
        /// 岗位等级
        /// </summary>
        public string TerritoryLevel { get; set; }
        /// <summary>
        /// 人员id
        /// </summary>
        public string OwnerID { get; set; }
        /// <summary>
        /// 人员姓名
        /// </summary>
        public string OwnerName { get; set; }
        /// <summary>
        /// 人员岗位名字
        /// </summary>
        public string RepName { get; set; }
    }
}

解释:

  • 构造函数与类名要保持一致
第六步 在逻辑层services里面处理逻辑

TestStaff.cs代码内容:

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Business.Models;
using CommonUtil;
using DatabaseLayer;
using Entity;

namespace Business.Services
{
    /// <summary>
    /// 测试获取岗位列表
    /// </summary>
    public class TestStaff
    {
        /// <summary>
        /// 根据人员id获取岗位列表
        /// </summary>
        /// <param name="OwnerID"></param>
        /// <returns></returns>
        public IList<staffItem> GetTestStaffList(string OwnerID)
        {
            var strsql = $"select * from b_app_territory where OwnerID={OwnerID}";
            DataTable dt = Query.ExecuteSQLQuery(strsql, SystemEnvironment.Instance.DefaultDataSource);
            return dt.AsEnumerable().Select(x => new staffItem
            {
                TerritoryID = x["TerritoryID"].ToString(),
                TerritoryCode = x["TerritoryCode"].ToString(),
                TerritoryName = x["TerritoryName"].ToString(),
                TerritoryLevel = x["TerritoryLevel"].ToString(),
                OwnerID = x["OwnerID"].ToString(),
                OwnerName = x["OwnerName"].ToString(),
                RepName = x["RepName"].ToString(),
            }).ToList();
        }
    }
}

解释:

  • strsql : sql语句
  • Query.ExecuteSQLQuery把sql查出来的结果转换成DataTable对象
  • dt.AsEnumerable().Select( x => ...).ToList() : 转换成和你定义的model里面的返回值一样的参数
第七步 运用postman调用试试
  • 利用数据库,先查出来一条人员的id.然后把id当作参数直接贴到接口后面.
  • 这里遇到了一个小问题.不想去查token.然后在项目里找到了一个超级密码.在文件夹WebApi下面的TokenAttribute文件里面.
  • WebApi\Infrastructure\Filters\TokenAttribute.cs

image.png

image.png

  • 最后在调用的时候把这个超级密码当做token贴上去就好了.

image.png

总结:

因为之前写过一丢丢java.所以现在前端接触.net也不是那么的难受.
但是还是很多地方很懵逼.请教了很多同事.慢慢的写出来了这个接口.
后端对于面向对象需要很清晰的理解.无处不对象.好好加油!

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月25日

Angluar5+ionic3实践(五)

背景:复宏汉霖项目CR做完后.来整理下需要优化的地方和给其他页面发送消息知识点.

优化项目启动时间

先记一下:最开始运行的时候所需时间:
image.png
删完99%的console.log和解决掉所有tslint的报错后项目跑起来的时间:
image.png

整整少了14.78s.真得不要小看console.log...

发送消息

实际开发场景: 当前登录人的信息是保存在主页面的.最开始登陆进去的时候存入主页面的,然后其他页面用到的人员信息是主页面传出来的.在其中一个模块修改了人员岗位后.主页面没有重新获取人员信息.则会导致其他模块的信息有误.
解决思路: 在其中一个模块修改了人员岗位后,给主页面传一个消息.告诉它需要重新获取登录人的信息.
(其他任意页面都能通过Events获取到这个消息)

// 修改人员岗位的模块代码内容:

import {Events} from 'ionic-angular';

export class SetupPage {

 constructor(public ev: Events){}
 
 // 岗位切换
 chooseJob = ()=>{
     if (this.territoryList.length <= 1) {
        return;
     }
    let modal = this.modalCtrl.create("ChooseJobPage", { jobList:this.territoryList ,territoryID},{ cssClass: 'inset-modal'});
    modal.onDidDismiss(data => {
     if (data.action == 'save') {
    // 在岗位切换成功后告诉主页面要重新获取人员信息
    // 利用this.ev.publish('selectedStff')发消息.
        this.staffService.SelectedTerritoryToken(json).then((info) => {this.ev.publish('selectedStff')})}
    });
    modal.present();
 }
}
// 主页面代码内容:

import {Events} from 'ionic-angular';

export class MyApp {

 constructor(public ev: Events){
      // 接收到消息后,去调取获取人员信息接口
      ev.subscribe("selectedStff", () =>{
         this.getStaffInfo();
     })
 }
 
 // 获取当前用户信息
 getStaffInfo = () => this.staffService.GetStaffInfo().then((info) => {
    // 重新赋值人员信息
    this.currentStaff = info;
 });
}
查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月21日

Android +ios ----- APP打包超详细步骤解析

背景:复宏汉霖APP的CR结束了.今天来打包.记录一下打包流程.Android+ios的打包流程
(项目所用技术+自身环境说明:ionic+ Angular + win10系统 + cordova)

第一步:下载需要的安装包

需要下载的安装包:
(1):android studio 最新版
(2):java JDK1.8
(3):gradle 最新版(官网下载)
(4):node 10.16.3
(5):全局安装ionic(不用指定版本,安装最新的就好了) npm install -g ionic
(6):全局安装cordova 8.0.0 ,命令: npm install -g cordova@8.0.0

附上我的前三个的安装包.也可以自行去网上下载.百度网盘(永久有效):
链接: https://pan.baidu.com/s/1z9ha0jyLw1ABRWEZui0cUQ 提取码: xrnn

第二步:安装,配置环境

gradle + java + android studio 配置环境变量.
自行在网上找环境变量配置教程.......一个个截图太多了..就不截图了...反正就配置下环境变量.有的在系统变量配置有的在用户变量配置.

  • 配置结束后.在桌面(或者任意文件夹下)运行cmd窗口.执行命令查看环境变量配置是否成功.以下六个命令运行成功后(参考我以下截图),版本对上了.就可以进行打包了.(我的框架是ionic的,所以查看了ionic的版本,如果用的不是ionic就不用查看)

(1):gradle -v
image.png
(2):java -version
image.png
(3):adb(没有截全,后面还有一些...)
image.png
(4):cordova -v
image.png
(5):node -v
image.png
(6):ionic -v
image.png

第三步:进行打包
  • 找到你需要打包的项目文件夹.
  • 配置好你需要的环境

一: 打包之前需要更改的配置(4-5个文件)(非常重要!!,这个配置代表你打包的环境!!):**
(我们公司的大平台会给出证书,签名密码,ios key,android key,app key.密钥等.其他公司的不太清楚你们放在哪里...自行寻找哈...)
(1):config.xml需要改的id.打安卓的就把-改为下划线_.打ios的改为-.(一定要改,不然会报错!!!)以及要改的key值(涉及到打包环境).
image.png
image.png
(2):package.json要改的内容:
image.png
(3):fetch.json要改的内容
image.png
(4):app.interceptor.ts里面的地址
image.png
(5): 由于这个项目涉及到其他部门.所以还有其他部门的接口地址(没有的自行忽略)global.variable.ts里面的地址:
image.png

二: 配置好了之后就可以打开命令窗口(最好用管理员身份运行,可以避免N多问题...).

  • 安卓打包:
  • 1:执行:ionic cordova platform rm android(保证平台环境干净)
  • 2:执行:ionic cordova platform add android(添加安卓打包平台)
  • 3:执行:ionic cordova build android(debug调试环境) 或者ionic cordova build android --prod --release(正式发版环境).以下用正式做练习:

(1):命令开始执行的时候
image.png
(2):出现这个乱码的时候就代表要成功了!!!!
image.png
(3):命令执行成功的时候
image.png
(4):出现以下输出语句的时候就代表打包成功了.

BUILD SUCCESSFUL in 49s
46 actionable tasks: 46 executed
Built the following apk(s):
C:\timor\xiaosk_projects\platforms\android\app\build\outputs\apk\release\app-release-unsigned.apk

三: 签名.(签名文件和密码自行找公司相关人员咨询...这里默认签名文件和密码都已拥有...(我们公司的就在自身项目里.没有的找项目负责人要.))
(1): 找到com.xiaosk.henlius_uat.jks签名文件.复制放在刚刚打包成功的路径C:\timor\xiaosk_projects\platforms\android\app\build\outputs\apk\release里面.如下图所示:
image.png
(2):在当前目录下打开命令窗口.运行命令jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore com.xiaosk.henlius_uat.jks app-release-unsigned.apk my-alias (就是这么长!!!!!)
其中com.xiaosk.henlius_uat.jks为你本次签名文件的文件名,自行跟着签名文件改名字!!.
(3):输入签名密码(自行准备的,每家公司都不一样,我们公司的在项目的README.md文件里面),回车运行.成功的结果如下图:
image.png
image.png

  • 打包成功后会把apk后缀的文件.发送到QQ就可以直接安装先看看安卓打包后的APP了.
  • ios打包:
  • 必备苹果电脑.可以先在window电脑上打包.后面在苹果电脑上改配置.(这样就可以安卓的包打完直接打ios的包.方便一些.)

1:先保证平台的环境干净.运行命令ionic cordova platform rm android
image.png
2:创建ios平台的环境.运行命令ionic cordova platform add ios
image.png
3:开始打包,运行命令ionic cordova build ios --prod --release
同事说一般打ios的都会成功.只要报的不是红色的err就代表成功了...
我的打出来最后报的是这个:
image.png
但是后面更改配置发版没问题...
1:把打出来的文件.解压到苹果电脑上面.
image.png
2:打开workspace后缀名的文件.
image.png
3:选择项目为ios
image.png
4:上传证书(我们公司在大平台上可以下载对应的证书)
image.png
把下载好的证书上传到这个位置
image.png
5:更改info下面的语言为中文
image.png
6:更改build settings里面的标识
image.png
7:点击左上角produce里面的archive,进行打包
image.png
image.png
8:打完包后生成app,选择为企业版
image.png
image.png
9:选择一下XSK
image.png
10:如果提示如下.就把Frameworks里面红色的JavaScriptcore.framework包删掉.重新点击左上角produce里面的archive,进行打包.
image.png
11:打包成功.可以导出了.
image.png
选择导出的位置
image.png
打开导出的文件夹,这个ipa就是打包后的项目了
image.png

  • 把配置好的ipa文件,借助数据线和iTools还有应用兔手机软件.到苹果手机上测试.手机上需要安装应用兔软件.配合使用.
  • 附上iTools安装链接(百度云盘,永久有效):

链接: https://pan.baidu.com/s/1WWVpWeAtEMHG3ODQFnZHQA 提取码: uz9i

常见报错整理:

(1):第一种报错信息:
image.png
解决方法: 把id的-uat改为下划线_uat
image.png
(2):第二种报错信息:
image.png
解决方法:
重新运行add安卓包.运行命令为ionic cordova platform add android
(3):第三种报错信息:
image.png
解决方法:
真的是在网上搜索了各种方法.各种命令运行.后面还是没有用...最有用的一篇文章是参考这个文章 但是有个坑是:

1、在node_modules.bin 下的 *.cmd 文件中,有如下 "%_prog%"
2、修改 "%_prog%" 为 %_prog%,即去掉双引号
  • 我是怎么搜node_modules.bin里面的"%_prog%"内容都没有搜到.最后我想到.*.cmd 文件可能代表的是所有后缀为.cmd的文件....
  • 然后随意点开了一个...发现里面真的有"%_prog%"....后面没办法...一个个文件点开去把"%_prog%"内容给替换成了%_prog%.
  • 实在是没有找到合适的解决方法了...改了又二十个文件左右....哎...不过好在.我成功解决了......这个问题应该是npm install的问题.但是我重新安装了好多次都没办法.

(4):第四种报错信息:内存泄漏(会经常遇到....)
image.png
解决方法:

  • 1、删除项目中 node_modules文件夹
  • 2、执行 npm cache clear --force
  • 3、npm install 安装依赖
  • 4: 管理员身份全局安装 increase-memory-limit
  • 5: npm install -g increase-memory-limit
  • 6: 进入工程目录,执行:increase-memory-limit

(5):第五种报错信息:python报错
image.png
解决方法:
第一步:安装windows-build-tools : npm install --global --production windows-build-tools
第二步:安装node-gyp : npm install --global node-gyp

附带的知识点:

1: 关于nrm
安装nrm : npm i -g nrm
nrm ls查看指向源image.png
nrm use taobao把npm的指向源设置为taobao
image.png
再次运行nrm ls查看指向源,更改成功.(避免出现npm安装指向不一致的各种问题...)
image.png
2: 优化APK
zipalign -v 4 app-release-unsigned.apk app-release-signed.apk

总结:

内心感受: 今天打包从上午十点出头一直打到晚上九点半.真的非常惨...惨绝人寰...没有经验的小白就是各种踩坑.还好我一直对自己说今天打不好就不下班了.同事也过来帮我看报错..各种出主意.. 最后成功了..一把心酸泪...
遇到问题解决的方法:其实很多问题都是因为运行者的身份权限不够,或者有缓存.版本不正确,步骤不正确导致的.静下心来在网上找找答案.或者开口问问同事.最后还是不行就清空回收站,电脑杀个毒,清理下垃圾.然后关机重启.把运行的进程关掉一大部分.重新再来一次.要相信自己,一定能行.绝不轻言放弃!
打包最重要的三个因素:缓存,内存,网速

  • 写这篇文章.一:是给自己留下记忆.二:是分享出来,避免再有人和我一样踩坑.每个项目可能多少有点不同.但是大致思路是一样的.遇到的错误也是大同小异的.有问题的小伙伴可以好好参考.不要忽略了细节哦.
  • 有问题可以下方留言沟通.基本上每天都会上线.觉得有用的小伙伴记得点个赞~
查看原文

赞 1 收藏 1 评论 0

Timor 发布了文章 · 9月18日

Angluar5+ionic3实践(四)

背景 : 复宏汉霖项目的CR做完了.用时五天.超出预计时间十天.这五天每天都在加班.终于功夫不负有心人.我现在可以开始独自开发Angluar+ionic项目了.之前都是用的React+AntDesign.现在算是扩展了新框架.收获满满.这里最后记录下.这两天开发过程中遇到的问题.学到的知识.

学到的知识:一定会遇到的model弹层
  • 比如这样的需求: 进项目的时候选择岗位,在我的页面又要有切换岗位的弹框.这时候就会遇到两个点.一个是model弹层.还有一个就是抽组件.

image.png

  • 首先来看下抽组件
  • 顾名思义就是把多个用处的同一块东西抽成公共组件.这样在任何页面就可以公用.这也是项目必备技能.
  • 一般都把抽出来的组件放到src/components里面.
  • 来看下我的这个model弹层的公共组件怎么写的:
  1. 目录结构:

image.png

  1. 代码内容:
choose-job.module.ts 内容:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { ChooseJobPage } from './choose-job';
@NgModule({
     declarations: [ChooseJobPage],
     imports: [
        IonicPageModule.forChild(ChooseJobPage),
     ],
})
export class ChooseJobPageModule {}
choose-job.ts 内容:

import { Component, Input } from '@angular/core';
import { NavParams,IonicPage, ViewController } from "ionic-angular";

@IonicPage()
@Component({
 selector: 'choose-job',
 templateUrl: 'choose-job.html',
})
export class ChooseJobPage {
 @Input() jobList: any; // 岗位列表
 checkd = {
    TerritoryID:''
 } // 选中的岗位
 
 // 初始化
 constructor(
     public navParams: NavParams,
     public viewCtrl: ViewController,) {
     this.jobList = this.navParams.get('jobList');
     this.checkd.TerritoryID = this.navParams.get('territoryID') || '';
     }
 // 选中的值
 radioSelected =(v)=>{
    this.checkd = v
 }
 
 // 点击确认
 determine = ()=>{
    this.viewCtrl.dismiss({selectedItem: this.checkd, action: 'save'});
 }
}
choose-job.html 内容:

<ion-header class="modal-header">
     <ion-navbar color="sky" padding-left padding-right>
         <ion-title text-center="">选择岗位</ion-title>
     </ion-navbar>
</ion-header>
<ion-content style="height: 300px;">
     <ion-item-group class="list">
         <ion-item *ngFor="let item of jobList;let i = index" >
             <ion-label>
                 <ion-row>
                 <h3>{{item.TerritoryName}}</h3>
                 <span class="tr">({{item.isPartTime ? "代岗" : "主岗" }})</span>
                 </ion-row>
             </ion-label>
             <ion-radio (click)="radioSelected(item)" [checked]="checkd.TerritoryID === item.TerritoryID" ></ion-radio>
         </ion-item>
         <ion-row justify-content-center align-items-center *ngIf="jobList?.length === 0">
             <img data-original="assets/icon/no_data.png" alt="" width="70" style="margin-top: 150px"/>
         </ion-row>
     </ion-item-group>
     <button ion-button class="save" (click)="determine()">
        确定
     </button>
</ion-content>
choose-job.scss 内容:

approve-list {
     .list{
         max-height: 200px;
         overflow-x: hidden;
     }
     .tr{
         color: #32a3e7;
         font-size: 12px;
         margin-left: 5px;
     }
     .save{
         width: 87%;
         background: #32a3e7;
         margin: 20px;
         position: absolute;
         bottom: 0;
     }
}
  1. 内容解析:
  • 这个公共组件需要的参数只有两个.一个jobList还有一个territoryID.(刚进页面的时候是没有默认值的,在我的里面切换岗位的时候,是需要默认为自己登陆的岗位)
  • 需要注意的地方:

(1): 调用组件是需要在组件页的类上方定义@IonicPage()的.不然获取不到的.
(2): 不加@IonicPage()的组件是被用作标签使用.不需要choose-job.module.ts.在components的公共components.module.ts里面导出就好了.

  • 现在组件抽好了.怎么调用出来呢.
  • 来看下我的页面调用的代码
`我的` html内容:

 <button ion-item (click)="chooseJob()">
     <ion-icon item-start>
         <img data-original="assets/icon/tr.png" width="30">
     </ion-icon>
     <ion-row>
         <h3>岗位切换</h3>
         <span class="color-blue" style="font-size: 15px;margin-left: 5px;">{{territoryName || ''}}</span>
     </ion-row>
 </button>

`我的` ts内容:

 // 岗位切换
 chooseJob = ()=>{
    // 判断只有一个岗位不触发弹层
     if (this.territoryList.length <= 1) {
        return;
     }
     // 获取岗位id
     let territoryID = localStorage.getItem("territoryID");
     // 获取model弹层 
     // `ChooseJobPage`就是我从`choose-job.module.ts`里面导出的名字.
     // jobList 和 territoryID 就是我给组件的传参
     // cssClass是组件位于页面样式的一个公共css.
     let modal = this.modalCtrl.create("ChooseJobPage", { jobList:this.territoryList ,territoryID},{
     cssClass: 'inset-modal'
     });
     // 点击确定的时候的返回值
     modal.onDidDismiss(data => {
         if (data.action == 'save') {
         // 把新切换的岗位赋值到localStorage里面(用于设置页面展示当前岗位所用)
         this.territoryName = this.territoryList.filter(item => item.TerritoryID === data.selectedItem.TerritoryID)[0].TerritoryName
         }
     });
     modal.present(); 
 }
 `我的` module内容:
 
import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { SetupPage } from './setup';
import {SharedModule} from "../../../app/shared.module";
import { ChooseJobPageModule } from "../../../components/choose-job/choose-job.module"; // 引入组件的module

@NgModule({
 declarations: [],
 imports: [
     IonicPageModule.forChild(SetupPage),
     SharedModule,
     ChooseJobPageModule, // 这里写了ts页面就能取到组件页`ChooseJobPage`了
 ],
})

export class SetupPageModule {}

以上就是model弹层的抽组件和调用,传参的代码了.有想法的可以互相讨论哈.

常用的生命周期
constructor(){} // 初始化
ionViewWillEnter(){
    // 获取页面列表等操作
} //初始化后调用
遇到的需要注意的问题

(1):*ngif*ngfor不可以在同一个标签上使用.可以用div包起来.父上写if子上写for
(2): 给数组列表增加一组数据用array.unshift({key:'',value:''})
(3): 处理日期的方法:
比如date为你要处理的日期

  • 第一种: 利用moment直接处理 : moment(date).format('YYYYMM').如果是当前年月的话得到的就是202009.如果需要加-就是moment(date).format('YYYY-MM').得到的是2020-09.moment的用法还有很多.感兴趣的可以去官网看看.或者直接Ctrl点进去看源码.最快最方便.
  • 第二种: 项目是老项目.没有引入moment也不想装.那就用字符串去处理.参考一下我写的方法
 // 处理年月传参
 getMonth = ()=>{
    // this.date为你把需要处理的日期.用Date转一下.getDate接收.
     let getDate = new Date(this.date)
     // 获取年
     let year = String(getDate.getFullYear());
     // 处理月份(先转为字符串再判断长度不足两位补0)
     let month = String(getDate.getMonth()+1).toString().length > 1 ? String(getDate.getMonth()+1) : '0'+String(getDate.getMonth()+1);
     this.date = year + month;
     // 这时候你页面再调用this.date就是你处理好的日期了.例如得到当前年月就是202009
 }
总结:

从看不懂Angluar+ionic的项目到写完整个复宏汉霖项目的CR.
学到了Angluar+ionic的基本使用.常用的生命周期.echarts处理报表.遇到的问题等等.
让我快速入门了这门框架.相信在不久的将来.Angluar+ionic的项目写的越多就会越顺手.遇到的问题越多就会进步越快.加油.

  • 这个项目的CR一共写了五篇文章.附上之前写的复宏汉霖四篇的链接

复宏汉霖第一篇认识项目(Angular5 + Ionic3 + TS)
Angular5+ionic3实践(一)
Angluar5+ionic3实践(二)
echarts处理报表---Angluar5+ionic3实践(三)

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月15日

Angluar5+ionic3实践(三)

背景: 这几天在做复宏汉霖的报表.用到了echarts.git到了一个新功能.三张报表.静态页面画了两天.今天来整理下学到的知识点.

认识下echarts

echarts官网地址
image.png
里面有许许多多的图例.目前我需要用到的是饼图Pie柱状图Bar.

实践饼图Pie
  • 先看下实现效果:

image.png
由上图可看出实际覆盖率用的是饼图.这里用到的就是echartsPie.

  • 实现逻辑:
html 页面代码:

 <ion-row justify-content-between >
     <div no-margin class="font-12 echarts-title" style='border-bottom: none !important;'>
         <span style='margin:0px 0px 10px 0px;color: #14a3d9;display: block;'>实际覆盖客户数</span>
         <div style="position: relative; margin-left: 10%;"> 
         <img data-original="assets/icon/actual.png" alt="" style="width: 80px;margin-left: 40%;"/>
         <p class='number'>10000人</p>
         </div>
     </div>
     <div no-margin class="font-12 echarts-title" style='border-bottom: none !important;'>
         <span style='margin:0px 0px 0px -40px;color: #d98a14;display: block;'>实际覆盖率</span>
         <div #chart1 style='width:100px;height:100px;' ></div>
     </div>
 </ion-row>
ts 页面代码:

export class VisitReportPageNew {
     @ViewChild("chart1") chart1: ElementRef; 
      ionViewWillEnter() {
         this.setChart1();
      }
      setChart1() {
         const ec = echarts as any;
         const container = this.chart1.nativeElement;
         const chart = ec.init(container);
         chart.setOption({
             title: {
                 show: true,
                 x: "center",
                 y: "center",
                 text: 85 + "%",
                 itemGap: 0, // 主副标题间距
                 textStyle: {
                     fontSize: "13",
                     color: "#d98a14",
                 },
                 subtext: "",
                 subtextStyle: {
                     fontSize: "13",
                     color: "#5B697A",
                     fontWeight: "600",
                 },
             },
             color: ["#d98a14", "#f1dbbb"],
             series: {
                 name: "",
                 type: "pie",
                 radius: ["72%", "82%"],
                 avoidLabelOverlap: true,
                 hoverAnimation: false,
                 labelLine: {
                     normal: {
                        show: false,
                     },
                 },
                 data: [
                     { value: 85, name: "" },
                     { value: 15, name: "" },
                 ],
             },
         });
         }
}
  • 还有css和module.ts页面的代码关联不大我就不放了.
  • 这里主要记住的一些基本参数.
  1. series.type : 定义图形形状
  2. series.radius : 图形大小,第一个参数是外圈,第二个参数是内圈
  3. color : 图形颜色,第一个参数是分布圈主要颜色,第二个参数是剩余内容颜色
  4. title.text : 图形中间的文字
  5. title.textStyle : 图形中间的文字的样式
  6. series.data : 占比值
实践饼图稍复杂版Pie
  • 先看下实现效果:

image.png
上图中的拜访次数分布by拜访目的的图就是稍复杂版的饼图.
来看下代码:

html 页面代码:

 <ion-card>
     <div class="visit-number">
         <div no-margin class="font-12 echarts-title" style='border-bottom: none !important;'>
             <p style="font-size: 12px;color: #999999;">拜访次数分布by拜访目的</p>
         <div #chart2 style='width:300px;height:300px;margin-top: 20px;'></div>
         </div>
     </div>
  </ion-card>
ts 页面代码:

export class VisitReportPageNew {
     @ViewChild("chart2") chart2: ElementRef;
      ionViewWillEnter() {
         this.setChart2();
      }
      setChart2() {
         const ec = echarts as any;
         const container = this.chart2.nativeElement;
         const chart = ec.init(container);
         chart.setOption({
             tooltip: {
                 name: "占比",
                 trigger: "item",
                 backgroundColor: "rgba(255,255,255,0.8)",
                 textStyle: {
                    color: "black",
                 },
                 formatter: function (params) {
                     return (params.marker + params.name + " : " +params.value + "人" + "(" +params.percent +"次)");
                 },
                 position: [10, 10],
            },
             color: ["#4584DC","#14A3D9","#5FBFE4","#2FC691","#F3B73B","#F0D7A2","#DC6025",],
             legend: {
                 show: "true",
                 orient: "horizontal",
                 x: "center",
                 bottom: "6%",
                 itemWidth: 15,
                 itemHeight: 15,
                 itemGap: 15,
                 data: ["拜访目的1", "拜访目的2", "拜访目的3", "拜访目的4", "拜访目的5"],
                 textStyle: {
                     color: "#535E6C",
                     opacity: 0.7,
                 },
             },
         // 圆心中间说明
             graphic: {
                 elements: [{
                     type: "text",
                     style: {
                         text: `占比`,
                         fill: "#98A6B7",
                         fontSize: 14,
                         textAlign: "center",
                         fontWeight: 800,
                     },
                     left: "center",
                     top: "32%",
                 }],
             },
             series: [{
                 name: "",
                 type: "pie",
                 radius: ["30%", "40%"],
                 center: ["50%", "34%"],
                 avoidLabelOverlap: true,
                 label: {
                     normal: {
                         formatter: `{d}次`,
                         borderWidth: 0,
                         borderRadius: 4,
                         fontWeight: "bold",
                         padding: [-20, -35, 0, -25], // 外标说明位置
                     rich: {
                         a: {
                            // 外标底部
                             color: "#606C7B",
                             fontSize: 14, // 字大小
                         },
                     hr: {
                         width: "100%",
                         borderWidth: 0.5,
                         height: 0,
                     },
                     b: {
                         // 外标顶部
                         fontSize: 14, // 字大小
                         color: "#606C7B",
                     },
                    },
                    },
                 },
                 labelLine: {
                     show: true,
                     length: 25,
                     length2: 35,
                 },
                 data: [
                 {
                     value: "1",
                     name: "拜访目的1",
                 },
                 {
                     value: "2",
                     name: "拜访目的2",
                 },
                 {
                     value: "3",
                     name: "拜访目的3",
                 },
                 {
                     value: "4",
                     name: "拜访目的4",
                 },
                 {
                     value: "5",
                     name: "拜访目的5",
                 },
                 ],
             }],
       });
   }
}
  • 那个代码有点点多.... 可能以后学会了熟练了代码就变得精简了...
  • 整理一下这个稍复杂的饼图学到的属性值:
  1. series.label.normal.formatter : 饼图块延伸出来的文字说明.
  2. series.center : 图形在所在区域的位置.
实践柱状图Bar
  • 先看下实现效果:

image.png
上图中的机构分布by等级是用柱状图展示的

HTML 页面代码:

 <ion-row>
     <div no-margin class="font-12 echarts-title" style='border-bottom: none !important;'>
        <span style='color: #999999;'>机构分布by等级</span>
     <div #chart1 style='width:300px;min-height:200px;' ></div>
     </div>
 </ion-row>
ts 页面代码:

export class VisitReportPageNew {
     @ViewChild("chart1") chart1: ElementRef; 
      ionViewWillEnter() {
         this.setChart1();
      }
      setChart1() {
         const ec = echarts as any;
         const container = this.chart1.nativeElement;
         const chart = ec.init(container);
         chart.setOption({
             xAxis:[{
                 type: "category",
                 data: ['A级', 'B级', 'C级', 'D级',],
                 axisTick:{
                    alignWithLabel:true,
                 },
                boundaryGap:['20%', '20%']
             }],
             yAxis:[{
                show: false,
             }],
             series:[{
                 name:'',
                 barWidth: 10,
                 data: [60, 76, 55, 19],
                 type: 'bar',
                 color: '#32a3e7',
                 label: {
                     show: true,
                     position: 'top',
                     formatter: "{c}"+"家",
                     color: '#000000',
                 }
             }]
         });
    }
  • 柱状图稍微简单一些.这里用到了隐藏Y轴,修改X轴刻度.增加状图文字.
  • 学到的属性值介绍:
  1. yAxis.show : 是否展示Y轴
  2. series.barWidth : 柱状图的粗度调整
  3. xAxis.axisTick.alignWithLabel : 刻度展示
总结一下学到的知识点:
  • 认识并依葫芦画瓢的使用了echarts.
  • 很多问题和需求都是有人遇到过的,如果看官方API没有找到,就直接搜狗搜索.可能还找的快一些.
  • 官网点开一个图形会直接进入实例页面.可以实时修改查看.完全可以先在实例页面.实现想要的结果后,再复制刚刚实现的代码进到项目中.(因为维护的老项目每次启动和热部署都很慢...所以在网上实时修改好了再用对我来说很有用)
  • 有时候项目热部署后没有生效不代表你写错了.重新运行下项目再看看.
  • 不赶时间的话,方法和变量还是要好好命名!养成好的习惯!不要学我...我会改的...
查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月8日

Angluar5+ionic3实践(二)

背景: 昨天看了一天的别人的代码.整理了一下接口所需的二十多个参数.今天联调.把用到的一些方法记录一下.

先看下两个常用的方法:ArrayStringStringArray.
  • Array.join(',')代表把Array拆成一组字符串,用,分割
  • String.split(',')代表把String组成一个数组,用,分割.

例如 :
image.png

<ion-input>属性值placeholder的展示内容
  • 在输入字段为空时显示.业务需求需要区分编辑中和详情页.所以需要处理下.原来用React的写法是在等号后面直接写{ }判断.
  • Angluar这里不行.需要把placeholder[ ]包起来.然后在后面的" "里面写判断条件.

例如 :

<ion-item>
 <ion-label class="font-15">银行联行号</ion-label>
     <ion-input 
        [(ngModel)]="clientSpeakerRequest.bankBranchNumber"
        [placeholder]="editable ? '请填写' : '' " 
        [readonly]="!editable" 
        type="number"
     >
     </ion-input>
 </ion-item>
在HTML页面中可以直接修改model的值
  • 需求是在点击编辑按钮的时候把按钮状态给取反
  • 我看之前别人的写法是写个点击方法,然后在model的点击方法里面再去写this.isEdit = !this.isEdit.
  • 我以为是必须要那样写.. 结果今天发现可以这样.直接修改.操作少的时候,这样写特别方便.
<ion-buttons end>
     <button 
         *ngIf="!isEdit && type === 'talker'" 
         ion-button 
         icon-only 
         (click)="this.isEdit = !this.isEdit;"
     >编辑</button>
 </ion-buttons>

监听请求结果的subscribe方法

  • 在请求成功的时候获取接口返回值.
  • 在请求失败的时候打印错误提示语.
this.http.get(`api/clientSpeaker/GetStaffRepInstitutionSimplePageData?access_token=${token}&staffId=${this.TerritoryID}`, httpOptions)
 .subscribe(
 (res: any) => {
    console.log('res',res)
 },
 (err) => {
    this.alertService.presentAlert("提示", `${err.message}`);
 }
 );
总结:

今天大部分时间都在联调接口.后端要求的传参格式都不一样.所以页面存取值一直在调试.这里记一下今天用到的一些方法.加油!

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月7日

Angular5+ionic3实践(一)

背景:这几天在做复宏汉霖项目.有个讲者功能这个礼拜就要交付了.没有太多的时间去学习.只能直接看代码上手了.记录一下学到的基础知识点.

[(ngModel)],( ),{{ }}有什么作用?

打开HTML页面的代码.入眼的就是各个[],(),{{}}.这些都是什么意思呢?

  • {{ }}代表的是属性值.
    例如:<span>{{clientSpeakerRequest?.speakerLevelValue}}</span>的意思就是取clientSpeakerRequest里面的speakerLevelValue作为值展示到这个<span>标签中.
  • ( )代表的是方法.
    例如:<ion-item (click)="getSpeakerLevel()"></ion-item>的意思就是点击<ion-item>标签的时候触发getSpeakerLevel()方法.
  • [(ngModel)]代表的是双向绑定.
    例如: <ion-input placeholder="请填写" [(ngModel)]="material.learnDuties"></ion-input>的意思就是把输入的input的值绑定到material.learnDuties中.

*ngIf,*ngFor有什么作用?

  • *ngIf相当于if条件判断.
    例如:<span *ngIf="clientSpeakerRequest?.academicTitleValue!==''">{{clientSpeakerRequest?.academicTitleValue}}</span>的意思是当clientSpeakerRequest里面的academicTitleValue值不等于''的时候再展示clientSpeakerRequest.academicTitleValue
  • *ngFor相当于for循环.
    例如:<div *ngFor="let item of meetingModelList;let j=index"></div> 的意思是循环meetingModelList,每一次遍历的值用item接收.j就是数组的下标.

@Input()@Output()有什么作用?

  • @Input()是子组件向父组件传值.
    例如:
    子页面 : @Input() editable: boolean;
    父页面 : <ion-icon *ngIf="editable"></ion-icon>
  • @Output()是父组件向子组件传值.
    例如:
    子页面 : @[Output] refreshData = new [EventEmitter](); this.refreshData.emit('refresh');
    父页面 :

    <campaign-content-edit 
         [pageData]="pageData
         [canEditCampaign]="canEditCampaign"
         (refreshData)="getCampaignModel($event)">
    </campaign-content-edit> 

    父页面的getCampaignModel方法就能取到'refresh'

@ViewChild有什么作用?

  • 获取组件页面的方法,也可以用来传参.

例如:
A页面:

ts :

@Component({
  selector: 'page-talker-add',
  templateUrl: 'talker-add.html',
})
export class TalkerAddPage {
  @ViewChild('meetingContent') meetingContent: any;//计划内容页面
  constructor(public navCtrl: NavController,
              public navParams: NavParams){}

  ionViewDidLoad() {}
  
  savePlan = () => {
    let model = this.meetingContent.getModel()
    console.log('model',model)
    }
    
 HTML : 
   
<ion-header>
  <ion-navbar color="sky">
    <ion-title>新增讲者</ion-title>
  </ion-navbar>
</ion-header>

<ion-content class="gray-bg">
  <ng-container>
    <talker-content #meetingContent></talker-content>
  </ng-container>
  <div style="width: 100%;height: 100px;"></div>
</ion-content>
<ion-footer>
  <ion-toolbar color="stable" padding>
    <button ion-button no-margin block (click)="savePlan()" color="sky">
      提交
    </button>
  </ion-toolbar>
</ion-footer>

A页面在触发提交的click方法savePlan()的时候.会调用获取组件页面传递过来的meetingModelList的值.就是组件HTML页面上的列表的值.

组件页面:

ts :

@Component({
  selector: 'talker-content',
  templateUrl: 'talker-content.html'
})
export class TalkerContentComponent {
  meetingModelList: any={
    periodical:[],
    qualification:[]
  }
  getModel = () => this.meetingModelList;
  }
  
 HTML : 

<ion-item-group no-padding>
<div *ngFor="let material of meetingModelList?.periodical;let j=index">
    <ion-item-divider color="stable" class="ion-item-divide" tappable>
      <span class="font-15">期刊信息({{j+1}})</span>
      <span item-end class="color-red" (click)="periodicalDelete(j)">&nbsp;&nbsp;<ion-icon name="trash-outline"></ion-icon>&nbsp;&nbsp;</span>
    </ion-item-divider>
    <!--  期刊级别  -->
    <ion-item tappable (click)="getJournaData(material)">
      <ion-label class="font-15">期刊级别</ion-label>
      <span item-end class="font-15 text-normal" align-items-center justify-content-end>
        <span [ngClass]="{'color-Hui':!editable}">{{material?.journalLevel}}</span>&nbsp;
        <span class="color-Hui" *ngIf="material?.journalLevel==''">请选择</span>&nbsp;
        <ion-icon name="ios-arrow-forward" class="font-18 color-gray" *ngIf="editable"></ion-icon>
      </span>
    </ion-item>
    <!--  期刊名称  -->
    <ion-item>
      <ion-label class="font-15">期刊名称</ion-label>
      <ion-input item-end class="font-14" text-end placeholder="请填写" type="text" [disabled]="!editable" [(ngModel)]="material.journalTitle"></ion-input>
    </ion-item>
    <!--  文章名称  -->
    <ion-item>
      <ion-label class="font-15">文章名称</ion-label>
      <ion-input item-end class="font-14" text-end placeholder="请填写" type="text" [disabled]="!editable" [(ngModel)]="material.journalDuties"></ion-input>
    </ion-item>
  </div>
</ion-item-group>
总结:

今天看了一天的Angular和ionic的代码.请教了同事很多次.慢慢的理解了这些用法.脑海里大致了解了基础写法.相信多写段时间.我一定能学会的.加油.

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月4日

复宏汉霖(Angular5 + Ionic3 + TS)

背景: 新接手复宏汉霖项目,记一下需要前期熟悉的东西,方便后期维护.首次开始Angular+ionic项目.给自己打气!加油!文章有点长,需要耐心看~~


先放张图片,安抚一下眼睛.
image.png

打包地址的位置:

两个都要替换对应的地址再进行打包.ios打包需要苹果电脑.

  • image.png
  • image.png

先熟悉一个简单的个人设置页面:

页面实际图如下:

  • image.png
看一下页面文件夹的目录结构:

image.png
image.png

setup.html : 页面
setup.scss : css样式
setup.ts : 处理逻辑
setup.module.ts : model层
staff.service.ts : services层

我发现这个项目它们是把service都放在一起的.我之前写的其他项目是每个文件夹下有自己的service....

来研究一下个人设置这个页面是怎么画出来的:
先研究下页面实现HTML:

来看下人家的代码是怎么写的:

  • 第一部分发现了<ion-header>`<ion-title>`的标签.从名字看理解就是写title的标签.果然找到了系统设置四个字.就是页面的头部位置.
  • 第二部分,整体用<ion-content>标签包起来,就是页面的内容
  1. 继续往下看,发现了<ion-icon>`<h2>标签用来展示头像和姓名.用<div>`稍微调整了下布局.
  2. 继续往下看,发现了<ion-list>标签包裹的内容.对照页面看.果然有修改手势密码,关于,客服热线等一个个item.这样的item用list标签是最合适的.没毛病.里面就是用一个个div把头像和文字写到一排.然后设置了一个点击方法.
  3. 继续往下看,在<ion-list>结束标签后面.写了一个div标签.用来绘制页面底部的注销账号的位置.div里面包个button,加个点击事件就好了.
  • 这样一条条理出来整个页面的布局就清晰可见了.
setup.html内容:

<ion-header>
  <ion-navbar color="sky">
    <ion-title>系统设置</ion-title>
  </ion-navbar>
</ion-header>

<ion-content class="gray-bg">
  <div class="setting-top" padding-top>
    <ion-item tappable (tap)="toProfile()">
      <ion-icon item-start>
        <img data-original="assets/icon/avatar_duel_126.png" width="50">
      </ion-icon>
      <h2>{{currentStaff?.UserName}}</h2>
      <p></p>
    </ion-item>
  </div>
  <ion-list>
    <button ion-item (click)="changeGestureCode()">
      <ion-icon item-start>
        <img data-original="assets/icon/pattern_yellow_58.png" width="30">
      </ion-icon>
      <h3>修改手势密码</h3>
    </button>
    <button ion-item (click)="aboutPage()">
      <ion-icon item-start>
        <img data-original="assets/icon/info_blue_58.png" width="30">
      </ion-icon>
      <h3>关于</h3>
    </button>
    <button ion-item (click)="ToCallNumber()">
      <ion-icon item-start>
        <img data-original="assets/icon/phone_green_58.png" width="30">
      </ion-icon>
      <h3>客服热线 <span class="color-blue">400-XXX-0800</span></h3>
    </button>
  </ion-list>

  <div padding>
    <button ion-button block color="danger" (click)="logout()">注销账号</button>
  </div>
</ion-content>
研究完HTML页面后,下一步就要看,点击事件的背后做了什么事情.

先来看下逻辑页面的处理:

  • 顶部引入了页面所需的装饰器.组件.service等内容.
  • @IonicPage()空装饰器
  • @Component({ selector: 'page-setup',templateUrl: 'setup.html',}) 公共组件和该组件的 HTML 模板文件.
  1. templateUrl:'setup.html'这个名字很熟悉就不多解释了.就是我刚刚分析的HTML页面的文件名.
  2. selector: 'page-setup'是一个公共组件,可以共用组件内的样式,逻辑,等所有内容.
  • 下面看下SetupPage类里面有哪些东西.
  1. 定义页面所需的变量 : currentStaff: any;看名字理解为当前的人员信息,类型为any
  2. 定义页面所需的变量 : selectedStaff: any;看名字理解为选择的人员信息,类型为any
  3. constructor页面初始化的时候注入依赖,依赖里面有一些下面要用到的方法.
  4. toProfile,changePassword等方法的注释介绍的很清楚了.是用来做什么的.这里说一下this.navCtrl.push的意思是页面跳转.里面的两个参数:一是跳转的页面路由二是带过去的参数.this.navCtrl就是刚刚注入的NavController依赖,this.navCtrl.push.push就是NavController里面的方法.
  5. 修改手势密码的方法里面用到了一个方法叫做this.modalCtrl.create是用来在页面上层浮现一个model.传参也是两个参数,一个页面路由一个传递的参数.
  6. ionViewDidEnter方法是在constructor之后执行的.相当于在页面初始化之后去获取一些人员信息用来展示.
setup.ts 内容:

import {Component} from '@angular/core';
import {IonicPage, ModalController, NavController, NavParams, Platform} from 'ionic-angular';
import {AlertService} from "../../../providers/util/alert.service";
import {StaffService} from "../../../services/staff.service";
import {JPush} from '@jiguang-ionic/jpush';

@IonicPage()
@Component({
  selector: 'page-setup',
  templateUrl: 'setup.html',
})
export class SetupPage {
  currentStaff: any;
  selectedStaff: any;

  constructor(public navCtrl: NavController,
              public navParams: NavParams,
              public staffService: StaffService,
              public jPush: JPush,
              public platform: Platform,
              public alertService: AlertService,
              public modalCtrl: ModalController) {

  }


  //查看个人信息
  toProfile() {
    this.navCtrl.push('StaffProfilePage', {});
  }

  //修改密码
  changePassword() {
    this.navCtrl.push('ChangePasswordPage', {});
  }

  //关于页面
  aboutPage() {
    this.navCtrl.push('AboutPage', {});
  }
  /***
   * 拨打客服热线
   */
  ToCallNumber = () => {
    document.location.href = "tel:400-xxx-0800"
  };

  /**
   * 修改手势密码
   */
  changeGestureCode = () => {
    let modal = this.modalCtrl.create("GesturePage", {type: "modify", cssClass: 'gesture-modal'});
    modal.present();
  };
  /**
   * 获取当前用户信息
   */
  getStaffInfo = () => this.staffService.GetStaffInfo().then((info) => {
    this.currentStaff = info;
  });


  /**
   * 注销
   */
  logout = () => this.alertService.presentAlertWithCallback("请确认", "是否确认注销").then((status) => {
    if (status) {
      this.navCtrl.setRoot("LoginPage").then(() => {
        this.selectedStaff = null;
        localStorage.clear();
        if (this.platform.is('cordova')) {
          this.jPush.deleteAlias({sequence: 1}); // 注销极光别名
        }
      });
      // 403 后跳到登录
      // this.staffService.GetStaffMobileIndexModel().then(() => this.navCtrl.setRoot("LoginPage"))
    }
  });

  ionViewDidEnter() {
    this.getStaffInfo()
  }

}
setup.scss 内容:

page-setup {
  .scroll-content {
    -webkit-overflow-scrolling: auto;
  }
  .setting-top {
    background: url("../assets/imgs/settings_bg.png") center no-repeat;
    height: 20vh;
    width: 100%;
    background-size: 100% 100%;
    .item-md, .item-ios {
      background-color: transparent;
      ion-icon[item-start] + .item-inner {
        margin-left: 12px;
      }
      &.item-block {
        .item-inner {
          border-bottom: none;
          color: #fff;
          p {
            color: #fff;
          }
        }
      }
    }
  }
  .header-ios .toolbar-background-ios {
    border-color: $color-nav;
  }
}
现在用的方法介绍完了来介绍一下页面的model
  • @NgModule 是Angular的的根模块,称为元数据.这个里面有逻辑页面需要用到的模块,管道等内容.
  • imports里面的IonicPageModule.forChild(SetupPage)就是用来连接你的逻辑(SetupPage)页面.可以往回看.你的setup.ts的类名就是叫SetupPage.
setup.module.ts 内容:

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import { SetupPage } from './setup';
import {SharedModule} from "../../../app/shared.module";

@NgModule({
  declarations: [],
  imports: [
    IonicPageModule.forChild(SetupPage),
    SharedModule
  ],
})
export class SetupPageModule {}
现在看一下最后的service层:
  • service层就是用来连接后端接口的返回值的.
  • setup.ts逻辑文件的上方可以看到有import {StaffService} from "../../../services/staff.service";的导入.这样导入后就可以用 this.staffService.GetStaffInfo().then((info) => {...});去获取后端返回的当前用户信息.

staff.service.ts 部分方法内容:

import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {Observable} from "rxjs";

@Injectable()
export class StaffService {
  constructor(public http: HttpClient) {
  }

 /**
   * 获取当前用户的信息
   * @constructor
   */
  GetStaffInfo = () => new Promise((resolve, reject) =>
    this.http.get('api/Staff/GetCurrentStaffInfo')
      .subscribe(res => {
        resolve(res);
      }, (err) => {
        //reject(err);
      })
  );
  
  ....
  
}

总结

今天认识了一下复宏汉霖我的页面的实现.从html-scss-model-serivce.页面到样式到逻辑到接口返回值简单的了解了一下.大致知道了页面是怎么实现的.后期还需要经常光顾官网深刻了解:
Angular官网
Ionic3官网

查看原文

赞 0 收藏 0 评论 0

Timor 发布了文章 · 9月1日

天堂管理系统第二篇---人员列表

背景: 这几天不是特别忙.于是写了一个人员列表的模块.用mock数据实现了简单的增删改查功能.代码也已经上传到GitHub,感兴趣的同学可自行下载.下载地址

先放几张效果图:

image.png

image.png

image.png

image.png

image.png

image.png

简单介绍一下这个页面:

人员列表模块:
    上半部分是一个搜索区域.可以搜索人员名字,职位描述,飞升时间,月薪,目前状态.
    下半部分是展示的人员列表主体.拥有新增,修改,删除,刷新等功能.翻页也是OK的.
    列表中间有一个提示语的地方.可以查看选中的人员的月薪总额.
    保留了框架自带的缩放页面.去除列表单列的功能.
查看原文

赞 1 收藏 0 评论 0

认证与成就

  • 获得 23 次点赞
  • 获得 2 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 2 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2019-08-22
个人主页被 906 人浏览