前言
在我工作的日常中,經(jīng)常會(huì)用一些畫(huà)圖編輯器,簡(jiǎn)單設(shè)計(jì)一些頁(yè)面原型。而在去年低代碼很火的時(shí)候,我在公司就開(kāi)發(fā)了一款大屏可視化編輯器,可以通過(guò)拖拉拽生成網(wǎng)頁(yè)的一個(gè)工具。后面也想著自己也開(kāi)發(fā)一個(gè)畫(huà)圖的編輯器,可以用來(lái)自己平時(shí)做圖或者設(shè)計(jì)海報(bào)之類(lèi)的。而這次我將使用鴻蒙ArkTs來(lái)開(kāi)發(fā)這款海報(bào)編輯器APP,順便分享一下我這次的開(kāi)發(fā)經(jīng)驗(yàn)。
項(xiàng)目架構(gòu)與開(kāi)發(fā)流程
我這次項(xiàng)目功能架構(gòu)以及整體開(kāi)發(fā)流程如下:
項(xiàng)目功能結(jié)構(gòu)

整體開(kāi)發(fā)流程

這次開(kāi)發(fā)我使用了鴻蒙的端云一體化的開(kāi)發(fā)模式進(jìn)行整個(gè)項(xiàng)目的構(gòu)建。說(shuō)實(shí)話(huà):之前我都是自己寫(xiě)后端代碼,開(kāi)發(fā)流程確實(shí)比較繁瑣。而云開(kāi)發(fā)模式就很方便了,端側(cè)與云側(cè)同時(shí)開(kāi)發(fā),無(wú)需搭建服務(wù)器,工具成本低。這點(diǎn)我還是很喜歡的。
端云一體化工程講解
端云一體化的工程我也是第一次開(kāi)發(fā),相信很多伙伴也沒(méi)開(kāi)發(fā)過(guò)。我這次用的是官方提供的云模板工程,我大概給大家講解一下:

整體結(jié)構(gòu)很簡(jiǎn)單,使用起來(lái)也比較方便。所有的操作DevEco Studio開(kāi)發(fā)工具都集成了。
而在講解之前,使用云模板創(chuàng)建項(xiàng)目之前需要在華為開(kāi)發(fā)平臺(tái)創(chuàng)建項(xiàng)目,具體創(chuàng)建流程可以到官方文檔查看,地址我也放在下面:https://developer.harmonyos.com/cn/docs/documentation/doc-guides-V3/agc-harmonyos-clouddev-agcapp-0000001439436876-V3#section397317130308
注意:記得是創(chuàng)建項(xiàng)目哦,不是應(yīng)用。我一開(kāi)始就搞錯(cuò)了
創(chuàng)建表與方法
- 比如你要新建一張數(shù)據(jù)庫(kù)表,只需在
clouddb云數(shù)據(jù)庫(kù)入口文件點(diǎn)擊右鍵,點(diǎn)擊new,然后你選擇需要?jiǎng)?chuàng)建什么。
而我比較喜歡在開(kāi)發(fā)平臺(tái)創(chuàng)建,比較方便,傻瓜式操作。大家也可以看看官方文檔:https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-Guides/agc-clouddb-createfirstclouddb-0000001569588629
2.比如你要?jiǎng)?chuàng)建一個(gè)云函數(shù)方法,也是只需在cloudfuntion云函數(shù)入口文件點(diǎn)擊右鍵,點(diǎn)擊new,然后你直接創(chuàng)建一個(gè)對(duì)應(yīng)的云函數(shù)即可。

開(kāi)發(fā)函數(shù)與數(shù)據(jù)庫(kù)的使用
由于第一次使用云函數(shù)與云數(shù)據(jù)庫(kù),一路上磕磕碰碰。所以我打算將自己經(jīng)驗(yàn)都分享給大家,希望能幫助大家。
開(kāi)發(fā)云函數(shù)
在創(chuàng)建云函數(shù)之后,代碼結(jié)構(gòu)如下:

其中有一個(gè)ts文件,這個(gè)就是我們的函數(shù)入口了,其他的我們都暫時(shí)不用動(dòng)。這里我默認(rèn)的是nodejs開(kāi)發(fā)模式以及http請(qǐng)求模式。如果你們需要修改配置可以看一下官方文檔:https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-Guides/agc-cloud-function-start-from-here-0000001512489692
ts文件里面默認(rèn)有一個(gè)主入口方法:
let myHandler = async function (event, context, callback, logger) {
// 獲取你的參數(shù)
const body = event.body ? JSON.parse(event.body) : event
// 寫(xiě)你的業(yè)務(wù)代碼
callback({
code: 200,
data: [],
msg: '提示內(nèi)容'
});
};
export { myHandler };
- myHandler:入口方法名稱(chēng)。
- event:調(diào)用方傳遞的事件對(duì)象,JSON格式。具體內(nèi)容請(qǐng)參見(jiàn)event對(duì)象。
- context:函數(shù)運(yùn)行時(shí)上下文對(duì)象,封裝了日志接口、回調(diào)接口、環(huán)境變量env對(duì)象等。
- callback:事件處理結(jié)果。
- logger:記錄日志。
這里需要注意的是:獲取參數(shù)的方式,我在本地調(diào)試的時(shí)候,event就是參數(shù)對(duì)象了,但是發(fā)布到云服務(wù)器之后,端側(cè)傳遞的參數(shù)需要通過(guò)event.body來(lái)判斷是否存在,然后將數(shù)據(jù)JSON化。也不知道是不是我用的不對(duì),但是目前我是遇到這個(gè)問(wèn)題了。
接下來(lái)我講解一下云函數(shù)調(diào)用云數(shù)據(jù)庫(kù)與云存儲(chǔ)的相關(guān)步驟。詳細(xì)步驟如下:
云函數(shù)使用云數(shù)據(jù)庫(kù)
1. 云數(shù)據(jù)庫(kù)注冊(cè)認(rèn)證
在使用云數(shù)據(jù)庫(kù)的所有方法時(shí),都需要先注冊(cè)認(rèn)證哈
const path = require('path');
const clouddb = require('@hw-agconnect/database-server/dist/index.js')
const { AGCClient, CredentialParser } = require("@hw-agconnect/common-server");
const db_demo = require('./db/bd_demo') // 從開(kāi)發(fā)者平臺(tái)下載對(duì)應(yīng)的js配置文件,放在對(duì)應(yīng)的函數(shù)目錄根目錄下
// 加載憑證文件,憑證文件也是在開(kāi)發(fā)者平臺(tái)下載,具體看我的截圖
let client_name = "./db/agc-apiclient-chen.json";
let client_path = path.join(__dirname, client_name);
let credential = CredentialParser.toCredential(client_path);
AGCClient.initialize(credential, "clientCN", "CN");
let myHandler = async function (event, context, callback, logger) {
// xxxx
};
export { myHandler };
1.1 下載加載對(duì)象類(lèi)型文件
1.2 將上面下載的文件引入到云函數(shù)目錄中
1.3 下載憑證文件
2. 初始化云數(shù)據(jù)庫(kù)實(shí)例以及打開(kāi)存儲(chǔ)區(qū)
// 接著加載憑證文件的相關(guān)代碼下
const agcClient = AGCClient.getInstance("clientCN");
clouddb.AGConnectCloudDB.initialize(agcClient);
const agconnectCloudDB = clouddb.AGConnectCloudDB.getInstance(agcClient);
//云數(shù)據(jù)庫(kù)區(qū)塊,獲取方法看以下截圖
const zoneName = '區(qū)塊名稱(chēng)';
const cloudDBZoneConfig = new clouddb.CloudDBZoneConfig(zoneName);
const mCloudDBZone = agconnectCloudDB.openCloudDBZone(cloudDBZoneConfig);
2.1 獲取區(qū)塊名稱(chēng)
3. 使用云數(shù)據(jù)庫(kù)的方法
3.1 云數(shù)據(jù)庫(kù)-新增數(shù)據(jù)
需要注意的是:表名稱(chēng),直接寫(xiě)對(duì)應(yīng)的字符串名稱(chēng)就好
// 上面是注冊(cè)、加載憑證、打開(kāi)存儲(chǔ)區(qū)的代碼
let myHandler = async function (event, context, callback, logger) {
// 獲取你的參數(shù)
const body = event.body ? JSON.parse(event.body) : event
//表名稱(chēng)也是通過(guò)開(kāi)發(fā)者平臺(tái)獲取即可,字符串模式
const bookInfo = clouddb.CloudDBZoneGenericObject.build('表名稱(chēng)')
// 添加屬性對(duì)應(yīng)的數(shù)據(jù),按照自己定義的字段格式去賦值
bookInfo.addFieldValue('字段名稱(chēng)1', '數(shù)據(jù)')
bookInfo.addFieldValue('字段名稱(chēng)2', '數(shù)據(jù)')
// 同步插入表里
const resp = await mCloudDBZone.executeUpsert(bookInfo)
callback({
code: 200,
data: [],
msg: '提示內(nèi)容'
});
};
export { myHandler };
3.2 云數(shù)據(jù)庫(kù)-更新數(shù)據(jù)
需要注意的是:要先獲取表實(shí)例以及定位唯一鍵
const db_demo = require('./db/bd_demo')
// 上面是注冊(cè)、加載憑證、打開(kāi)存儲(chǔ)區(qū)的代碼
let myHandler = async function (event, context, callback, logger) {
// 獲取你的參數(shù)
const body = event.body ? JSON.parse(event.body) : event
// 引入表實(shí)例
const bookInfo = new db_demo.db_demo();
// 定位唯一鍵,目的找到對(duì)應(yīng)的數(shù)據(jù)
bookInfo.setId('主鍵數(shù)據(jù)值') // 主鍵字段,自己在創(chuàng)建數(shù)據(jù)庫(kù)的時(shí)候需要自定義主鍵
// 注冊(cè)
const operator = clouddb.CloudDBZoneObjectOperator.build(bookInfo)
operator.update('字段名稱(chēng)1', 數(shù)據(jù)) // 更新對(duì)應(yīng)字段數(shù)據(jù)
operator.update('字段名稱(chēng)2', 數(shù)據(jù)) // 更新對(duì)應(yīng)字段數(shù)據(jù)
operator.update('字段名稱(chēng)3', 數(shù)據(jù)) // 更新對(duì)應(yīng)字段數(shù)據(jù)
// ....
// 更新表里數(shù)據(jù)
const resp = await mCloudDBZone.executeUpdate(operator)
callback({
code: 200,
data: [],
msg: '提示內(nèi)容'
});
};
export { myHandler };
3.2 云數(shù)據(jù)庫(kù)-查詢(xún)數(shù)據(jù)
這里需要注意的是:查詢(xún)方式有很多,我這邊只用到很基礎(chǔ)的。想要更多操作可以看一下官網(wǎng):https://developer.huawei.com/consumer/cn/doc/AppGallery-connect-Guides/agc-clouddb-otheroperations-servernodejs-0000001569466329#section171182910246
const db_demo = require('./db/bd_demo')
// 上面是注冊(cè)、加載憑證、打開(kāi)存儲(chǔ)區(qū)的代碼
let myHandler = async function (event, context, callback, logger) {
// 獲取你的參數(shù)
const body = event.body ? JSON.parse(event.body) : event
// 初始化表
let cloudDBZoneQuery = clouddb.CloudDBZoneQuery.where(db_demo.db_demo)
// 查詢(xún)字段名稱(chēng)等于xxx的數(shù)據(jù)
const userCloudDBZoneQuery = cloudDBZoneQuery.equalTo('字段名稱(chēng)', 'xxx');
const respUser = await mCloudDBZone.executeQuery(userCloudDBZoneQuery);
const data = respUser.getSnapshotObjects()[0] // 獲取對(duì)應(yīng)數(shù)據(jù)
callback({
code: 200,
data: [],
msg: '提示內(nèi)容'
});
};
export { myHandler };
3.3 云數(shù)據(jù)庫(kù)-刪除數(shù)據(jù)
刪除相關(guān)的操作我還沒(méi)使用過(guò),等我使用之后再補(bǔ)充給大家
云函數(shù)使用云存儲(chǔ)
1. 云存儲(chǔ)注冊(cè)認(rèn)證
在使用云存儲(chǔ)的所有方法時(shí),也是都需要先注冊(cè)認(rèn)證哈
import {AGCClient, CredentialParser} from "@agconnect/common-server"
import {StorageManagement, Bucket, File, AGCCloudStorage} from "@agconnect/cloudstorage-server"
// 加載憑證文件
let client_name = "./db/agc-apiclient-chen.json";
let client_path = path.join(__dirname, client_name);
let credential = CredentialParser.toCredential(client_path);
AGCClient.initialize(credential, "clientDW");
let storage = AGCCloudStorage.getInstance("clientDW");
// name: 存儲(chǔ)實(shí)例名稱(chēng),獲取方式從開(kāi)發(fā)者平臺(tái)獲取
let bucket = storage.bucket('xxxx');
let myHandler = async function (event, context, callback, logger) {
// xxxx
};
export { myHandler };
1.1 獲取存儲(chǔ)實(shí)例名稱(chēng)

2. 使用云存儲(chǔ)的方法
2.1 上傳文件
需要注意的是:上傳文件需要注意destination的文件路徑規(guī)則。需要上傳的文件對(duì)應(yīng)的路徑則是本地路徑,文件在云函數(shù)的根目錄下,。后續(xù)我也會(huì)將怎么通過(guò)端側(cè)上傳圖片到云函數(shù)再上傳到云存儲(chǔ)的相關(guān)操作。
// 以上是認(rèn)證的相關(guān)代碼
let myHandler = async function (event, context, callback, logger) {
const options = {
destination: 'demo/demo.png', // 對(duì)應(yīng)云存儲(chǔ)中的文件路徑,demo文件夾需要自己在開(kāi)發(fā)者平臺(tái)創(chuàng)建,文件名稱(chēng)自定義,存在則覆蓋不存在則新增
onUploadProgress: (event) = > {}
};
bucket.upload('需要上傳的文件路徑,例如:./static/demo.png', options);
};
export { myHandler };
2.2 下載文件
// 以上是認(rèn)證的相關(guān)代碼
let myHandler = async function (event, context, callback, logger) {
const remoteFile = bucket.file(‘云存儲(chǔ)下的文件具體路徑’);
const localFile = '需要上傳的文件路徑,例如:./static/demo.png'
const directory = path.dirname(localFile);
// 判斷本地是否有當(dāng)前文件,有則創(chuàng)建
if (!fs.existsSync(directory)) {
fs.mkdirSync(directory, { recursive: true });
}
// 下載云存儲(chǔ)的文件內(nèi)容到對(duì)應(yīng)的本地文件
await remoteFile.createReadStream()
.on('error', (err) = > {})
.on('end', () = > {
// 業(yè)務(wù)代碼
})
.pipe(fs.createWriteStream(localFile));
};
export { myHandler };
總結(jié)
這次的鴻蒙端云一體化的開(kāi)發(fā)經(jīng)驗(yàn)就講解到這里,可能我講的不是很細(xì),因?yàn)橐彩堑谝淮问褂茫M梢詭椭蠹摇H绻厦婷枋龅挠袉?wèn)題,歡迎大家在評(píng)論區(qū)指出來(lái),謝謝。后面我們也會(huì)分享端側(cè)的開(kāi)發(fā)經(jīng)驗(yàn),以及會(huì)將對(duì)應(yīng)app上線(xiàn),到時(shí)候有相關(guān)技術(shù)討論的都可以找我們
審核編輯 黃宇
-
鴻蒙
+關(guān)注
關(guān)注
60文章
2991瀏覽量
46079
發(fā)布評(píng)論請(qǐng)先 登錄
中科創(chuàng)達(dá)攜手亞馬遜云科技推出端云一體化邊緣AI解決方案
廣汽集團(tuán)參與車(chē)路云一體化中外車(chē)企協(xié)同開(kāi)發(fā)測(cè)試
飛凌嵌入式ElfBoard-常用編輯器之Vim編輯器
潤(rùn)和軟件發(fā)布基于開(kāi)源歐拉的云邊端一體化智能物聯(lián)解決方案
解決方案 | 云管端一體化OTA HIL測(cè)試解決方案
一體化解決方案Jama Software,如何支持醫(yī)療設(shè)備開(kāi)發(fā)中的需求管理、風(fēng)險(xiǎn)管理與驗(yàn)證?
零碳園區(qū)建設(shè)的突破之路:安科瑞 “云邊端” 一體化解決方案
曠視科技與云舟智維合作打造裝備維修智能一體化平臺(tái)
HarmonyOS5云服務(wù)技術(shù)分享--云函數(shù)預(yù)加載文章整理
Vim編輯器的基本操作
電機(jī)群網(wǎng)絡(luò)管控一體化PLC-SCADA設(shè)計(jì)及應(yīng)用
整村開(kāi)發(fā)源網(wǎng)荷儲(chǔ)一體化:安科瑞打造鄉(xiāng)村零碳新范式
Linux下Vim編輯器的使用技巧
鴻蒙海報(bào)編輯器APP,分享端云一體化開(kāi)發(fā)的經(jīng)驗(yàn)!
評(píng)論