• 
    

    
    

      99热精品在线国产_美女午夜性视频免费_国产精品国产高清国产av_av欧美777_自拍偷自拍亚洲精品老妇_亚洲熟女精品中文字幕_www日本黄色视频网_国产精品野战在线观看

      ?

      基于華為appcube的口罩預(yù)約與配送系統(tǒng)的開發(fā)與設(shè)計

      2021-10-30 02:43張鼎仁任娟韓英夫
      科海故事博覽·中旬刊 2021年9期

      張鼎仁 任娟 韓英夫

      摘 要 隨著“互聯(lián)網(wǎng)+”的快速發(fā)展,用戶的需求也日益增加,敏捷開發(fā)、快速跟進(jìn)用戶需求變得更加重要。華為云appcube是華為自主研發(fā)的aPaaS服務(wù)平臺,開發(fā)者可以迅捷高效的整合自己的實際需求,集成云計算、大數(shù)據(jù)、視頻、人工智能、5G等多種新技術(shù)的平臺,將這些新技術(shù)以組件化的方式接入和融合至開發(fā)者數(shù)據(jù),本文以口罩預(yù)約與配送系統(tǒng)的開發(fā)與設(shè)計為例,通過華為appcube平臺快速開發(fā)構(gòu)建。最后總結(jié)分析本項目的成功經(jīng)驗,以及項目存在的不足和改進(jìn)措施。

      關(guān)鍵詞 appcube aPaaS JavaScript 預(yù)約配送

      中圖分類號:TN919 文獻(xiàn)標(biāo)識碼:A 文章編號:1007-0745(2021)09-0005-05

      1 緒論

      在新冠疫情影響下,口罩成為人們?nèi)粘I钪斜夭豢扇钡娜沼闷?,如何分配和調(diào)度口罩成為人們面臨的一項難題,即使是同一地區(qū),不同社區(qū)和鄉(xiāng)鎮(zhèn)也存在需求不均衡的現(xiàn)象,手動通過填報表格匯總統(tǒng)計,這項工作本身耗時耗力,不同地區(qū)的表格格式還可能不盡相同,更會影響發(fā)放口罩的效率。因此,亟需開發(fā)一個能快速適應(yīng)各種需求、能夠快速構(gòu)建的口罩預(yù)約與配送系統(tǒng),引入的華為appcube開發(fā)平臺可安裝行業(yè)服務(wù),平臺自身擁有豐富的工具集,它是支持在云上開發(fā)、測試、部署、運維的aPaaS平臺,針對不同水平的開發(fā)者,可采用對應(yīng)程度的開發(fā)模式,促進(jìn)了開發(fā)的高效應(yīng)用和實現(xiàn),降低了開發(fā)門檻。

      2 口罩預(yù)約與配送系統(tǒng)總體設(shè)計方案

      第一步,注冊登錄。開發(fā)者通過注冊華為開發(fā)者中心進(jìn)入應(yīng)用開發(fā);第二步,創(chuàng)建應(yīng)用。首先定義命名空間,創(chuàng)建APP及目錄并定義業(yè)務(wù)對象,之后組裝前端頁面,定義市政報表管理頁面,配置物業(yè)人員無需登錄即可預(yù)約和市政人員使用的菜單最后編譯發(fā)布應(yīng)用,其中組裝前端頁面包括定義市政人員管理頁面、定義市政人員修改頁面、定義物業(yè)人員預(yù)約頁面、定義“根據(jù)ID查詢”邏輯和定義“新增與編輯”邏輯;第三步,應(yīng)用獨立部署并對外開放。獨立部署后的應(yīng)用包括三個方面,分別是物業(yè)人員掃碼預(yù)約、市政人員管理信息和市政人員報表統(tǒng)計。

      3 口罩預(yù)約與配送系統(tǒng)詳細(xì)設(shè)計方案

      3.1 定義業(yè)務(wù)對象

      通過appcube創(chuàng)建app以及相應(yīng)目錄,app名稱為MaskMgtApp,開發(fā)者支持多種數(shù)據(jù)格式的字段,這樣就能靈活應(yīng)對各種用戶需求,同時平臺可以通過增刪改自定義對象,同時每個字段需要定義是否需要索引、是否必需、創(chuàng)建人、最后修改人、最后修改時間。

      對應(yīng)口罩預(yù)約的申請信息,我們同時需要自定義一個對象以表示預(yù)約信息,對象名稱為MaskMgtInfo,華為appcube會自動將這些信息寫入數(shù)據(jù)庫表結(jié)構(gòu),開發(fā)者無需再寫相關(guān)的數(shù)據(jù)庫增刪查改的接口,省去了大量數(shù)據(jù)交互的工作量,這種可視化建立表結(jié)構(gòu)的方法也為用戶更快的了解項目提供了基礎(chǔ)(口罩預(yù)約信息屬性表如表1所示)。

      3.2 組裝前端頁面

      3.2.1 定義“新增與編輯”邏輯

      //本腳本用于新增或者修改信息

      import * as db from ‘db;//導(dǎo)入處理object相關(guān)的標(biāo)準(zhǔn)庫

      import * as context from ‘context;//導(dǎo)入上下文相關(guān)的標(biāo)準(zhǔn)庫

      import * as date from ‘date;

      import * as buffer from ‘buffer;

      //定義入?yún)⒔Y(jié)構(gòu),入?yún)?個參數(shù):業(yè)務(wù)對象,為必填字段

      @action.object({ type: “param” })

      export class ActionInput {

      @action.param({ type: ‘Struct, required: true, label: ‘object })

      maskMgtInfo: object;

      }

      //定義出參結(jié)構(gòu),出參包含1個參數(shù),記錄業(yè)務(wù)對象的id

      @action.object({ type: “param” })

      export class ActionOutput {

      @action.param({ type: ‘String })

      maskMgtInfoId: string;

      }

      //使用數(shù)據(jù)對象lgj__maskMgtInfo__CST

      @useObject([‘lgj__MaskMgtInfo__CST])

      @action.object({ type: “method” })

      export class editMaskMgtInfo {? ? //定義接口類,接口的入?yún)锳ctionInput,出參為ActionOutput

      @action.method({ input: ‘ActionInput, output: ‘ActionOutput })

      public editMaskMgtInfo(input: ActionInput): ActionOutput {

      let out = new ActionOutput();? ? //新建出參ActionO utput類型的實例,作為返回值

      let error = new Error();? ? //新建錯誤類型的實例,用于在發(fā)生錯誤時保存錯誤信息

      try {

      let maskMgtInfo = input.maskMgtInfo;? ? //將入?yún)①x值給maskMgtInfo變量,方便后面使用

      let s = db.object(‘lgj__MaskMgtInfo__CST);? ? //獲取lgj__MaskMgtInfo__CST這個Object的操作實例

      //新增口罩預(yù)約信息

      if (!maskMgtInfo[‘id]) {

      //合法性效驗

      this.doValidate(input);

      this.checklegality(input);

      //根據(jù)預(yù)約小區(qū)名稱與聯(lián)系人手機號碼,查詢近8天內(nèi)是否有預(yù)約記錄,如果有預(yù)約記錄,則不允許再次預(yù)約

      let maskMgtInfosByCondition = s.queryByCondition({

      conjunction: db.Conjunction.AND,

      conditions: [

      { field: “l(fā)gj__expectArriveDate__CST”, operator: db.Operator.gt, value: date.format(date.now(), ‘yyyy-MM-dd, context.getTimeZone()) },

      { field: “l(fā)gj__residence__CST”, operator: db.Operator.eq, value: maskMgtInfo[‘lgj__residence__CST] },

      { field: “l(fā)gj__phoneNumber__CST”, operator: db.Operator.eq, value: maskMgtInfo[‘lgj__phoneNumber__CST] }]

      });

      console.log(“maskMgtInfosByCondition is: “ + JSON.stringify(maskMgtInfosByCondition));

      if ((maskMgtInfosByCondition || []).length) {

      let expectArriveday = maskMgtInfosByCondition[0].lgj__expectArriveDate__CST;

      //效驗8天后的日期

      let now = date.now();

      now.setDate(now.getDate() + 8);

      if (expectArriveday <= date.format(now, ‘yyyy-MM-dd, context.getTimeZone())) {

      error.name = “EM”;

      error.message = "您近8天內(nèi)有預(yù)約,不能再預(yù)約.";

      throw error;

      }

      }

      else {

      this.removeSpace(maskMgtInfo);

      let maskMgtInfoId = s.insert(maskMgtInfo);? ? //向lgj__MaskMgtInfo__CST插入一條數(shù)據(jù),返回數(shù)據(jù)的唯一標(biāo)識即口罩預(yù)約信息ID

      if (maskMgtInfoId && maskMgtInfoId != “”) {

      out.maskMgtInfoId = maskMgtInfoId;

      }

      else {

      error.name = “EM”;

      error.message = “maskMgtInfo Cannot Be Added.”;

      throw error;

      }

      }

      }

      //編輯修改口罩預(yù)約信息

      else {

      this.removeSpace(maskMgtInfo);

      let id = maskMgtInfo[‘id];

      delete maskMgtInfo[‘id];

      let count = s.update(id, maskMgtInfo);? ? //根據(jù)口罩預(yù)約信息ID,編輯更新lgj__maskMgtInfo__CST的一條數(shù)據(jù)

      if (count && count == 1) {

      out.maskMgtInfoId = id;

      }

      else {

      error.name = “EM”;

      error.message = “maskMgtInfo Cannot Be Updated.”;

      throw error;

      }

      }

      } catch (error) {

      console.error(error.name, error.message);

      context.setError(error.name, error.message);

      }

      return out;

      }

      //去除空格

      private removeSpace(maskMgtInfo) {

      //防止前后空格入庫

      maskMgtInfo[‘lgj__phoneNumber__CST] = maskMgtInfo[‘lgj__phoneNumber__CST].replace(/\s+/g, “”);

      maskMgtInfo[‘lgj__residence__CST] = maskMgtInfo[‘lgj__residence__CST].replace(/\s+/g, “”);

      maskMgtInfo[‘name] = maskMgtInfo[‘name].replace(/\s+/g, “”);

      if (maskMgtInfo[‘lgj__address__CST]) {

      maskMgtInfo[‘lgj__address__CST] = maskMgtInfo[‘lgj__address__CST].replace(/\s+/g, “”);

      }

      }

      //檢查具體的合法性

      private checklegality(input) {

      console.log(“checklegality”);

      let error = new Error();

      if (JSON.stringify(input.maskMgtInfo) == “{}”) {

      error.name = “EM”;

      error.message = “”;

      error.name = “EM”;

      error.message = "信息有誤";

      throw error;

      }

      console.log(input.maskMgtInfo[‘lgj__residence__CST]);

      //residence不能為空

      let residence = input.maskMgtInfo[‘lgj__residence__CST];

      if (!residence || residence.replace(/\s+/g, “”) == “”) {

      error.name = “EM”;

      error.message = "請?zhí)顚?預(yù)約小區(qū)名稱.";

      throw error;

      }

      if (/[~!@#$%^&*()/\|,.<>?”();:_+\-=\[\]{}a-zA-Z]/.test(residence.replace(/\s+/g, “”))) {

      error.name = “EM”;

      error.message = "請?zhí)顚?無特殊符號及數(shù)字與字母的小區(qū)名稱.";

      throw error;

      }

      console.log(input.maskMgtInfo[‘lgj__orderCount__CST]);

      //orderCount不能為空

      let orderCount = input.maskMgtInfo[‘lgj__orderCount__CST];

      if (!orderCount) {

      error.name = “EM”;

      error.message = "請?zhí)顚懣谡诸A(yù)約數(shù)量.";

      throw error;

      }

      let numberReg = /^([1-9][0-9]{0,2})$/;

      console.log(!numberReg.test(orderCount));

      if (!numberReg.test(orderCount) || orderCount > 500) {

      error.name = “EM”;

      error.message = "請正確填寫口罩預(yù)約數(shù)量,最多預(yù)約500個.";

      throw error;

      }

      //expectArriveDate不能為空

      let expectArriveDate = input.maskMgtInfo[‘lgj__expectArriveDate__CST];

      console.log(expectArriveDate);

      if (!expectArriveDate || expectArriveDate == “”) {

      error.name = “EM”;

      error.message = "請?zhí)顚懫谕竭_(dá)日期.";

      throw error;

      }

      //效驗3天后的日期

      let now = date.now();

      now.setDate(now.getDate() + 2);

      if (expectArriveDate <= date.format(now, ‘yyyy-MM-dd, context.getTimeZone())) {

      error.name = “EM”;

      error.message = "期望到貨日期,請至少填寫3天后日期.";

      throw error;

      }

      console.log(input.maskMgtInfo[‘lgj__phoneNumber__CST]);

      //phoneNumber不能為空

      let phoneNumber = input.maskMgtInfo[‘lgj__phoneNumber__CST];

      if (!phoneNumber || phoneNumber.replace(/\s+/g, “”) == “”) {

      error.name = “EM”;

      error.message = "請?zhí)顚懧?lián)系人手機號碼.";

      throw error;

      }

      //手機號碼合法

      let reg = /^1[3|4|5|7|8][0-9]{9}$/;

      console.log(reg.test(phoneNumber.replace(/\s+/g, “”)));

      if (!reg.test(phoneNumber.replace(/\s+/g, “”))) {

      error.name = “EM”;

      error.message = "請?zhí)顚懞戏ǖ穆?lián)系人手機號碼.";

      throw error;

      }

      console.log(input.maskMgtInfo[‘name]);

      //personName不能為空

      let personName = input.maskMgtInfo[‘name];

      if (!personName || personName.replace(/\s+/g, “”) == “”) {

      error.name = “EM”;

      error.message = "請?zhí)顚?聯(lián)系人姓名.";

      throw error;

      }

      if ((/[~!@#$%^&*()/\|,.<>?”();:_+-=\[\]{}0-9]/.test(personName.replace(/\s+/g, “”)))) {

      error.name = “EM”;

      error.message = "請?zhí)顚?無特殊符號的聯(lián)系人姓名.";

      throw error;

      }

      }

      //長度基礎(chǔ)效驗

      private doValidate(input) {

      console.log(“doValidate”);

      for (let property in input) {

      console.log(property);

      if (Array.isArray(input[property])) {

      console.log(‘a(chǎn)aa + input[property]);

      for (let tmp of input[property]) {

      this.doValidate(tmp);

      }

      } else {

      let buf = buffer.from(input[property] || ‘);

      console.log(‘bbb + input[property]);

      if (typeof (input[property]) == “string”) {

      console.log(‘ccc + input[property]);

      if (property != “url”) {

      if (buf.size() > 255) {

      context.throwError(‘請檢查--某個屬性是否填的長度>255, property);

      }

      }

      } else if (typeof (input[property]) == “object”) {

      console.log(‘ddd + input[property]);

      for (let i in input[property]) {

      buf = buffer.from(input[property][i] || ‘);

      if (i == “l(fā)gj__residence__CST”) {

      if (buf.size() > 64) {

      context.throwError(‘請檢查--預(yù)約小區(qū)名稱是否填的長度>64, i);

      }

      }

      else (i != “url” && i != “content”) {

      console.log(‘eee + buf);

      if (buf.size() > 255) {

      context.throwError(‘請檢查--某個屬性是否填的長度>255, i);

      }

      }

      }

      }

      }

      }

      }

      }

      Appcube平臺同時支持腳本驗證功能,可以通過編輯器測試新增邏輯能否正常執(zhí)行,測試的結(jié)果以json字符串格式顯示。同理,可以采用同樣的方法定義“根據(jù)Id查詢”邏輯,腳本名稱定義為queryMaskMgtDetail。

      腳本代碼如下所示:

      /*****************************

      * 本腳本用于按記錄ID查詢信息記錄

      * ***************************/

      import * as db from ‘db;//導(dǎo)入處理object相關(guān)的標(biāo)準(zhǔn)庫

      import * as context from ‘context;//導(dǎo)入上下文相關(guān)的標(biāo)準(zhǔn)庫

      //定義入?yún)⒔Y(jié)構(gòu)

      @action.object({ type: “param” })

      export class ActionInput {

      @action.param({ type: ‘String, required: true })

      maskMgtInfoId: string;//口罩預(yù)約ID

      }

      //定義出參結(jié)構(gòu)

      @action.object({ type: “param” })

      export class ActionOutput {

      @action.param({ type: ‘Struct, label: ‘object })

      maskMgtInfo: object;//口罩預(yù)約對象

      }

      @useObject([‘lgj__MaskMgtInfo__CST])//使用數(shù)據(jù)庫對象lgj__MaskMgtInfo__CST

      @action.object({ type: “method” })

      export class QueryMaskMgtInfoDetail {

      @action.method({ input: ‘ActionInput, output: ‘ActionOutput })

      public queryMaskMgtInfoDetail(input: ActionInput): ActionOutput {

      let out = new ActionOutput();? ? //新建出參ActionO utput類型的實例,作為返回值

      let error = new Error();? ? //新建錯誤類型的實例,用于在發(fā)生錯誤時保存錯誤信息

      try {

      //必填校驗

      if (!input.maskMgtInfoId || input.maskMgtInfoId == “”) {

      error.name = “TM”;

      error.message = "請傳入口罩預(yù)約記錄的Id.";

      throw error;

      }

      //獲取lgj__MaskMgtInfo__CST這個Object的操作實例

      let s = db.object(‘lgj__MaskMgtInfo__CST);

      //查詢字段(全部)

      let option = {};

      //查詢條件

      let condition = {

      “conjunction”: “AND”,

      “conditions”: [{

      “field”: “id”,

      “operator”: “eq”,

      “value”: input.maskMgtInfoId

      }]

      };

      //調(diào)用按條件查詢lgj__MaskMgtInfo__CST的接口

      let record = s.queryByCondition(condition, option);

      //如果查詢到數(shù)據(jù)

      if (record && record[0]) {

      //將結(jié)果掛入輸出對象中

      out.maskMgtInfo = record[0]

      }

      } catch (error) {

      console.error(error.name, error.message);

      context.setError(error.name, error.message);

      }

      return out;

      }

      }

      3.2.2 組裝頁面

      3.3 定義市政管理報表

      Appcube報表關(guān)聯(lián)的對象需要設(shè)置為“允許報表使用”,定義的報表分為按預(yù)約日統(tǒng)計各小區(qū)預(yù)約量報表和按期望到貨日統(tǒng)計各小區(qū)待配發(fā)量報表。同時,為了方便物業(yè)人員的使用,能夠?qū)⑷藗兊目谡中枨髷?shù)量及時快速統(tǒng)計,我們將申請設(shè)置為通過二維碼掃碼預(yù)約的形式免登陸登記。

      3.4 獨立部署并對外開放

      項目開發(fā)成功后,我們還可以導(dǎo)入對應(yīng)的資產(chǎn)包給其他用戶,以便其他用戶直接使用和測試該項目。這種軟件包式的管理方式大大提高了項目部署效率,免去了部署開發(fā)環(huán)境的重復(fù)操作,同時云端部署還省去了運維成本,提高了項目運行的穩(wěn)定性。

      4 結(jié)語

      本文主要介紹了基于華為appcube平臺開發(fā)的口罩預(yù)約與配送系統(tǒng),它可以滿足新冠疫情防控期間口罩需求的統(tǒng)計匯總的現(xiàn)實需求,解決了基層繁雜的表格填報難題,對其他行業(yè)的數(shù)據(jù)統(tǒng)計和匯總同樣具有借鑒意義,更加值得學(xué)習(xí)的地方是該aPaaS平臺云開發(fā)、云測試、云部署、云運維的特點。它不再依賴于復(fù)雜的現(xiàn)場網(wǎng)絡(luò)環(huán)境和硬件局限性,同時大大縮短了項目開發(fā)周期,提高了工作效率。同時在appcube平臺開發(fā)過程中也發(fā)現(xiàn)了一些問題,比如開發(fā)的舊模塊無法適配新版本的問題。在后續(xù)的學(xué)習(xí)和工作中,我將不斷充電學(xué)習(xí),開發(fā)具有高適配性、高安全性的口罩預(yù)約與配送系統(tǒng)。

      金平| 怀化市| 汕头市| 独山县| 台湾省| 海原县| 社会| 靖安县| 水富县| 北宁市| 合阳县| 平安县| 铜梁县| 沛县| 霍林郭勒市| 霍邱县| 郓城县| 十堰市| 桦南县| 芦山县| 剑河县| 友谊县| 平利县| 上高县| 高密市| 丽江市| 乌恰县| 鹤峰县| 漾濞| 始兴县| 平昌县| 香河县| 乌兰县| 鄢陵县| 江都市| 鄂伦春自治旗| 罗城| 黄石市| 长岭县| 苏尼特右旗| 交城县|