工程训练:生意专家:03 注册的实现
目录
- 0. 项目目录
- 1. 任务
- 1.1 任务介绍
- 1.2 任务要求
- 2. ==思路==
- 3. 使用Module管理代码
- 4 创建passportModule
- 4.1 创建模块passport,同时添加passport路由
- 4.2 创建注册页面和登录页面
- 4.3 删去signup文件夹下signup.routing.ts和signup.module.ts这两个文件
- 4.4 在passport的路由文件夹添加路由信息
- 4.5 在app的路由文件夹添加passport路由信息
- 4.6 模块声明
- 5 使用share模块
- 5.1 导入CommonModule,FormsModule,IonicModule等第三方模块
- 5.2 修改exports属性,导出其他模块都需要的模块。
- 5.3 在PassportModule中导入SharedModule
- 5.4 在WelcomeModule中导入SharedModule
- 6 跳转到注册页面
- 6.1 在欢迎页中==点击注册==按钮进入注册页
- 6.2 在欢迎页中点击==跳过==按钮进入注册页
- 6.2.1 在WelcomePage组件类中添加onSkip方法。
- 6.2.2 为“跳过”按钮添加click事件绑定
- 7 实现注册界面
- 7.1 样式scss
- 7.2 布局
- ① 放4张图片表示4个步骤。
- 7.3 使用Slides,通过索引判断注册到那一步了,同时亮不同的标
- 7.3.1 通过索引来判断注册进行到哪一步
- 7.3.2 通过代码切换4个slide
- 7.3.2 把退后\前进实现
- 8. 设置用户信息
0. 项目目录
- 欢迎页的实现
- 程序第一次运行实现
- 注册的实现
- 登陆的实现
- 首页的实现
- 店铺设置的实现
- 商品分类浏览的实现
- 编辑商品分类的实现
- 新增商品的实现
- 商品管理的实现
2020.12.17 重写 文章没写全,有空补全。
测试都过了
主要添加验证码 可显示 为检测用
1. 任务
1.1 任务介绍
实现用户的注册功能。
1.2 任务要求
用户场景: 用户注册之后才能有权限使用软件的功能。用户在欢迎页点击“注册”按钮进入注册页,或者在登录页点击“注册”按钮进入注册页。
输出/后置条件: 注册成功后,由于没有搭建服务器端,因此注册的数据保存在浏览器的本地存储中。页面跳转到首页。
**在欢迎页中点击“跳转”按钮的处理:**通过Angular的事件绑定,点击“跳过”按钮时页面跳转到首页。
2. 思路
1. 把经常用的功能放在share模块中,创建share模块
2. 路由上打通:
---- ①passport与注册signup路由打通;
---- ②根路由与passport打通
3. 模块声明好,让相互之间知道:
---- ① passport与注册signup模块打通;
---- ②根模块与passport打通
4. 注册页面的配置
3. 使用Module管理代码
在小型的项目中可以参考欢迎页的做法直接在pages文件夹中创建页面,但是功能多起来就不好管理。你可以直接创建文件夹分门别类管理好每个页面,也可以使用模块管理页面。例如可以把注册、登录、修改密码等页面都归到passport模块中管理。如果你觉得使用模块的方式组织项目结构比较复杂,你也可以不创建passport模块,只创建passport文件夹。在简单的项目中你可以这么处理,但在实际的项目中建议使用模块。
发现前面一个小问题:
我没有pages文件夹 于是我建了个文件夹 然后把welcome移到里面了 然后做了相应的改动(主要是相对地址)
4 创建passportModule
4.1 创建模块passport,同时添加passport路由
目的就是用passport模块来管理注册 登录等一系列模块
在小型的项目中可以参考欢迎页的做法直接在pages文件夹中创建模块passport,同时添加passport路由:
ionic g module passport --routing
4.2 创建注册页面和登录页面
在passport下
4.3 删去signup文件夹下signup.routing.ts和signup.module.ts这两个文件
同理login文件夹
不想让每个页面都带一个路由和模块
4.4 在passport的路由文件夹添加路由信息
完成思路.2.①
const routes: Routes = [{ path: 'signup',component: SignupPage},{path: 'login',component: LoginPage
}];
这是一个数组,放的是对象,也是一个route,每个路由有个path和组件名称
4.5 在app的路由文件夹添加passport路由信息
完成思路.2.②
{path: 'passport',loadChildren: () => import('../app/pages/passport/passport.module').then( m => m.PassportModule),}
4.6 模块声明
完成思路.3.①
要让passport知道有两个对象login和signup
一般组件 页面都是在这声明
5 使用share模块
完成思路.1:
1. 第三方模块的导入导出
2. 谁用到这些模块第三方,都要声明share模块
共享模块,指当你需要针对整个业务模块都需要使用一些第三方模块,自定义组件,自定义指令,都应该存在这里。
5.1 导入CommonModule,FormsModule,IonicModule等第三方模块
5.2 修改exports属性,导出其他模块都需要的模块。
为了别人能用
share模块代码如下:
import { LocalStorageService } from './local-storage.service';
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { IonicModule } from '@ionic/angular';@NgModule({declarations: [],providers: [LocalStorageService], // 服务提供者,不写也没问题imports: [CommonModule,FormsModule,IonicModule],exports: [CommonModule,FormsModule,IonicModule]
})
export class SharedModule { }
5.3 在PassportModule中导入SharedModule
要用share模块中的第三方就要声明share模块:在这里passport想用到share模块里的模块,就应该让oasport知道由share,所以声明
5.4 在WelcomeModule中导入SharedModule
我之前有导入过
6 跳转到注册页面
6.1 在欢迎页中点击注册按钮进入注册页
方法一:
为“注册”按钮添加href属性。
src\app\pages\welcome\welcome.page.html
<!-- 为ion-button元素添加href属性 -->
<ion-button color="primary" fill="outline" expand="block" href="/passport/signup">注册</ion-button>
方法二:
<!-- 为ion-button元素添加routerLink属性 -->
<ion-button color="primary" fill="outline" expand="block" routerLink="/passport/signup">注册</ion-button>
6.2 在欢迎页中点击跳过按钮进入注册页
1. 添加跳过事件
2.跳过事件与点击事件绑定
跳转事件标准
6.2.1 在WelcomePage组件类中添加onSkip方法。
参考之前的任务,使用Router实现从欢迎页导航到注册页。目前还没实现已登录状态下的跳过处理,等到登录任务中再完善逻辑。
6.2.2 为“跳过”按钮添加click事件绑定
使用 Angular 事件绑定语法把click事件绑定到事件处理器。
src\app\pages\welcome\welcome.page.html
<ion-header class="ion-no-border"><ion-toolbar><ion-buttons slot="end" [hidden] = "!showSkip" (click)="onClick()"> <ion-button > // (click)="onClick() 点击执行onClick()跳过</ion-button></ion-buttons></ion-toolbar>
</ion-header>
7 实现注册界面
7.1 样式scss
src\app\pages\passport\signup\signup.page.scss
存放样式
①通过样式表设置图片宽度。
界面的顶部放一张图片居中,宽度33%。
.logo {width: 33%;
}
② 图片居中
使用类选择器ion-text-center,在旧版Ionic中使用的是属性选择器text-center。后面的任务中喷到类似的情况统一改成class=“ion-text-center”。
src\app\pages\passport\signup\signup.page.html
<div class="ion-text-center"><img class="logo" src="assets/img/logo.png" alt="">
</div>
③ 居中和水平线
src\app\pages\passport\signup\signup.page.scss
/* 其他省略 */
hr {height: 1.5px;border: none;
}
.full-width {width: 100%;
}
实现添加水平线:
src\app\pages\passport\signup\signup.page.html
<!-- 其他代码省略 -->
<ion-col class="ion-align-self-center"><hr>
</ion-col>
<!-- 其他代码省略 -->
7.2 布局
① 放4张图片表示4个步骤。
使用Grid布局,1行7列,第2、4、6列中的内容垂直居中并添加一条水平线。
为注册页添加样式。
src\app\pages\passport\signup\signup.page.scss
/* 其他省略 */
hr {height: 1.5px;border: none;
}
.full-width {width: 100%;
}
图片之间添加水平线。
src\app\pages\passport\signup\signup.page.html
<!-- 其他代码省略 -->
<ion-col class="ion-align-self-center"><hr>
</ion-col>
<!-- 其他代码省略 -->
② 放4张图片表示4个步骤
使用Grid布局,1行7列,第2、4、6列中的内容垂直居中并添加一条水平线。
为注册页添加样式。
src\app\pages\passport\signup\signup.page.scss
/* 其他省略 */
hr {height: 1.5px;border: none;
}
.full-width {width: 100%;
}
图片之间添加水平线。
src\app\pages\passport\signup\signup.page.html
<!-- 其他代码省略 -->
<ion-col class="ion-align-self-center"><hr>
</ion-col>
<!-- 其他代码省略 -->
③ 使用Slides
包含4个slide子元素,每个slide对应一个form标签,元素不要加pager属性。参考之前的任务自行完成。
<!-- 其他代码省略 -->
<ion-slide><form><ion-list><ion-item></ion-item><!-- 根据需求添加若干ion-item --></ion-list></form>
</ion-slide>
<!-- 其他代码省略 -->
7.3 使用Slides,通过索引判断注册到那一步了,同时亮不同的标
部分代码:
<ion-grid class="fixed"><ion-row><ion-col class="ion-align-self-center"><img src="assets/img/registered_one.png" alt="" *ngIf="slideIndex!==0"><img src="assets/img/registered_one_one.png" alt="" *ngIf="slideIndex===0"></ion-col><hr/><ion-col class="ion-align-self-center"><img src="assets/img/registered_two.png" alt="" *ngIf="slideIndex!==1"><img src="assets/img/registered_two_two.png" alt="" *ngIf="slideIndex===1"></ion-col><hr/><ion-col class="ion-align-self-center"><img src="assets/img/registered_three.png" alt="" *ngIf="slideIndex!==2"><img src="assets/img/registered_three_three.png" alt="" *ngIf="slideIndex===2"></ion-col><hr/><ion-col class="ion-align-self-center"><img src="assets/img/register_four.png" alt="" *ngIf="slideIndex!==3"><img src="assets/img/register_four_four.png" alt="" *ngIf="slideIndex===3"></ion-col></ion-row></ion-grid>
讲解:
7.3.1 通过索引来判断注册进行到哪一步
每个步骤分别对应两张图片,某一种状态下显示其中一张,另外一张隐藏。第一个小标为例
src\app\pages\passport\signup\signup.page.html
<ion-col class="ion-align-self-center"><img src="assets/img/registered_one.png" alt="" *ngIf="slideIndex!==0"><img src="assets/img/registered_one_one.png" alt="" *ngIf="slideIndex===0"></ion-col>
当*ngIf后面的表达式的结果为true,ngIf会把img添加到DOM中,否则ngIf会从DOM中移除img。
- 那么如果slideIndex!==0,那么显示assets/img/registered_one.png
- 这张照片;如果slideIndex===0,显示assets/img/registered_one_one.png
7.3.2 通过代码切换4个slide
① 声明变量signupSlides 滑动时同时发生onSlideWillChange()
<ion-slides #signupSlides (ionSlideWillChange)="onSlideWillChange($event)">
② @ViewChild定义模板引用变量
@ViewChild饰器用于获取模板视图中的元素或直接调用其组件中的方法
在组件类中通过@ViewChild声明对子组件元素的实例引用,意思是通过注入的方式将子组件注入到@ViewChild容器中,你可以想象成依赖注入的方式注入,只不过@ViewChild不能在构造器constructor中注入,因为@ViewChild会在ngAfterViewInit()回调函数之前执行。
说人话就是我理解是感知鼠标
src\app\pages\passport\signup\signup.ts文件
export class SignupPage implements OnInit {@ViewChild('signupSlides', { static: true }) signupSlides: IonSlides;
。。。
}
//字符串'signupSlides'和模板中的#signupSlides引用变量的名称一致
export class SignupPage implements OnInit{}
signup初始化的东西,里面有页面表现出来的功能 都在这里搞
③ 定义事件onSlideWillChange()发生什么
触发slideIndex变化
export class SignupPage implements OnInit{}中
onSlideWillChange(event) {this.signupSlides.getActiveIndex().then((index) => {this.slideIndex = index;});
④ 设置slideIndex初始值
export class SignupPage implements OnInit{}中
slideIndex = 0;
7.3.2 把退后\前进实现
① 封装功能
同样位置:export class SignupPage implements OnInit{}
ngOnInit() {this.signupSlides.lockSwipes(true); // 如果时ture那么就锁定 滑动不了页面}onNext() {this.signupSlides.lockSwipes(false); // 没有所页面this.signupSlides.slideNext(); // 当发生滑倒下一页时this.slideIndex++; // slideIndex+1this.signupSlides.lockSwipes(true); // 就划不动了} onPrevious() {this.signupSlides.lockSwipes(false);this.signupSlides.slidePrev();this.slideIndex--;this.signupSlides.lockSwipes(true);}
先解锁,滑动,参数索引改变,再锁定
② 和按键产生关系实现功能
在“上一步”按钮上绑定click事件,调用onPrevious()。在“下一步”按钮上绑定click事件,调用onNext()。这里onNext没找到在哪用
在组件类中通过@ViewChild声明对子组件元素的实例引用,意思是通过注入的方式将子组件注入到@ViewChild容器中,你可以想象成依赖注入的方式注入,只不过@ViewChild不能在构造器constructor中注入,因为@ViewChild会在ngAfterViewInit()回调函数之前执行。
src\app\pages\passport\signup\signup.ts文件
创建sugnup,ts
视图模型的名称与页面的名称一致,也可以在名称的后面加VO(View Object)这个后缀。
src\app\pages\passport\signup\signup.ts
在组件类中通过@ViewChild声明对子组件元素的实例引用,意思是通过注入的方式将子组件注入到@ViewChild容器中,你可以想象成依赖注入的方式注入,只不过@ViewChild不能在构造器constructor中注入,因为@ViewChild会在ngAfterViewInit()回调函数之前执行。
src\app\pages\passport\signup\signup.ts文件
@ViewChild('signupSlides', {static: false}) signupSlides: IonSlides;
//字符串'signupSlides'和模板中的#signupSlides引用变量的名称一致
ngOnInit() {this.signupSlides.lockSwipeNext(true);
}
onNext(){this.signupSlides.slideNext();
}
onPrevious() {this.signupSlides.slidePrev()
}
然后在SignupPage组件类中添加signup属性。并初始化
src\app\pages\passport\signup\signup.page.ts
事件绑定
在这里插入图片描述
做下面有问题提示的
</ion-item ><ion-item *ngIf="phone.touched && phone.invalid"><ion-text class="ion-text-left" color="danger" *ngIf="phone.errors?.required">请输入手机号码</ion-text><ion-text class="ion-text-left" color="danger" *ngIf="phone.errors?.pattern">您输入的手机号格式不正确</ion-text> </ion-item>
提交保单
添加保单变量 是个angular表单,加上个绑定
短信验证
验证码功能基本上用于passport模块,注册或者忘记密码时会使用到。可以在passport文件夹下创建shared文件夹,或者直接在passport文件夹中创建。如果验证码服务在其他模块中也有用到,可以在ShareModule中创建。参考之前的任务创建验证码服务。
src\app\passport\authentication-code.service.ts
@Injectable({providedIn: 'root'
})
export class AuthenticationCodeService {// 用于保存验证码private code: string;// 存放验证码的过期时间private deadline: number;constructor() {this.code = '';}// 生成指定长度的随机数字createCode(count: number): string{this.code = '';// 10分钟内有效this.deadline = Date.now() + 60 * 10 * 1000;for (let i = 0; i < count; i++) {// 请补上相关的代码}return this.code;}// 验证用户输入的短信验证码是否一致,是否过期validate(value: string): boolean{const now = Date.now();return value === this.code && now < this.deadline;}
}
创建服务AuthenticationCode
8. 设置用户信息
import { Injectable } from '@angular/core';
import { AjaxResult } from 'src/app/shared/classes/ajax-result';
import { LocalStorageService } from 'src/app/shared/services/local-storage.service';
import { Shop } from '../setting/shop/shop';
import { ShopService } from '../setting/shop/shop.service';
import { Signup } from './signup/signup';@Injectable({providedIn: 'root'
})
export class PassportService {constructor(private localStorageService: LocalStorageService, private shopService: ShopService) { }/*** 登录*/async login(phoneOrEmail: string, password: string): Promise<AjaxResult> {const accounts = this.localStorageService.get('TLoginAccount', []);// tslint:disable-next-line:prefer-for-offor (let i = 0; i < accounts.length; i++) {// 此处要用== 因为你输入的时候是数字,而他这个Identifier是字符串,不能用===if (accounts[i].Identifier == phoneOrEmail && accounts[i].credential === password) {this.setLoginLog(accounts[i].userId, accounts[i].Identifier);this.setUser(accounts[i].userId);return new AjaxResult(true, null);}}return new AjaxResult(false, null, {message: '账户不存在或者密码错误',details: ''});}/*** 登录日志* @param userId */public setLoginLog(userId: any, username: string) {let LoginLogs = this.localStorageService.get('LoginLogs', []);const loginLog: LoginLog = {userId: userId,username: username,loginTime: new Date().getTime(),expirTime: new Date().getTime() + 1000 * 60 * 60 * 24 * 5};LoginLogs.push(loginLog);this.localStorageService.set('LoginLogs', LoginLogs);}/*** 设置当前登录用户* @param userId */public setUser(userId: any) {let users = this.localStorageService.get('TUser', []);for (let i = 0; i < users.length; i++) {if (users[i].id === userId) {let user = users[i];this.localStorageService.set('User', user);}}}/*** 注册* @param sign */async addUser(sign: Signup) {// 验证手机号是否唯一const ajaxResult = this.isUniquePhone(sign.phone);if (!ajaxResult.success) {return ajaxResult;}// 判断邮箱是否已存在const ajaxResult1 = this.isUniqueEmail(sign.email);if (!ajaxResult1.success) {return ajaxResult1;}// 添加用户let users: User[];const userId = Date.now();const user: User = {id: userId,phone: sign.phone,email: sign.email,password: sign.password,createTime: new Date()};users = this.localStorageService.get('TUser', []);users.push(user);this.localStorageService.set('TUser', users);// 添加手机号的账户const account: LoginAccount = {userId: userId,Identifier: sign.phone,credential: sign.password,}this.addAccount(account);// 添加邮箱的账户const account1: LoginAccount = {userId: userId,Identifier: sign.email,credential: sign.password,}this.addAccount(account1);// 添加店铺let shop: Shop = {userId: userId,shopName: '未填写',shopShortName: '未填写',userName: '未填写',shopTel: sign.phone,industryType: '未填写'}this.shopService.addShop(shop);return new AjaxResult(true, null);}/*** 判断手机号是否存在* @param sign 注册用户信息*/public isUniquePhone(phone: string) {let users = this.localStorageService.get('TUser', []);for (let i = 0; i < users.length; i++) {if (users[i].phone === phone) {return new AjaxResult(false, null, {message: '您的手机号码已经被注册',details: ''});}}return new AjaxResult(true, null);}/*** 判断邮箱是否存在* @param sign 注册用户信息*/public isUniqueEmail(email: string) {let users = this.localStorageService.get('TUser', []);for (let i = 0; i < users.length; i++) {if (users[i].email === email) {return new AjaxResult(false, null, {message: '您的邮箱已经被注册',details: ''});}}return new AjaxResult(true, null);}/*** 判断账户是否已存在* @param account */async isUniqueAccount(account: string): Promise<AjaxResult> {let accounts = this.localStorageService.get('TLoginAccount', []);for (let i = 0; i < accounts.length; i++) {if (accounts[i].Identifier === account) {return new AjaxResult(true, null);}}return new AjaxResult(false, null, {message: '账户不存在,请先注册',details: ''});}async updatePassword(username: string, password: string) {let accounts = this.localStorageService.get('TLoginAccount', []);for (let i = 0; i < accounts.length; i++) {// 根据手机号或者邮箱找到账户if (accounts[i].Identifier === username) {let userId = accounts[i].userId;// 同一个用户以手机号和以邮箱为账户名的两个账户的id一致// 再根据账户的id,修改另一个以邮箱或手机号为账户名的账户的密码for (let j = 0; j < accounts.length; j++) {if (accounts[j].userId === userId) {accounts[j].credential = password;}}this.localStorageService.set('TLoginAccount', accounts);return new AjaxResult(true, null);}}return new AjaxResult(false, null, {message: '账户不存在或者密码错误',details: ''});}public addAccount(account: LoginAccount) {let accounts = this.localStorageService.get('TLoginAccount', []);accounts.push(account);this.localStorageService.set('TLoginAccount', accounts);}}export interface User {id: number;phone: string;email: string;password: string;createTime: Date
}export interface LoginAccount {userId: number;Identifier: string;credential: string;
}export interface LoginLog {userId: string,username: string,loginTime: number,expirTime: number
}
工程训练:生意专家:03 注册的实现相关推荐
- 工程训练:生意专家:04 登陆实现
0. 项目目录 欢迎页的实现 程序第一次运行实现 注册的实现 登陆的实现 首页的实现 店铺设置的实现 商品分类浏览的实现 编辑商品分类的实现 新增商品的实现 商品管理的实现 目录 0. 项目目录 1. ...
- 智能车竞赛接入工程训练竞赛相关事项-建议稿件
简 介: 对于智能车竞赛与工训竞赛在教指委指导下完成相互结合方面进行初步的规划. 关键词: 智能车竞赛,工训竞赛 §01 背景介绍 一.全国大学生智能车竞赛 全国大学生 智能车竞赛 最初是由教育部 ...
- 工程训练大赛物流小车_宁大机械学子在工程训练省赛中斩获佳绩,取得历史性突破...
2019第六届 浙江省大学生工程训练综合能力竞赛暨第五届浙江创客教育基地联盟创客大赛 圆满落幕 --宁大斩获省一等奖1项,二等奖3项,三等奖1项,获奖率100%,获奖人数15人创历史新高. 赛事介绍 ...
- 移动平台开发工程训练
题 目 移动平台开发工程训练 学科部.系: 信息学科部计算机系 专业班级: 学 号: 学生姓名: 指导教师: 起讫日期: 移动平台开发工程训练报告 实验名称: 移动平台开发工程训练 实验目的: 本次工 ...
- 【南大科院】高级网络服务工程训练
密级: 科学技术学院 NANCHANG UNIVERSITY COLLEGE OF SCIENCE AND TECHNOLOGY 计算机系工程训练报告 <高级网络服务工程训练> (2019 ...
- 【竞赛总结】第七届工程训练大赛智能搬运赛项心得
22/9/25更新 最近发现这篇博客被越来越多人收藏,我受宠若惊.为了给大家提供更准确的参考,我在今晚修改了之前的全文内容,并删掉一些没用的废话. 22/4/15更新 发现这篇文章被很多人看到了,潦草 ...
- 南开大学工程训练结课报告
工程训练结课报告 一.焊电路 1.什么是虚焊?虚焊有什么危害? 答:虚焊是指焊锡过少或未很好焊接. 虚焊会导致电路未连接甚至焊锡脱落. 2.通过工程训练课的练习,你认为焊好电路有那些要领? 答:1)要 ...
- 工程训练大赛物流小车_我校在全国大学生工程训练综合能力竞赛总决赛中创佳绩...
6月1日至6月2日,第六届全国大学生工程训练综合能力竞赛总决赛在天津职业技术师范大学隆重举行.我校三名学子在无碳小车"S环形"赛道挑战赛中获一等奖,这是我校首次在该项赛事中摘得重量 ...
- 第七届全国大学生工程训练综合能力竞赛(工训赛) 智能配送无人机赛项 省赛心得
第七届全国大学生工程训练综合能力竞赛(工训赛) 智能配送无人机赛项 省赛心得 第七届全国大学生工程训练综合能力竞赛(工训赛)江西省赛 在华东交通大学落下帷幕.至此,为时四个多月的备赛阶段终于告一段落了 ...
- 南昌大学数据库实训大作业_南昌大学工程训练实习报告范文
2017南昌大学工程训练实习报告[一] (一)电火花加工--第一天的收获 第一天,金工实习第一天,在经过早上一个小时的安全教育以及自己的心理觉悟,开始了第一个工种的训练, 首先,老师指导我们把自己喜欢 ...
最新文章
- C++继承和派生简明教程
- React优化性能的经验教训
- Mongodb带验证的主从复制架构
- 法那科机器人初始化启动_发那科机器人的控制方式和控制柜的启动方式
- 计算机图形设计论文 真实图形生成技术的发展,绘制技术论文,关于计算机图形图像绘制技术的现状应用相关参考文献资料-免费论文范文...
- spatial Statistics
- Html5学习进阶一 视频和音频
- vb 复制 剪贴板 html,VB把选中的内容复制到剪切板
- centos linux 通过yum安装nginx
- schedule java_Schedule.java
- 对volatile不具有原子性的理解
- 图像传感器设计资料-764-GSPRINT4502 2MP-4.5微米 全局快门 高速 CMOS 图像传感器
- MapGIS 的一些小总结
- idm bt种子下载如何提升速度?
- 跨站点设置 Cookie
- 如何避免渠道商的“养卡”和“劝弃卡”行为的发生
- [清华集训2015 Day1]玛里苟斯-[线性基]
- 2020双非通信跨考江南大学软件工程专硕
- 前端复健(微信小程序)
- python多元非线性回归_利用Python进行数据分析之多元线性回归案例