在前面测试通过odoo登录的功能,这次的问题重点是如何访问后台具体的业务类的接口呢?这次就以我们在odoo中安装的lunch模块为例,目标是获取lunch.alert的数据,如下图

具体过程接上次文章,继续完善OdooJsonRpc类的代码,首先是基础代码,这个是需要提供具体的model名称和具体方法,也是是一个很基础的方法,后台的odoo网站会利用类似C#反射的机制调用目标类的方法。

    /**
* Calls the method of that particular model
* @param model Model name
* @param method Method name of particular model
* @param args Array of fields
* @param kwargs Object
*/
public call(model: string, method: string, args: any, kwargs?: any)
{
kwargs = kwargs || {};
let params =
{
model: model,
method: method,
args: args,
kwargs: kwargs == false ? {} : kwargs,
context: this.getContext()
};
return this.sendRequest("/web/dataset/call_kw", params);
}

调用以上基础call方法的几个基本封装函数有如下几个,基本实现了对数据的CRUD功能,当然基本上是针对一条数据的操作

    /**
* Reads that perticular fields of that particular ID
* @param model Model Name
* @param id Id of that record which you want to read
* @param mArgs Array of fields which you want to read of the particular id
*/ public read(model: string, id: number, mArgs: any): Promise<any>
{
let args =
[
id, [mArgs]
]
return this.call(model, 'read', args)
} /**
* Provide the name that you want to search
* @param model Model name
* @param name Name that you want to search
*/
public nameSearch(model: string, name: string): Promise<any>
{
let kwargs =
{
name: name,
args: [],
operator: "ilike",
limit:
}
return this.call(model, 'name_search', [], kwargs)
} /**
* Provide the IDs and you will get the names of that paticular IDs
* @param model Model name
* @param mArgs Array of IDs that you want to pass
*/
public nameGet(model: string, mArgs: any): Promise<any>
{
let args = [mArgs]
return this.call(model, 'name_get', args)
} /**
* Create a new record
* @param model Model name
* @param mArgs Object of fields and value
*/
public createRecord(model: string, mArgs: any)
{
let args = [mArgs];
return this.call(model, "create", args, null)
} /**
* Delete the record of particular ID
* @param model Model Name
* @param id Id of record that you want to delete
*/
public deleteRecord(model: string, id: number)
{
let mArgs = [id]
return this.call(model, "unlink", mArgs, null)
} /**
* Updates the record of particular ID
* @param model Model Name
* @param id Id of record that you want to update the.
* @param mArgs The Object of fields and value that you want to update
* (e.g)
* let args = {
* "name": "Mtfa"
* }
*/
public updateRecord(model: string, id: number, mArgs: any)
{
let args =
[
[id], mArgs
]
return this.call(model, "write", args, null)
}

针对单条数据的读取,这里还有另外一种方法,类似上面的read函数

    /**
* Loads all data of the paricular ID
* @param model Model name
* @param id Id of that particular data which you want to load
*/
public load(model: string, id: number): Promise<any>
{
let params =
{
model: model,
id: id,
fields: [],
context: this.getContext()
}
return this.sendRequest("/web/dataset/load", params)
}

还有对odoo多条件查询的情况,尤其还有分页的问题,这里也有这样一个很实用的分页查询的方法,这个在日后app的开发中会经常用到

    /**
* Fires query in particular model with fields and conditions
* @param model Model name
* @param domain Conditions that you want to fire on your query
* (e.g) let domain = [
* ["id","=",11]
* ]
* @param fields Fields names which you want to bring from server
* (e.g) let fields = [
* ["id","name","email"]
* ]
* @param limit limit of the record
* @param offset
* @param sort sorting order of data (e.g) let sort = "ascending"
*/
public searchRead(model: string, domain: any, fields: any, limit: number, offset: any, sort: string)
{
let params =
{
model: model,
fields: fields,
domain: domain,
offset: offset,
limit: limit,
sort: sort,
context: this.getContext()
};
return this.sendRequest("/web/dataset/search_read", params);
}

到此,访问odoo具体业务类的OdooJsonRpc类封装完毕,完整的代码在这里。接下来怎么获取我们的lunch.alert数据呢??

首先定义我们访问odoo业务类的成员变量,这里我们的model类是lunch.alert,需要获取的字段是message和id,其他参数我们暂使用默认的值

    private lunchAlert = "lunch.alert";
private fields = ["message", "id"];
private domain = []
private sort = ""
private limit =
private offset =
private items: Array<{ id: number, message: string }> = []

第二步是,与odoo后台网站交互获取数据的过程

    private TestMyOdooModel()
{
this.odooRpc.searchRead(this.lunchAlert,this.domain, this.fields, this.limit, this.offset,this.sort)
.then((lunchAlerts: any) =>
{
let json = JSON.parse(lunchAlerts._body);
if (!json.error)
{
let query = json["result"].records
for (let i in query)
{
this.items.push
({
id: query[i].id,
message: query[i].message
})
}
this.utils.presentAlert("Lunch Message", this.items[].message,[{text: "Ok"}])
}
else
{
this.utils.presentAlert("LunchAlert", "Parse lunch alert error",[{text: "Ok"}])
}
})
}

如果正确获取数据,我们会弹出第一条数据对应的message.

编译打包成*.apk,在手机上测试,确实成功了,如下图所示。

由于这些都是测试阶段的代码,将来可能会改变,现阶段把这些代码全部放在这里。

测试部分的Page页面odooLogin.ts

import { Component } from '@angular/core';
import {
AlertController,
IonicPage,
Loading,
LoadingController,
NavController,
NavParams
} from 'ionic-angular';
import { OdooJsonRpc } from '../../../../providers/baseService/Odoojsonrpc';
import { Utils } from "../../../../providers/baseService/Utils"; @IonicPage()
@Component
({
selector: 'page-odooLogin',
templateUrl: 'odooLogin.html',
}) export class OdooLoginPage
{
private listForProtocol: Array<{ protocol: string}> = []
public perfectUrl: boolean = false
public odooUrl
public selectedProtocol
private dbList: Array<{ dbName: string}> = []
private selectedDatabase
private email
private password constructor(public navCtrl: NavController,
private alert: AlertController, public navParams: NavParams,
private odooRpc: OdooJsonRpc, private loadingCtrl: LoadingController,
private utils: Utils)
{
this.listForProtocol.push({ protocol: "http" })
this.listForProtocol.push({protocol: "https"})
} public checkUrl()
{
this.utils.presentLoading("Please Wait")
this.odooRpc.init
({
odoo_server: this.selectedProtocol + "://" + this.odooUrl
//http_auth: 'username:password' // optional
}) this.odooRpc.getDbList().then((dbList: any) =>
{
console.log(dbList)
this.perfectUrl = true
this.utils.dismissLoading()
this.fillData(dbList)
}).
catch((err: any) =>
{
console.log(err)
this.utils.presentAlert("Error", "You Entered a wrong Odoo URL",
[{
text: "Ok"
}])
this.utils.dismissLoading()
});
} public fillData(res: any)
{
let body = JSON.parse(res._body)
let json = body['result'];
this.dbList.length = ;
for (var key in json)
{
this.dbList.push({ dbName: json[key] });
}
} private login()
{
this.utils.presentLoading("Please wait", , true)
this.odooRpc.login(this.selectedDatabase, this.email, this.password)
.then((res: any) =>
{
let logiData: any = JSON.parse(res._body)["result"];
logiData.password = this.password
localStorage.setItem("token", JSON.stringify(logiData));
//this.utils.dismissLoading()
this.utils.presentAlert("Congratulation", "You login success",[{text: "Ok"}])
this.TestMyOdooModel()
}).
catch((err) =>
{
this.utils.presentAlert("Error", "Username or password must be incorrect",
[{
text: "Ok"
}])
});
} private lunchAlert = "lunch.alert";
private fields = ["message", "id"];
private domain = []
private sort = ""
private limit =
private offset =
private items: Array<{ id: number, message: string }> = [] private TestMyOdooModel()
{
this.odooRpc.searchRead(this.lunchAlert,this.domain, this.fields, this.limit, this.offset,this.sort)
.then((lunchAlerts: any) =>
{
let json = JSON.parse(lunchAlerts._body);
if (!json.error)
{
let query = json["result"].records
for (let i in query)
{
this.items.push
({
id: query[i].id,
message: query[i].message
})
}
this.utils.presentAlert("Lunch Message", this.items[].message,[{text: "Ok"}])
}
else
{
this.utils.presentAlert("LunchAlert", "Parse lunch alert error",[{text: "Ok"}])
}
})
}
}

页面布局部分odooLogin.html

<ion-content class="background">
<ion-card>
<ion-card-content> <div class="spacer" style="height: 10px;"></div>
<ion-item>
<ion-label style="color: #fff">Select Protocol</ion-label>
<ion-select [(ngModel)]="selectedProtocol" style="color: #fff" name="dbNames">
<ion-option *ngFor="let item of listForProtocol" value="{{item.protocol}}">{{item.protocol}}</ion-option>
</ion-select>
</ion-item>
<div class="spacer" style="height: 10px;"></div>
<ion-item>
<ion-input [(ngModel)]="odooUrl" type="url" name="odooUrl" placeholder="Odoo Url"></ion-input>
</ion-item>
<div class="spacer" style="height: 10px;"></div>
<button ion-button block round outline color="light" (click)="checkUrl()" text-center>
Check Url
<ion-icon name="md-arrow-round-forward"></ion-icon>
</button>
<div [hidden]="!perfectUrl">
<form (ngSubmit)="login()" #registerForm="ngForm">
<div class="spacer" style="height: 10px;"></div>
<ion-item>
<ion-input type="email" [(ngModel)]="email" name="email" placeholder="Email" required></ion-input>
</ion-item>
<div class="spacer" style="height: 5px;"></div>
<ion-item>
<ion-input type="password" [(ngModel)]="password" name="pass" placeholder="Password" required></ion-input>
</ion-item>
<div class="spacer" style="height: 10px;"></div>
<div class="spacer" style="height: 10px;"></div>
<ion-item>
<ion-label style="color: #fff">Select Database</ion-label>
<ion-select [(ngModel)]="selectedDatabase" name="selectDatabase" style="color: #fff" required>
<ion-option *ngFor="let item of dbList" value="{{item.dbName}}">{{item.dbName}}</ion-option>
</ion-select>
</ion-item>
<button ion-button block round outline color="light" [disabled]="!registerForm.form.valid" (click)="signin()">Login</button>
</form>
</div>
</ion-card-content>
</ion-card>
</ion-content

CSS效果部分odooLogin.scss

page-odooLogin {
.background {
height: %;
width: %;
background-size: cover !important;
background-position: center center !important;
background-image: url('../assets/imgs/mountain.jpg')
} ion-card.card {
margin-top: %;
box-shadow: none;
background: rgba(, , , 0.5);
border-radius: 5px;
}
a, p,
ion-card-header.card-header {
color: #fff!important;
} .list > .item-block:first-child {
border: medium none;
} .item {
margin-bottom: 10px;
background: rgba(, , , 0.5);
border: medium none; .text-input, {
color: #fff;
} input::-moz-placeholder{
color: #fff!important;
}
input:-moz-placeholder {
color: #fff!important;
}
*:-moz-placeholder{
color: #fff!important;
}
*:-ms-input-placeholder{
color: #fff!important;
}
*::-webkit-input-placeholder{
color: #fff!important;
}
}
}

OdooJsonRpc部分Odoojsonrpc.ts

import { Injectable } from '@angular/core';
import 'rxjs/add/operator/toPromise';
import 'rxjs/Rx'; import { Headers, Http } from '@angular/http';
import { Utils } from './Utils'; @Injectable()
export class OdooJsonRpc
{
private jsonRpcID: number = ;
private headers: Headers;
private odoo_server: string;
private http_auth: string;
private list = "/web/database/list";
private get_list = "/web/database/get_list";
private jsonrpc = "/jsonrpc"; constructor(private http: Http, private utils: Utils)
{
this.http = http;
} /**
* Builds a request for odoo server
* @param url Odoo Server URL
* @param params Object
*/
private buildRequest(url: String, params: any)
{
this.jsonRpcID += ;
return JSON.stringify
({
jsonrpc: "2.0",
method: "call",
id: this.jsonRpcID,
params: params,
});
} /**
* Returns the error message
* @param response Error response from server
*/
public handleOdooErrors(response: any)
{
let err: string = response.error.data.message
let msg = err.split("\n")
let errMsg = msg[] this.utils.presentAlert("Error", errMsg, [{
text: "Ok",
role: "cancel"
}])
} /**
* Handles HTTP errors
*/
public handleHttpErrors(error: any)
{
return Promise.reject(error.message || error);
} /**
* Sends a JSON request to the odoo server
* @param url Url of odoo
* @param params Object
*/
public sendRequest(url: string, params: Object): Promise<any>
{
let options = this.buildRequest(url, params);
this.headers = new Headers({
'Content-Type': 'application/json; charset=utf-8',
}); let result = this.http.post(this.odoo_server + url, options, { headers: this.headers })
.toPromise()
return result;
} public init(configs: any)
{
this.odoo_server = configs.odoo_server;
this.http_auth = configs.http_auth || null;
} public setOdooServer(odoo_server: string)
{
this.odoo_server = odoo_server;
} public setHttpAuth(http_auth: string)
{
this.http_auth = http_auth;
} /**
* Gets the server info
*/
public getServerInfo()
{
return this.sendRequest("/web/webclient/version_info", {});
} /**
* Gets the session info
*/
public getSessionInfo()
{
return this.sendRequest("/web/session/get_session_info", {});
} /**
* Gets the Odoo Server Version Number
*/
public getServerVersionNumber(): Promise<number>
{
return this.getServerInfo().then((res: any): Promise<number> =>
{
return new Promise<number>((resolve) =>
{
resolve(JSON.parse(res._body)["result"]["server_version_info"][]);
});
});
} /**
* Get the database list
*/
public getDbList(): Promise<string>
{
let dbParams =
{
context: {}
}
return this.getServerVersionNumber().then((data: number) =>
{
if (data <= )
{
return this.sendRequest(this.get_list, dbParams);
}
else if (data == )
{
return this.sendRequest(this.jsonrpc, dbParams);
}
else
{
return this.sendRequest(this.list, dbParams);
}
})
} /**
* Returns all modules that are installed in your database
*/
public modules(): Promise<string>
{
let params =
{
context: {}
}
return this.sendRequest("/web/session/modules", params)
} /**
* Login to the database
* @param db Database name of odoo
* @param login Username
* @param password password
*/
public login(db: string, login: string, password: string)
{
let params =
{
db: db,
login: login,
password: password,
base_location: this.odoo_server,
context: {}
};
return this.sendRequest("/web/session/authenticate", params)
} /**
* Check whether the session is live or not
*/
public check(): Promise<string>
{
let params =
{
context: this.getContext()
}
return this.sendRequest("/web/session/check", params)
} /**
* Destroy the session
*/
public destroy()
{
let params =
{
context: {}
}
return this.sendRequest("/web/session/destroy", params)
} /**
* Fires query in particular model with fields and conditions
* @param model Model name
* @param domain Conditions that you want to fire on your query
* (e.g) let domain = [
* ["id","=",11]
* ]
* @param fields Fields names which you want to bring from server
* (e.g) let fields = [
* ["id","name","email"]
* ]
* @param limit limit of the record
* @param offset
* @param sort sorting order of data (e.g) let sort = "ascending"
*/
public searchRead(model: string, domain: any, fields: any, limit: number, offset: any, sort: string)
{
let params =
{
model: model,
fields: fields,
domain: domain,
offset: offset,
limit: limit,
sort: sort,
context: this.getContext()
};
return this.sendRequest("/web/dataset/search_read", params);
} /**
* Calls the method of that particular model
* @param model Model name
* @param method Method name of particular model
* @param args Array of fields
* @param kwargs Object
*/
public call(model: string, method: string, args: any, kwargs?: any)
{ kwargs = kwargs || {};
let params =
{
model: model,
method: method,
args: args,
kwargs: kwargs == false ? {} : kwargs,
context: this.getContext()
};
return this.sendRequest("/web/dataset/call_kw", params);
} /**
* Reads that perticular fields of that particular ID
* @param model Model Name
* @param id Id of that record which you want to read
* @param mArgs Array of fields which you want to read of the particular id
*/ public read(model: string, id: number, mArgs: any): Promise<any>
{
let args =
[
id, [mArgs]
]
return this.call(model, 'read', args)
} /**
* Loads all data of the paricular ID
* @param model Model name
* @param id Id of that particular data which you want to load
*/
public load(model: string, id: number): Promise<any>
{
let params =
{
model: model,
id: id,
fields: [],
context: this.getContext()
}
return this.sendRequest("/web/dataset/load", params)
} /**
* Provide the name that you want to search
* @param model Model name
* @param name Name that you want to search
*/
public nameSearch(model: string, name: string): Promise<any>
{
let kwargs =
{
name: name,
args: [],
operator: "ilike",
limit:
}
return this.call(model, 'name_search', [], kwargs)
} /**
* Provide the IDs and you will get the names of that paticular IDs
* @param model Model name
* @param mArgs Array of IDs that you want to pass
*/
public nameGet(model: string, mArgs: any): Promise<any>
{
let args = [mArgs]
return this.call(model, 'name_get', args)
} /**
* Create a new record
* @param model Model name
* @param mArgs Object of fields and value
*/
public createRecord(model: string, mArgs: any)
{
let args = [mArgs];
return this.call(model, "create", args, null)
} /**
* Delete the record of particular ID
* @param model Model Name
* @param id Id of record that you want to delete
*/
public deleteRecord(model: string, id: number)
{
let mArgs = [id]
return this.call(model, "unlink", mArgs, null)
} /**
* Updates the record of particular ID
* @param model Model Name
* @param id Id of record that you want to update the.
* @param mArgs The Object of fields and value that you want to update
* (e.g)
* let args = {
* "name": "Mtfa"
* }
*/
public updateRecord(model: string, id: number, mArgs: any)
{
let args =
[
[id], mArgs
]
return this.call(model, "write", args, null)
} /**
* Get the User Context from the response of odoo server
*/
private getContext()
{
let response = localStorage.getItem("token");
let jsonData = JSON.parse(response);
let context = jsonData["user_context"];
return context;
}
}

通用类Utils.ts

import { Injectable } from "@angular/core";
import
{
AlertController, Loading,
LoadingController, Toast, ToastController,
ActionSheetController
} from "ionic-angular"; @Injectable()
export class Utils
{
private loading: Loading constructor(private alrtCtrl: AlertController,
private loadingCtrl: LoadingController,
private toastCtrl: ToastController,
private actionSheetCtrl: ActionSheetController)
{ } public presentAlert(title: string,
message: string,
buttons: [{}],
subtitle?: string,
enableBackdropDismiss?: boolean,
inputs?: [{}]): void
{ let alrt = this.alrtCtrl.create
({
title: title,
subTitle: subtitle,
message: message,
buttons: buttons,
enableBackdropDismiss: enableBackdropDismiss,
inputs: inputs
}) alrt.present()
} public presentToast(message: string, duration?: number,
dissmissOnPageChange?: boolean,
position?: string,
showCloseButton?: boolean,
closeButtonText?: string): void
{
let toast = this.toastCtrl.create
({
message: message,
position: position,
dismissOnPageChange: dissmissOnPageChange,
duration: duration,
showCloseButton: showCloseButton,
closeButtonText: closeButtonText
})
toast.present()
} public presentLoading(content: string, duration?: number,
dissmissOnPageChange?: boolean,
enableBackDropDismiss?: boolean,
showBackDrop?: boolean,
spinner?: string): void
{
this.loading = this.loadingCtrl.create
({
content: content,
dismissOnPageChange: dissmissOnPageChange,
duration: duration,
enableBackdropDismiss: enableBackDropDismiss,
showBackdrop: showBackDrop,
spinner: spinner
})
this.loading.present()
} public dismissLoading(): void
{
this.loading.dismiss()
} public presentActionSheet(buttons: [{}], title: string, subtitle?: string,
enableBackdropDismiss?: boolean): void
{
let actionCtrl = this.actionSheetCtrl.create
({
buttons: buttons,
subTitle: subtitle,
title: title,
enableBackdropDismiss: enableBackdropDismiss
})
actionCtrl.present()
}
}

ionic 访问odoo11之具体业务类api接口的更多相关文章

  1. 一次php访问sql server 2008的API接口的采坑

    2018年6月21日17:17:09,注意:不是详细文档,新手可能会看不懂 windows下安装 项目是sql server 2008的k3,php连接数据库写的API,因为是买的时候是别人的程序,测 ...

  2. ionic访问odoo 11接口

    在架设完毕odoo 11的网站之后,第一次面临手机app该如何访问后台网站的问题,是不是模式类似asp.net mvc 那样的模式,或者还存在其他的访问方法,带着这个疑问与困惑,开始的我的研究学习之路 ...

  3. Http下的各种操作类.WebApi系列~通过HttpClient来调用Web Api接口

    1.WebApi系列~通过HttpClient来调用Web Api接口 http://www.cnblogs.com/lori/p/4045413.html HttpClient使用详解(java版本 ...

  4. 熟练掌握HDFS的Java API接口访问

    HDFS设计的主要目的是对海量数据进行存储,也就是说在其上能够存储很大量文件(可以存储TB级的文件).HDFS将这些文件分割之后,存储在不同的DataNode上, HDFS 提供了两种访问接口:She ...

  5. Winform混合式开发框架访问Web API接口的处理

    在我的混合式开发框架里面,集成了WebAPI的访问,这种访问方式不仅可以实现简便的数据交换,而且可以在多种平台上进行接入,如Winform程序.Web网站.移动端APP等多种接入方式,Web API的 ...

  6. Java知多少(107)几个重要的java数据库访问类和接口

    编写访问数据库的Java程序还需要几个重要的类和接口. DriverManager类 DriverManager类处理驱动程序的加载和建立新数据库连接.DriverManager是java.sql包中 ...

  7. 如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问。

    由于 web api 项目通常是被做成了一个独立站点,来提供数据,在做web api 项目的时候,不免前端会遇到跨域访问接口的问题. 刚开始没做任何处理,用jsonp的方式调用 web api 接口, ...

  8. Asp.Net Web Api 接口,拥抱支持跨域访问。

    如何让你的 Asp.Net Web Api 接口,拥抱支持跨域访问. 由于 web api 项目通常是被做成了一个独立站点,来提供数据,在做web api 项目的时候,不免前端会遇到跨域访问接口的问题 ...

  9. Tomcat 配置 项目 到tomcat目录外面 和 域名绑定访问(api接口、前端网站、后台管理网站)

    先停止tomcat服务 1.进入apache-tomcat-7.0.68/conf/Catalina/localhost(如果之前还都没有启动过tomcat,是不会有此目录的,先启动一次再关闭,会自动 ...

随机推荐

  1. Power BI 与 Azure Analysis Services 的数据关联:3、还原备份文件到Azure Analysis Services

    Power BI 与 Azure  Analysis Services 的数据关联:3.还原备份文件到Azure  Analysis Services 配置存储设置 备份前,需要为服务器配置存储设置. ...

  2. FreeSSHD login with permission denied

    登录遇到问题: Permission denied, please try again. 解决方法: 在window中使用freesshd开启ssh后,客户端登陆时报 access denied错误 ...

  3. Expo大作战(三十一)--expo sdk api之Payments(expo中的支付),翻译这篇文章傻逼了,完全不符合国内用户,我只负责翻译大家可以略过!

    简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...

  4. The stacking context

    文档中的层叠上下文由满足以下任意一个条件的元素形成: 1. z-index 值不为 "auto"的 绝对/相对定位. 2. position位fixed. 3. opacity 属 ...

  5. LeetCode题解之 Find Mode in Binary Search Tree

    1.题目描述 2.问题分析 使用map记录元素出现的次数. 3.代码 vector<int> v; map<int,int> m; vector<int> find ...

  6. [Linux.NET]Nginx 泛解析配置请求映射到多端口实现二级域名访问

    由于想实现一个域名放置多个应用运行的目的,而不想通过域名后加端口号方式处理,这种方式处理记起来太麻烦,偷懒党简直不能忍,故而考虑了使用二级域名来处理多个应用同时运行.Google了一番资料并进行了尝试 ...

  7. python常用模块json

    python jons模块 json模块 主要是解决数据格式的转换问题,比如python接收到json对象需要转换为python对象,供python处理,亦或者python数据需要发送到其给其他客户端 ...

  8. rpm安装时出现循环依赖

    在安装git包时提示要安装perl-git,当安装perl-git时又提示要安装git包.报错如下: [root@racdb1 Packages]# rpm -ivh perl-Git-1.7.1-4 ...

  9. 7z常用命令行&7z检测压缩包完整性&7z压缩包错误不执行rsync同步

    7Z简介&常用命令 7Z脚本使用说明 7Z检测压缩包完整性脚本 7Z压缩包错误不执行Rsync脚本 1.7Z简介&常用命令 ⑴简介: 7z,全称7-Zip, 是一款开源软件.是目前公认 ...

  10. 安装.Net Framework 4.6.2时出现“无法建立到信任根颁发机构的证书链”解决方法

    在安装Microsoft .NET Framework 4.6.2脱机包时提示 无法建立到信任根颁发机构的证书链 实际上是要安装一个根证书.解决方案如下(因无法贴链接,可百度搜索“mamicode.c ...