├── .gitignore ├── README.md ├── TODO.txt ├── config └── settings.table ├── default.aproj ├── dlg ├── goods_purchase.aardio ├── goods_purchase_history.aardio ├── goods_select.aardio ├── goods_sell.aardio ├── model_form.aardio ├── model_list.aardio ├── select_fields.aardio └── settings.aardio ├── lib ├── config.aardio └── sqlitemodel │ ├── _.aardio │ └── modelForm.aardio ├── main.aardio └── res ├── models ├── company.sql.aardio ├── goods_category.sql.aardio └── store.sql.aardio └── toolbar.gif /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | media 3 | *.pyc 4 | *.pui 5 | *.prj 6 | *.db 7 | log/*.* 8 | temp 9 | Thumbs.db 10 | test* -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sqlitemodel 2 | 3 | 给aardio封装了一个sqlite的增删改查的库 4 | 5 | item={ 6 | id=5; 7 | name="fadf"; 8 | code="fadf" 9 | } 10 | 11 | 12 | model.create(item) //创建一条数据 13 | model.get(item); //查询数据 14 | model.filter(item); //根据配置好的filter_fields过滤数据 15 | model.update(item); //根据id更新数据 16 | model.delete(item); //根据id删除数据 17 | model.search(item); //根据配置好的search_fields搜索数据 18 | 19 | 东西写了很久, 但是一直有各种错误 20 | 21 | 目标就是: 22 | 1. 增删改查少操心(console下可用) 23 | 2. 直接生成界面(增删改查的界面自动生成) 24 | 3. 和Excel互相批量导入导出 25 | 26 | 以上3个基本实现,还有待完善。 27 | -------------------------------------------------------------------------------- /TODO.txt: -------------------------------------------------------------------------------- 1 | 插入数据故障 2 | 3 | 1. 数据库太忙被锁定,导致复式记账法失败(应该插入4条,结果只有3条) -------------------------------------------------------------------------------- /config/settings.table: -------------------------------------------------------------------------------- 1 | { 2 | autoclose_model_form=0; 3 | rdConfirmDelete2=0; 4 | edit_dbpath="/data/biz.db"; 5 | edit_Orgs='行政部;\r\n销售部;\r\n后勤部;'; 6 | rdConfirmDelete1=1; 7 | dbpath="/data/biz.db"; 8 | confirm_delete=true; 9 | edit_companyname="快乐的公司" 10 | } -------------------------------------------------------------------------------- /default.aproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /dlg/goods_purchase.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import console; 3 | import time; 4 | import config; 5 | /*DSG{{*/ 6 | var winform = win.form(text="采购单(入库)";right=982;bottom=458) 7 | winform.add( 8 | button={cls="button";text="选择商品";left=798;top=7;right=976;bottom=65;dr=1;dt=1;z=8}; 9 | button2={cls="button";text="全部清空";left=892;top=99;right=976;bottom=130;dr=1;dt=1;z=9}; 10 | button3={cls="button";text="删除选中";left=892;top=150;right=976;bottom=181;dr=1;dt=1;z=10}; 11 | button5={cls="button";text="保存采购单";left=768;top=416;right=855;bottom=446;db=1;dr=1;z=14}; 12 | edit_applier={cls="edit";left=462;top=38;right=592;bottom=60;dl=1;dt=1;edge=1;z=13}; 13 | edit_from_store={cls="combobox";left=265;top=10;right=395;bottom=30;dl=1;dt=1;edge=1;items={};mode="dropdown";z=2}; 14 | edit_org={cls="combobox";left=265;top=40;right=392;bottom=61;dl=1;dt=1;edge=1;items={};mode="dropdown";z=15}; 15 | edit_ps_id={cls="edit";left=662;top=6;right=754;bottom=28;disabled=1;dl=1;dt=1;edge=1;readonly=1;z=18}; 16 | edit_subject={cls="edit";left=265;top=67;right=674;bottom=90;dl=1;dt=1;edge=1;z=6}; 17 | edit_to_store={cls="combobox";left=462;top=10;right=592;bottom=30;dl=1;dt=1;edge=1;items={};mode="dropdown";z=4}; 18 | listview={cls="listview";left=206;top=99;right=878;bottom=397;db=1;dl=1;dr=1;dt=1;edge=1;fullRow=1;gridLines=1;vscroll=1;z=7}; 19 | static={cls="static";text="供应商";left=205;top=9;right=260;bottom=29;dl=1;dt=1;transparent=1;z=1}; 20 | static2={cls="static";text="仓库";left=401;top=12;right=452;bottom=33;dl=1;dt=1;transparent=1;z=3}; 21 | static3={cls="static";text="备注";left=204;top=70;right=259;bottom=90;dl=1;dt=1;transparent=1;z=5}; 22 | static4={cls="static";text="部门处室";left=204;top=41;right=259;bottom=61;dl=1;dt=1;transparent=1;z=11}; 23 | static5={cls="static";text="申请人";left=401;top=40;right=452;bottom=60;dl=1;dt=1;transparent=1;z=12}; 24 | static6={cls="static";text="采购单";left=606;top=9;right=657;bottom=29;dl=1;dt=1;transparent=1;z=17}; 25 | treeview={cls="treeview";left=11;top=10;right=198;bottom=401;asel=false;bgcolor=16777215;dl=1;dt=1;edge=1;hscroll=1;vscroll=1;z=16} 26 | ) 27 | /*}}*/ 28 | 29 | // 30 | winform.user_define_fields= {} 31 | 32 | /*winform_reset_listview{{*/ 33 | winform.reset_listview = function(model, items, fields, clear_data=true){ 34 | 35 | if(#items == 0){ 36 | winform.listview.clear(); 37 | return 38 | } 39 | 40 | console.log("winform.listview.columnCount", winform.listview.columnCount) 41 | 42 | var display_fields; 43 | 44 | if(fields != null and type(fields) == "table" and #fields > 0 ){ 45 | display_fields = fields; 46 | }else { 47 | display_fields = model.display_fields; 48 | } 49 | 50 | var n = winform.listview.columnCount; 51 | var unmatched = false; 52 | if(n != 0){ 53 | //检测列标题是否匹配 54 | var captions = {}; 55 | for(i=1;n;1){ 56 | table.push(captions, winform.listview.getColumnText(i)) 57 | } 58 | 59 | for(i=1;#display_fields;1){ 60 | var k = display_fields[i] 61 | var caption = model.headers[k] 62 | if(caption==null){ 63 | caption = k; 64 | } 65 | if(table.find(captions, caption) == null){ 66 | console.log("列标题和user fields不匹配,不匹配的列为:", caption, table.tostring(captions)) 67 | unmatched = true 68 | } 69 | } 70 | } 71 | 72 | //如果不匹配, 直接重新建立新的列标题 73 | if(unmatched or n == 0){ 74 | //重新制作rebuild 75 | //unmatched, user_fields和现在的列标题不匹配 76 | //n==0, 是没有列标题, listview没有准备好, 77 | if(n==0){ 78 | console.log("没有设置列标题,重新设置") 79 | }else { 80 | console.log("unmatched, user_fields和现在的列标题不匹配") 81 | } 82 | 83 | 84 | last_items = {} //列标题不匹配,数据也没用了。 85 | winform.listview.clear(); 86 | 87 | for(i=1;n;1){ 88 | winform.listview.delColumn(n+1-i);//从倒数开始删除, 以免删除前面的, 后面的索引都变了. 89 | } 90 | 91 | for(i=1;#display_fields;1){ 92 | var k = display_fields[i] 93 | var caption = model.headers[k]; 94 | if(caption==null){ 95 | caption=k; 96 | } 97 | winform.listview.insertColumn(caption, 80, i); 98 | } 99 | 100 | n = winform.listview.columnCount; 101 | winform.listview.insertColumn("数量", 80, n+1); 102 | winform.listview.insertColumn("单价", 80, n+2); 103 | winform.listview.insertColumn("金额", 100, n+3); 104 | 105 | n = winform.listview.columnCount; 106 | if(n>=4){ 107 | winform.listview.setColumn({cx=40},1) 108 | winform.listview.setColumn({cx=70},2) 109 | winform.listview.setColumn({cx=180},3) 110 | winform.listview.setColumn({cx=80},4) 111 | } 112 | } 113 | 114 | //如果清空listview 115 | if(clear_data){ 116 | winform.listview.clear(); 117 | } 118 | 119 | //加入新数据 120 | for(i=1;#items;1){ 121 | var item = {}//每一行的数据 122 | for(j=1;#display_fields;1){ 123 | field = display_fields[j]; 124 | //if(k=="id"){ 125 | // table.push(data, tostring(i)) 126 | // continue 127 | //} 128 | var value = items[i][field]; 129 | if(value != null){ 130 | table.push(item, value) 131 | }else { 132 | table.push(item, "") 133 | } 134 | } 135 | 136 | //后面的3列数据,这里手动添加 137 | //table.push(item, items[i]["quantity"])// 138 | //table.push(item, items[i]["price"]) 139 | //table.push(item, items[i]["amount"]) 140 | 141 | 142 | var num = 1;//数量默认为1 143 | if(items[i]["quantity"] != null){ 144 | num = items[i]["quantity"]; 145 | } 146 | 147 | table.push(item, tostring(num)); 148 | 149 | if(items[i]["price"] != null){ 150 | table.push(item, tostring(items[i]["price"]));//单价 151 | table.push(item, tostring(num * items[i]["price"]));//金额 152 | }else { 153 | table.push(item, "0");//单价 154 | table.push(item, "0");//金额 155 | } 156 | 157 | 158 | winform.listview.addItem({ 159 | text = item; 160 | }); 161 | } 162 | 163 | 164 | } 165 | /*}}*/ 166 | 167 | 168 | winform.reset_from = function(){ 169 | winform.edit_ps_id.text = ""; 170 | winform.edit_ps_id.disabled = true; 171 | winform.edit_applier.text = ""; 172 | winform.edit_org.text = ""; 173 | winform.edit_subject.text = ""; 174 | winform.edit_to_store.text = ""; 175 | winform.edit_from_store.text = ""; 176 | winform.listview.clear(); 177 | } 178 | 179 | winform.button.oncommand = function(id,event){ 180 | var frmChild = winform.loadForm("\dlg\goods_select.aardio"); 181 | var goods_ids = frmChild.doModal(); 182 | 183 | //var sql = "select from ["+winform.+"]" 184 | var model = modGoods 185 | if(#goods_ids){ 186 | var sql = string.format("select * from [%s] where id in (%s)", model.tablename, string.join(goods_ids,",")) 187 | var items = model.getTable(sql); 188 | 189 | for(i=1;#items;1){ 190 | items[i]["goods_id"] = items[i]["id"]; 191 | items[i]["id"] = ""; 192 | } 193 | 194 | 195 | /* 196 | var user_define_fields = model.display_fields 197 | table.removeByValue(user_define_fields, "created_at") 198 | table.removeByValue(user_define_fields, "updated_at") 199 | */ 200 | 201 | var user_define_fields = {"id"; "goods_id";"name"; "unit"; "specs";} 202 | winform.reset_listview(model, items, user_define_fields, false) 203 | winform.user_define_fields = user_define_fields; 204 | } 205 | } 206 | 207 | 208 | 209 | 210 | winform.init = function(){ 211 | //调用mainForm中的全局变量 212 | var suppliers = table.map(modStore.filter({["cate"]="供应商"}),function(v,k,result){ 213 | if(type(k)== "number"){ 214 | table.push(result, string.format("%s|%s", v.id, v.name)) 215 | } 216 | }) 217 | 218 | var stores = table.map(modStore.filter({["cate"]="仓库"}),function(v,k,result){ 219 | if(type(k)== "number"){ 220 | table.push(result, string.format("%s|%s", v.id, v.name)) 221 | } 222 | }) 223 | 224 | 225 | for(i=1;#suppliers;1){ 226 | winform.edit_from_store.add(suppliers[i]) 227 | } 228 | 229 | for(i=1;#stores;1){ 230 | winform.edit_to_store.add(stores[i]) 231 | } 232 | 233 | 234 | var edit_Orgs = config.settings.edit_Orgs; 235 | 236 | if(edit_Orgs != null){ 237 | var items = string.split(edit_Orgs, "<;>") 238 | for(i=1;#items;1){ 239 | winform.edit_org.add(string.trim(items[i])) 240 | } 241 | 242 | } 243 | 244 | var purchases = modPurchase.search(); 245 | for(i=1;#purchases;1){ 246 | winform.treeview.insertItem({text = purchases[i].name; ps_id = purchases[i].id}) 247 | } 248 | 249 | } 250 | 251 | winform.edit_from_store.onEditChange = function(){ 252 | var text = winform.edit_from_store.text; 253 | var items = table.filter( winform.edit_from_store.items, lambda(v) string.startWith(v,text) ); 254 | if(string.trim(text) == ""){ 255 | items = table.map(modStore.filter({["cate"]="供应商"}),function(v,k,result){ 256 | if(type(k)== "number"){ 257 | table.push(result, string.format("%s|%s", v.id, v.name)) 258 | } 259 | }) 260 | } 261 | winform.edit_from_store.autoComplete(items); 262 | } 263 | 264 | winform.edit_to_store.onEditChange = function(){ 265 | var text = winform.edit_to_store.text; 266 | var items = table.filter( winform.edit_to_store.items, lambda(v) string.startWith(v,text) ); 267 | if(string.trim(text) == ""){ 268 | items = table.map(modStore.filter({["cate"]="仓库"}),function(v,k,result){ 269 | if(type(k)== "number"){ 270 | table.push(result, string.format("%s|%s", v.id, v.name)) 271 | } 272 | }) 273 | } 274 | winform.edit_to_store.autoComplete(items); 275 | } 276 | 277 | winform.button2.oncommand = function(id,event){ 278 | winform.listview.clear(); 279 | } 280 | 281 | 282 | winform.listview.onnotify = function(id,code,ptr){ 283 | if(code = 0xFFFFFFFE/*_NM_CLICK*/ ){ 284 | if(winform.listview.columnCount==0){ 285 | return 286 | } 287 | var nm = winform.listview.getNotifyMessage(code,ptr); 288 | if( ! nm.iItem && nm.iSubItem ) return true;//不允许编辑项 289 | 290 | //一点击就出现编辑框, 不用先点一下, 再点一下 291 | //winform.listview.editLabel(nm.iItem, nm.iSubItem); 292 | //上面这一行只能编辑第一列, 第2列和后面的都不能编辑, 看了源码,不行 293 | var nCols = winform.listview.columnCount; 294 | if(nm.iSubItem")[1]); 413 | 414 | item["cate_id"] = 0; 415 | item["cate_name"] = "采购入库"; 416 | 417 | item["trans_dir"] = "入库"; 418 | item["trans_type"] = 1; 419 | item["trans_id"] = 0; 420 | item["balance"] = 0; 421 | 422 | console.log("准备保存的数据item"); 423 | console.varDump(item) 424 | var from_id = modGoodsJournal.create(item); 425 | 426 | //对方那一条数据 427 | item["store_id"] = tonumber(string.split(pitem["from_store"], "<|>")[1]); 428 | 429 | item["cate_id"] = 0; 430 | item["cate_name"] = "销售出库"; 431 | 432 | item["trans_dir"] = "出库"; 433 | item["trans_type"] = 0; 434 | item["trans_id"] = 0; 435 | item["balance"] = 0; 436 | var to_id = modGoodsJournal.create(item); //double entry booking!!! 437 | 438 | var gtitem={} 439 | gtitem["goods_id"] = item["goods_id"]; 440 | gtitem["name"]=item["name"]; 441 | gtitem["quantity"]=item["quantity"]; 442 | gtitem["amount"]=item["amount"]; 443 | 444 | gtitem["from_store_id"]= tonumber(string.split(pitem["from_store"], "<|>")[1]); 445 | gtitem["from_store_name"]=string.split(pitem["from_store"], "<|>")[2]; 446 | gtitem["from_journal_id"]=from_id; 447 | 448 | gtitem["to_store_id"]=tonumber(string.split(pitem["to_store"], "<|>")[1]); 449 | gtitem["to_store_name"]=string.split(pitem["to_store"], "<|>")[2]; 450 | gtitem["to_journal_id"]=to_id; 451 | 452 | 453 | 454 | 455 | var gt_it = modGoodsTrans.create(gtitem); //创建转库的记录 456 | 457 | modGoodsPrice.create(item); //因为item中包含了modGoodsPrice需要的字段,所以不用改 458 | 459 | //计算库存 460 | var query = {} 461 | 462 | query["store_id"] = gtitem["from_store_id"] 463 | query["goods_id"] = item["goods_id"] 464 | query["trans_type"] = 1; 465 | 466 | var sql = "select sum(quantity) as sum_in from goods_journal 467 | where store_id=@store_id and goods_id =@goods_id and trans_type=@trans_type" 468 | var r = modGoodsJournal.exec(sql, query) 469 | console.log("入库数量:") 470 | console.varDump(r) 471 | 472 | var in_quantity = (r != null) ? r.sum_in : 0; 473 | console.log("in_quantity":tostring(in_quantity)) 474 | console.varDump(in_quantity) 475 | 476 | sql = "select sum(quantity) as sum_out from goods_journal 477 | where store_id=@store_id and goods_id =@goods_id and trans_type=@trans_type" 478 | query["trans_type"] = 0; 479 | r = modGoodsJournal.exec(sql, query) 480 | var out_quantity = (r != null) ? r.sum_out : 0; 481 | 482 | sql="select sum(amount) as sum_in from goods_journal 483 | where store_id=@store_id and goods_id =@goods_id and trans_type=@trans_type" 484 | query["trans_type"] = 1; 485 | r = modGoodsJournal.exec(sql, query) 486 | var in_amount = (r != null) ? r.sum_in : 0; 487 | 488 | sql = "select sum(amount) as sum_out from goods_journal 489 | where store_id=@store_id and goods_id =@goods_id and trans_type=@trans_type" 490 | query["trans_type"] = 0; 491 | r = modGoodsJournal.exec(sql, query) 492 | var out_amount = (r != null) ? r.sum_out : 0; 493 | 494 | query["in_quantity"] = in_quantity; 495 | query["out_quantity"] = out_quantity; 496 | query["balance"] = in_quantity - out_quantity; 497 | query["amount"] = in_amount - out_amount; 498 | query["name"] = item["name"]; 499 | 500 | modGoodsBalance.create(query) 501 | 502 | 503 | 504 | } 505 | winform.treeview.insertItem({text = pitem["name"];ps_id=ps_id}) 506 | winform.reset_from(); 507 | }else { 508 | console.log("----------------更新----------------------------------") 509 | ps_id = tonumber(ps_id) 510 | var tm = time.now(); 511 | var pitem = {}; 512 | 513 | pitem["name"] = tostring(tm, "采购单-%Y%m%d_%H%M%S", "chs"); 514 | pitem["org"] = winform.edit_org.text; 515 | pitem["applier"] = winform.edit_applier.text; 516 | pitem["supplier"] = winform.edit_from_store.text; 517 | pitem["subject"] = winform.edit_subject.text; 518 | pitem["store"] = winform.edit_to_store.text; 519 | pitem["id"] = ps_id; 520 | 521 | var updated = modPurchase.update(pitem); 522 | console.log("modPurchase update", updated) 523 | 524 | required_fields = { 525 | "supplier"; 526 | "store"; 527 | "org"; 528 | "applier"; 529 | "name"; 530 | } 531 | 532 | invalid = false; 533 | invalid_field = "" 534 | for(i=1;#required_fields;1){ 535 | if(pitem[required_fields[i]] == null or pitem[required_fields[i]] == ""){ 536 | invalid = true; 537 | invalid_field = required_fields[i]; 538 | break; 539 | } 540 | 541 | } 542 | 543 | if(invalid){ 544 | winform.msgbox(string.format("%s不能为空!", invalid_field)); 545 | return ; 546 | } 547 | 548 | 549 | for(i=1;winform.listview.count;1){ 550 | var item = {}; 551 | //winform.user_define_fields 552 | for(j=1;#winform.user_define_fields;1){ 553 | var field = winform.user_define_fields[j] 554 | item[field] = winform.listview.getItemText(i,table.find(winform.user_define_fields, field)) 555 | console.log("field", field, item[field]) 556 | } 557 | //item["goods_id"] = tonumber(item["id"]); 558 | //item["id"] = null; 559 | 560 | n = winform.listview.columnCount; 561 | item["quantity"] = winform.listview.getItemText(i,n-2) 562 | item["price"] = winform.listview.getItemText(i,n-1) 563 | item["amount"] = winform.listview.getItemText(i,n) 564 | 565 | item["price"] = tonumber(item["price"]); 566 | item["quantity"] = tonumber(item["quantity"]); 567 | 568 | item["amount"] = item["price"] * item["quantity"] 569 | 570 | item["ps_id"] = tonumber(ps_id); 571 | 572 | item["store_id"] = tonumber(string.split(pitem["store"], "<|>")[1]); 573 | 574 | item["cate_id"] = 0; 575 | item["cate_name"] = "采购入库"; 576 | 577 | item["trans_dir"] = "入库"; 578 | item["trans_type"] = 1; 579 | item["trans_id"] = 0; 580 | item["balance"] = 0; 581 | 582 | console.log("准备更新的数据item"); 583 | console.varDump(item) 584 | if(item["id"]=="" or item["id"]== null){ 585 | modGoodsJournal.create(item); 586 | modGoodsPrice.create(item); //只新建价格 587 | }else { 588 | modGoodsJournal.update(item); 589 | var priceitem = item; 590 | priceitem["id"] = null; 591 | modGoodsPrice.create(priceitem);//只新建价格 592 | } 593 | console.log("----------------------更新完毕-----------------------"); 594 | } 595 | } 596 | 597 | } 598 | 599 | winform.delete_purchase = function(ps_id){ 600 | var pitem = modPurchase.get({id=ps_id}); 601 | var goods = modPurchaseGoods.filter({filter_field="purchase_id";keyword=ps_id}); 602 | for(i=1;#goods;1){ 603 | modPurchaseGoods.delete({id = goods[i].id}) 604 | } 605 | modPurchase.delete({id=ps_id}); 606 | } 607 | 608 | 609 | winform.treeview.onnotify = function(id,code,ptr){ 610 | select(code) { 611 | case 0xFFFFFFFE/*_NM_CLICK*/ { 612 | var hi = winform.treeview.hitTest(); 613 | if(hi){ 614 | winform.listview.clear(); 615 | var data = winform.treeview.getItemData(hi); 616 | var ps_id = data["ps_id"]; 617 | if(ps_id){ 618 | var pitem = modPurchase.get({id=ps_id}); 619 | var items = modGoodsJournal.filter({["ps_id"]=ps_id;["trans_type"] = 1}) 620 | console.log("pitem") 621 | console.varDump(pitem) 622 | console.log("goods[1]") 623 | console.varDump(items[1]) 624 | 625 | winform.edit_org.text = pitem["org"]; 626 | winform.edit_applier.text = pitem["applier"]; 627 | winform.edit_subject.text = pitem["subject"]; 628 | winform.edit_from_store.text = pitem["from_store"]; 629 | winform.edit_to_store.text = pitem["to_store"]; 630 | //取消winform.edit_ps_id禁用 631 | winform.edit_ps_id.disabled = false; 632 | winform.edit_ps_id.text = tostring(ps_id); 633 | 634 | winform.reset_listview(modGoods, items, winform.user_define_fields, false) 635 | } 636 | 637 | }else{ 638 | winform.reset_from(); 639 | } 640 | 641 | 642 | 643 | 644 | } 645 | case 0xFFFFFFFB/*_NM_RCLICK*/{ 646 | //右键菜单 647 | var x,y = mouse.getPos(); 648 | var hi = winform.treeview.hitTest(); 649 | 650 | var iRow, iCol = winform.listview.hitTest(x,y,true); 651 | if(iRow){ 652 | winform.listview.setSelected(iRow) 653 | winform.lastListviewSelected = iRow; 654 | } 655 | 656 | var menu = win.ui.popmenu(winform) 657 | 658 | menu.add("删除", 659 | function(){ 660 | if(winform.msgboxTest("确认删除采购单吗?"++'\r\n\r\n'++"确认将会同时删除采购单中的商品记录")){ 661 | var data = winform.treeview.getItemData(hi); 662 | var ps_id = data["ps_id"]; 663 | if(ps_id){ 664 | winform.delete_purchase(ps_id) 665 | winform.treeview.delItem(hi); 666 | winform.reset_from(); 667 | } 668 | } 669 | 670 | } 671 | ); 672 | 673 | menu.popup(x,y,true); 674 | } 675 | else { 676 | } 677 | } 678 | } 679 | 680 | 681 | winform.init(); 682 | winform.show(); 683 | win.loopMessage(); 684 | return winform; -------------------------------------------------------------------------------- /dlg/goods_purchase_history.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import win.ui.statusbar; 3 | import config; 4 | import console; 5 | import sqlitemodel.modelForm; 6 | /*DSG{{*/ 7 | var winform = win.form(text="数据列表";right=948;bottom=601;border="dialog frame";mode="popup";parent=...) 8 | winform.add( 9 | btnGotoNPage={cls="button";text="转到第N页";left=650;top=353;right=724;bottom=374;db=1;dl=1;z=10}; 10 | btnNext={cls="button";text="下一页";left=385;top=353;right=450;bottom=374;db=1;dl=1;z=8}; 11 | btnPrev={cls="button";text="上一页";left=305;top=353;right=370;bottom=374;db=1;dl=1;z=7}; 12 | button={cls="button";text="搜索";left=409;top=28;right=473;bottom=52;dl=1;dt=1;z=4}; 13 | button2={cls="button";text="Button";left=740;top=352;right=811;bottom=374;db=1;dr=1;z=13}; 14 | button3={cls="button";text="添加";left=52;top=28;right=127;bottom=51;z=15}; 15 | button4={cls="button";text="批量导入";left=696;top=30;right=777;bottom=53;z=16}; 16 | button6={cls="button";text="刷新";left=476;top=28;right=540;bottom=52;dl=1;dt=1;z=11}; 17 | button7={cls="button";text="选择显示字段";left=551;top=28;right=648;bottom=52;dl=1;dt=1;z=12}; 18 | comboCurrPage={cls="combobox";left=562;top=353;right=643;bottom=374;db=1;dl=1;edge=1;items={};mode="dropdown";z=9}; 19 | comboItemsPerpage={cls="combobox";left=215;top=354;right=293;bottom=374;db=1;dl=1;edge=1;items={"10";"20";"50";"100"};mode="dropdown";z=5}; 20 | edit={cls="edit";left=168;top=29;right=397;bottom=53;dl=1;dt=1;edge=1;z=14}; 21 | listbox={cls="listbox";left=161;top=377;right=941;bottom=578;db=1;dl=1;dr=1;edge=1;hscroll=1;items={};vscroll=1;z=2}; 22 | listview={cls="listview";left=162;top=56;right=934;bottom=346;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(name='Consolas');fullRow=1;gridLines=1;hscroll=1;vscroll=1;z=3}; 23 | static={cls="static";text="每页条数";left=160;top=354;right=211;bottom=369;db=1;dl=1;transparent=1;z=6}; 24 | treeview={cls="treeview";left=5;top=56;right=156;bottom=578;asel=false;bgcolor=16777215;db=1;dl=1;dt=1;edge=1;vscroll=1;z=1} 25 | ) 26 | /*}}*/ 27 | 28 | //// 29 | ////////////////////////////// 30 | ////全局变量 31 | winform.model = null; 32 | winform.lastListviewSelected = 0; 33 | 34 | is_form_valid = function(){ 35 | if( #winform.edit_title.text 36 | && #winform.edit_account.text 37 | && #winform.edit_pass.text) 38 | { 39 | return true; 40 | }else { 41 | winform.msgboxErr("title,account and password is requried","Err") 42 | } 43 | return false; 44 | } 45 | 46 | initTreeview = function(model, tv){ 47 | 48 | var filter_fields = model.filter_fields; 49 | if(#filter_fields>0){ 50 | tv.clear(); 51 | } 52 | 53 | var item = {text = "显示全部数据"} 54 | var hItem = tv.insertItem(item) 55 | 56 | for(i=1;#filter_fields;1){ 57 | var item = {} 58 | /*{ 59 | text = "按区划分"; 60 | { 61 | { text = "芙蓉区" }; 62 | { text = "天心区" }; 63 | { text = "岳麓区" }; 64 | { text = "开福区" }; 65 | { text = "雨花区" }; 66 | { text = "未分区" }; 67 | } 68 | }*/ 69 | 70 | 71 | 72 | var k = filter_fields[i] 73 | var caption = model.headers[k] 74 | 75 | console.varDump(model.headers) 76 | console.log("caption, k",caption, k) 77 | 78 | item["text"] = string.format("按%s过滤", caption); 79 | //query["filter_field"] = k 80 | 81 | var sql = string.format("select distinct %s from %s", k, model.tablename) 82 | var items = model.getTable(sql) 83 | 84 | var data = {} 85 | for(i=1;#items;1){ 86 | table.push(data, {text = items[i][k]; filter_field = k}) 87 | } 88 | 89 | table.push(item, data) 90 | 91 | var hItem = tv.insertItem(item) 92 | 93 | } 94 | 95 | tv.expandAll() 96 | 97 | 98 | } 99 | 100 | winform.button.oncommand = function(id,event){ 101 | 102 | if(winform.model == null){ 103 | winform.msgbox("窗口未设置model对象, 无法正确显示数据") 104 | } 105 | 106 | keyword = winform.edit.text; 107 | winform.load_data(keyword) 108 | 109 | } 110 | 111 | 112 | 113 | winform.load_data = function(keyword=""){ 114 | var items={}; 115 | var query = {}; 116 | if(type(keyword)=="table"){ 117 | query = keyword 118 | }elseif(type(keyword)=="string"){ 119 | query["keyword"] = keyword; 120 | } 121 | query["QUERY_MODE"] = "SEARCH"; 122 | 123 | 124 | 125 | CURR_QUERY = query; //记录到全局变量CURR_QUERY中 126 | //log(table.tostring(CURR_QUERY)); 127 | items = winform.model.search(query); 128 | 129 | winform.resetlistview(items) 130 | 131 | 132 | } 133 | 134 | 135 | 136 | winform.resetlistview = function(items){ 137 | winform.statusbar.setText("公司总数:" + #items); 138 | 139 | 140 | if(#items){ 141 | winform.listview.clear(); 142 | }else { 143 | winform.listview.clear(); 144 | } 145 | 146 | 147 | //for(i=1;#items;1){ 148 | // console.varDump(items[i]) 149 | //} 150 | 151 | 152 | //如果获取了数据, 那么清空listview 153 | var n = winform.listview.columnCount; 154 | for(i=1;winform.listview.columnCount;1){ 155 | winform.listview.delColumn(n+1-i); 156 | } 157 | 158 | var display_fields = winform.model.display_fields; 159 | for(i=1;#display_fields;1){ 160 | var k = display_fields[i] 161 | var caption = winform.model.headers[k] 162 | winform.listview.insertColumn(caption, 140, i); 163 | } 164 | 165 | winform.listview.setColumn({cx=30},1) 166 | winform.listview.setColumn({cx=180},2) 167 | winform.listview.setColumn({cx=80},3) 168 | 169 | 170 | 171 | for(i=1;#items;1){ 172 | //winform.listview.add(items[i]['title']); 173 | //console.log("query[i]") 174 | //console.varDump(items[i]) 175 | 176 | var row ={} 177 | for(j=1;#display_fields;1){ 178 | k = display_fields[j]; 179 | //if(k=="id"){ 180 | // table.push(data, tostring(i)) 181 | // continue 182 | //} 183 | //console.log('k', k); 184 | if(items[i][k]!=null){ 185 | table.push(row, items[i][k]) 186 | }else { 187 | table.push(row, "") 188 | } 189 | 190 | 191 | } 192 | // 193 | //console.varDump(items[i]) 194 | // 195 | 196 | winform.listview.addItem({ 197 | text = row 198 | }); 199 | } 200 | 201 | if(items["ITEMS_PERPAGE"]){ 202 | winform.comboItemsPerpage.text = tostring(items["ITEMS_PERPAGE"]) 203 | } 204 | if(items["PAGES"]){ 205 | winform.comboCurrPage.clear(); 206 | for(i=1;items["PAGES"];1){ 207 | winform.comboCurrPage.add(tostring(i)) 208 | } 209 | } 210 | if(items["CURR_PAGE"]!=null){ 211 | winform.comboCurrPage.text = tostring(items["CURR_PAGE"]+1) 212 | } 213 | } 214 | 215 | 216 | winform.init = function(model){ 217 | 218 | //winform.center() 219 | winform.model = model; 220 | 221 | var state = config.settings.autoclose_company_form; 222 | // 223 | //console.log(" config autoclose_company_form " ++ state) 224 | // 225 | 226 | if(state == null){ 227 | state = false; 228 | config.saveAll() 229 | } 230 | // 231 | //console.log(" started " ++ state) 232 | // 233 | win.ui.statusbar( winform ).addItem("公司:", 100/*宽度*/) 234 | 235 | winform.statusbar.addItem("数据库:", 500); 236 | 237 | initTreeview(winform.model, winform.treeview) 238 | 239 | winform.load_data(winform.model) 240 | } 241 | 242 | winform.button7.oncommand = function(id,event){ 243 | 244 | } 245 | 246 | winform.treeview.onnotify = function(id,code,ptr){ 247 | if(code = 0xFFFFFFFE/*_NM_CLICK*/){ 248 | //单击 249 | var x,y = mouse.getPos() 250 | var hItem,tvht = winform.treeview.hitTest(x,y,true); 251 | 252 | if(!hItem){ 253 | return 254 | } 255 | 256 | winform.treeview.setSelected(hItem); 257 | winform.treeview.expandAll() 258 | 259 | var hitem = winform.treeview.getSelection() 260 | //winform.text = winform.treeview.getItemData(hitem); 261 | var data = winform.treeview.getItemData(hitem); 262 | 263 | var filter_field = data["filter_field"]; 264 | //if(filter_field == null){ 265 | // return 266 | //} 267 | 268 | var keyword = ""; 269 | 270 | if(data == null or #data>0){ 271 | //未选中节点, 或者选中节点有子节点(根节点) 272 | keyword = "" 273 | //return 274 | }else { 275 | //没有子节点的节点,如果是根节点, 那么也是在这里处理, 但是没有filter_field数据, 所以后面的filter 276 | // 会因为没有filter_field数据, 而返回全部数据, 忽略keyword 277 | keyword = data["text"]; 278 | if(string.indexOf(keyword, "|")){ 279 | keyword = string.split(keyword, "<|>")[1] 280 | } 281 | //winform.text = data["text"] ++ " 单位"; 282 | } 283 | 284 | var query = {}; 285 | query["filter_field"] = filter_field; 286 | query["keyword"] = keyword; 287 | var items_perpage = tonumber(winform.comboItemsPerpage.text); 288 | query["ITEMS_PERPAGE"] = items_perpage 289 | query["QUERY_MODE"] = "FILTER"; 290 | 291 | CURR_QUERY = query; 292 | log(table.tostring(CURR_QUERY)); 293 | 294 | var items = winform.model.filter(query) 295 | 296 | reset_listview(items) 297 | 298 | } 299 | } 300 | 301 | 302 | winform.item_detail = function(id){ 303 | var mform = sqlitemodel.modelForm(winform.model, winform, id); 304 | mform.doModal(winform); 305 | winform.load_data(winform.model) 306 | } 307 | 308 | winform.delete_item = function(){ 309 | var iRow = winform.listview.getSelection(); 310 | console.log('irow',iRow) 311 | 312 | if(!iRow){ 313 | return 314 | } 315 | 316 | var query = {} 317 | console.log(table.tostring(winform.model.display_fields)) 318 | for(i=1;#winform.model.display_fields;1){ 319 | k = winform.model.display_fields[i] 320 | query[k] = winform.listview.getItemText(iRow, i) 321 | } 322 | 323 | var confirmed = false; //默认不删除 324 | if(config.settings.confirm_delete){ 325 | confirmed = winform.msgboxTest("确认删除吗?"); //看用户选择 326 | }else { 327 | confirmed = true; //无需确认 328 | } 329 | 330 | console.log("confirmed",confirmed, winform.model.tablename) 331 | if(confirmed){ 332 | console.log(table.tostring(query)) 333 | var deleted = winform.model.delete(query); 334 | //initTreeviewFilters(modCompany); 335 | if(deleted){ 336 | winform.load_data(); 337 | winform.msgbox("删除成功!") 338 | }else { 339 | winform.msgbox("删除失败!") 340 | } 341 | 342 | 343 | } 344 | } 345 | 346 | 347 | 348 | winform.listview.onnotify = function(id,code,ptr){ 349 | 350 | select(code) { 351 | 352 | case 0xFFFFFFFD/*_NM_DBLCLK*/ { 353 | //双击编辑 354 | var x,y = mouse.getPos() 355 | var iRow, iCol = winform.listview.hitTest(x,y,true); 356 | if(iRow){ 357 | winform.listview.setSelected(iRow) 358 | winform.lastListviewSelected = iRow; 359 | winform.item_detail(iRow) 360 | } 361 | 362 | } 363 | case 0xFFFFFFFB/*_NM_RCLICK*/ { 364 | //右键菜单 365 | var x,y = mouse.getPos() 366 | var iRow, iCol = winform.listview.hitTest(x,y,true); 367 | if(iRow){ 368 | winform.listview.setSelected(iRow) 369 | winform.lastListviewSelected = iRow; 370 | } 371 | 372 | var menu = win.ui.popmenu(winform) 373 | 374 | menu.add("详细信息", 375 | function(){ 376 | menu_company_detailinfo() 377 | } 378 | ); 379 | 380 | 381 | var filter_fields = modCompany.filter_fields 382 | 383 | var filter_menus = {} 384 | 385 | 386 | 387 | for(i=1;#filter_fields;1){ 388 | var item = {} 389 | 390 | var k = filter_fields[i] 391 | var caption = headers[k] 392 | 393 | table.push(item, string.format("更改选中项的%s为", caption)) 394 | var sql = string.format("select distinct %s from %s", k, modCompany.tablename) 395 | var items = modCompany.getTable(sql) 396 | 397 | console.varDump(items) 398 | 399 | var data = {} 400 | for(i=1;#items;1){ 401 | console.log("items[i][k]", items[i][k]); 402 | var x = { 403 | tostring(items[i][k]); //tostring() 避免 USTRING ERROR 404 | function(id){ 405 | //winform.msgbox(tostring(items[i][k])) 406 | change_company_field(k,items[i][k]); 407 | } 408 | } 409 | console.log(" console.varDump(x)") 410 | console.varDump(x) 411 | table.push(data, x) 412 | } 413 | 414 | if(#data){ 415 | console.log("console.varDump(data)") 416 | console.varDump(data) 417 | table.push(item, data) 418 | }else { 419 | continue; 420 | } 421 | 422 | console.log("continue;") 423 | 424 | console.varDump(item) 425 | table.push(filter_menus, item) 426 | } 427 | 428 | //console.varDump(filter_menus) 429 | if(#filter_menus){ 430 | menu.addTable( 431 | //{filter_menus} 432 | filter_menus 433 | ) 434 | } 435 | 436 | menu.add({}); 437 | 438 | menu.add("全选", 439 | function(){ 440 | for(i=1;winform.listview.count;1){ 441 | winform.listview.setSelected(i) 442 | } 443 | } 444 | ); 445 | 446 | 447 | 448 | menu.add("导出选中项数据", 449 | function(){ 450 | var items = {} 451 | //console.log(winform.listview.columnCount) 452 | var ids = {} 453 | for(i=1;winform.listview.count;1){ 454 | 455 | if(winform.listview.getSelected(i)){ 456 | table.push(ids, winform.listview.getItemText(i,1)); //每一行的第1列就是id 457 | } 458 | } 459 | if(#ids){ 460 | var TABLE_NAME = winform.model.tablename; 461 | var sql = "SELECT * FROM [" ++ TABLE_NAME ++ "] where id in (" + string.join(ids, ", ") + ")" 462 | items = winform.model.getTable(sql); 463 | export_model(winform.model, items); 464 | } 465 | 466 | } 467 | ); 468 | 469 | 470 | menu.add({}); 471 | 472 | 473 | menu.add("修改", 474 | function(){ 475 | menu_edit_commpany() 476 | } 477 | ); 478 | menu.add({}); 479 | 480 | menu.add("删除", 481 | function(){ 482 | console.log("删除") 483 | winform.delete_item() 484 | } 485 | ); 486 | //menu.add("调换班级", 487 | /// function(){ 488 | // 489 | // } 490 | //); 491 | menu.popup(x,y,true); 492 | 493 | } 494 | else { 495 | } 496 | } 497 | } 498 | 499 | winform.button3.oncommand = function(id,event){ 500 | var mform = sqlitemodel.modelForm(winform.model, winform); 501 | mform.text = string.format("添加%s数据", winform.model.label ) 502 | mform.doModal(); 503 | 504 | winform.load_data(winform.model) 505 | } 506 | 507 | winform.button6.oncommand = function(id,event){ 508 | winform.load_data() 509 | } 510 | 511 | //winform.init(); 512 | 513 | winform.button4.oncommand = function(id,event){ 514 | var filepath = fsys.dlg.open("Excel文件(*.xsl;*xlsx)|*.xsl;*xlsx","请选择Excel文件",,winform) 515 | if(filepath){ 516 | import_model(winform.model, filepath); 517 | } 518 | } 519 | 520 | winform.enableDpiScaling(); 521 | winform.show(); 522 | 523 | win.loopMessage(); 524 | return winform; -------------------------------------------------------------------------------- /dlg/goods_select.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import math; 3 | import fsys.dlg; 4 | import config; 5 | import console; 6 | import sqlitemodel.modelForm; 7 | /*DSG{{*/ 8 | var winform = win.form(text="选择商品";right=390;bottom=331) 9 | winform.add( 10 | button={cls="button";text="搜索";left=138;top=7;right=188;bottom=33;z=6}; 11 | button5={cls="button";text="确定";left=275;top=292;right=374;bottom=324;z=2}; 12 | button8={cls="button";text="新增商品";left=313;top=8;right=376;bottom=30;z=3}; 13 | edit={cls="edit";left=52;top=8;right=117;bottom=32;edge=1;z=5}; 14 | listview={cls="listview";left=12;top=42;right=379;bottom=284;edge=1;fullRow=1;gridLines=1;vscroll=1;z=4}; 15 | static={cls="static";text="名称";left=13;top=10;right=65;bottom=29;transparent=1;z=1} 16 | ) 17 | /*}}*/ 18 | 19 | winform.button5.oncommand = function(id,event){ 20 | 21 | var ids = {}; 22 | 23 | for(i=1;winform.listview.count;1){ 24 | if(winform.listview.getChecked(i)){ 25 | table.push(ids, winform.listview.getItemText(i)) 26 | } 27 | 28 | } 29 | 30 | 31 | 32 | winform.endModal(ids); 33 | 34 | 35 | } 36 | 37 | winform.onClose = function(){ 38 | winform.button5.oncommand() 39 | } 40 | 41 | 42 | 43 | winform.init = function(){ 44 | 45 | 46 | winform.listview.insertColumn("ID",50,1) 47 | winform.listview.insertColumn("名称",140,2) 48 | winform.listview.insertColumn("规格",100,3) 49 | winform.listview.setExtended(0x4/*_LVS_EX_CHECKBOXES*/); 50 | 51 | var goods = modGoods.search() 52 | 53 | 54 | for(i=1;#goods;1){ 55 | var item = {goods[i].id; goods[i].name; goods[i].specs} 56 | winform.listview.addItem(item) 57 | } 58 | 59 | } 60 | 61 | winform.button8.oncommand = function(id,event){ 62 | var goodsform = sqlitemodel.modelForm(modGoods, mainForm); 63 | goodsform.doModal(mainForm); 64 | 65 | var items = modGoods.search() 66 | if(#items>0){ 67 | winform.listview.clear(); 68 | for(i=1;#items;1){ 69 | var item = {items[i].id; items[i].name; items[i].specs} 70 | winform.listview.addItem(item) 71 | } 72 | } 73 | 74 | } 75 | 76 | winform.listview.onnotify = function(id,code,ptr){ 77 | select(code) { 78 | case 0xFFFFFFFE/*_NM_CLICK*/{ 79 | var nm = winform.listview.getNotifyMessage(code,ptr) 80 | if( ! nm.iItem ) return ; 81 | winform.listview.setChecked(nm.iItem,!winform.listview.getChecked(nm.iItem) ) 82 | } 83 | } 84 | } 85 | 86 | winform.button.oncommand = function(id,event){ 87 | var items = modGoods.search(winform.edit.text) 88 | if(#items>0){ 89 | winform.listview.clear(); 90 | for(i=1;#items;1){ 91 | var item = {items[i].id; items[i].name; items[i].specs} 92 | winform.listview.addItem(item) 93 | } 94 | } 95 | } 96 | 97 | winform.edit.oncommand = function(id,event){ 98 | if(event== 0x300/*_EN_CHANGE*/){ 99 | winform.button.oncommand(); 100 | } 101 | } 102 | 103 | winform.init() 104 | winform.show(); 105 | win.loopMessage(); 106 | return winform; -------------------------------------------------------------------------------- /dlg/goods_sell.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import console; 3 | import time; 4 | import config; 5 | /*DSG{{*/ 6 | var winform = win.form(text="采购单(入库)";right=790;bottom=457) 7 | winform.add( 8 | button={cls="button";text="选择商品";left=507;top=5;right=685;bottom=63;dr=1;dt=1;z=8}; 9 | button2={cls="button";text="全部清空";left=699;top=101;right=783;bottom=132;z=9}; 10 | button3={cls="button";text="删除选中";left=699;top=152;right=783;bottom=183;z=10}; 11 | button5={cls="button";text="生成采购单";left=575;top=418;right=662;bottom=448;z=14}; 12 | comboOrg={cls="combobox";left=72;top=42;right=199;bottom=63;edge=1;items={};mode="dropdown";z=15}; 13 | comboStore={cls="combobox";left=245;top=12;right=379;bottom=32;edge=1;items={};mode="dropdown";z=4}; 14 | comboSupplier={cls="combobox";left=72;top=12;right=202;bottom=32;edge=1;items={};mode="dropdown";z=2}; 15 | editApplier={cls="edit";left=269;top=40;right=399;bottom=62;edge=1;z=13}; 16 | editNote={cls="edit";left=72;top=69;right=481;bottom=92;edge=1;z=6}; 17 | listview={cls="listview";left=13;top=101;right=685;bottom=399;edge=1;fullRow=1;gridLines=1;vscroll=1;z=7}; 18 | static={cls="static";text="供应商";left=12;top=11;right=67;bottom=31;transparent=1;z=1}; 19 | static2={cls="static";text="仓库";left=208;top=11;right=237;bottom=32;transparent=1;z=3}; 20 | static3={cls="static";text="备注";left=11;top=72;right=66;bottom=92;transparent=1;z=5}; 21 | static4={cls="static";text="部门处室";left=11;top=43;right=66;bottom=63;transparent=1;z=11}; 22 | static5={cls="static";text="申请人";left=208;top=42;right=259;bottom=62;transparent=1;z=12} 23 | ) 24 | /*}}*/ 25 | 26 | /*winform_reset_listview{{*/ 27 | winform.reset_listview = function(model, items, fields){ 28 | 29 | //如果获取了数据, 那么清空listview 30 | if(#items!=0){ 31 | winform.listview.clear(); 32 | }else { 33 | winform.listview.clear(); 34 | return 35 | } 36 | 37 | var n = winform.listview.columnCount; 38 | for(i=1;n;1){ 39 | winform.listview.delColumn(n+1-i);//从倒数开始删除, 以免删除前面的, 后面的索引都变了. 40 | } 41 | 42 | var display_fields; 43 | 44 | if(fields != null and type(fields) == "table" and #fields > 0 ){ 45 | display_fields = fields; 46 | }else { 47 | display_fields = model.display_fields; 48 | } 49 | 50 | for(i=1;#display_fields;1){ 51 | var k = display_fields[i] 52 | var caption = model.headers[k] 53 | winform.listview.insertColumn(caption, 140, i); 54 | } 55 | 56 | n = winform.listview.columnCount; 57 | winform.listview.insertColumn("采购数量", 140, n+1); 58 | 59 | n = winform.listview.columnCount; 60 | if(n>=3){ 61 | winform.listview.setColumn({cx=30},1) 62 | winform.listview.setColumn({cx=180},2) 63 | winform.listview.setColumn({cx=80},3) 64 | } 65 | 66 | for(i=1;#items;1){ 67 | var item = {}//每一行的数据 68 | for(j=1;#display_fields;1){ 69 | k = display_fields[j]; 70 | //if(k=="id"){ 71 | // table.push(data, tostring(i)) 72 | // continue 73 | //} 74 | //console.log('k', k); 75 | if(items[i][k]!=null){ 76 | table.push(item, items[i][k]) 77 | }else { 78 | table.push(item, "") 79 | } 80 | } 81 | table.push(item, "1");//采购数量默认为1 82 | // 83 | //console.varDump(items[i]) 84 | // 85 | 86 | winform.listview.addItem({ 87 | text = item 88 | }); 89 | } 90 | 91 | 92 | } 93 | /*}}*/ 94 | 95 | winform.button.oncommand = function(id,event){ 96 | var frmChild = winform.loadForm("\dlg\goods_select.aardio"); 97 | var goods_ids = frmChild.doModal(); 98 | 99 | //var sql = "select from ["+winform.+"]" 100 | var model = modGoods 101 | if(#goods_ids){ 102 | var sql = string.format("select * from [%s] where id in (%s)", model.tablename, string.join(goods_ids,",")) 103 | var items = model.getTable(sql); 104 | 105 | /* 106 | var user_define_fields = model.display_fields 107 | table.removeByValue(user_define_fields, "created_at") 108 | table.removeByValue(user_define_fields, "updated_at") 109 | */ 110 | 111 | var user_define_fields = {"id"; "name"; "specs"; "unit"} 112 | winform.reset_listview(model, items, user_define_fields) 113 | } 114 | } 115 | 116 | 117 | 118 | 119 | winform.init = function(){ 120 | //调用mainForm中的全局变量 121 | var suppliers = table.map(modSupplier.search(),function(v,k,result){ 122 | if(type(k)== "number"){ 123 | table.push(result, string.format("%s|%s", v.id, v.name)) 124 | } 125 | }) 126 | 127 | var stores = table.map(modStore.search(),function(v,k,result){ 128 | if(type(k)== "number"){ 129 | table.push(result, string.format("%s|%s", v.id, v.name)) 130 | } 131 | }) 132 | 133 | 134 | for(i=1;#suppliers;1){ 135 | winform.comboSupplier.add(suppliers[i]) 136 | } 137 | 138 | for(i=1;#stores;1){ 139 | winform.comboStore.add(stores[i]) 140 | } 141 | 142 | 143 | var edit_Orgs = config.settings.edit_Orgs; 144 | 145 | if(edit_Orgs != null){ 146 | var items = string.split(edit_Orgs, "<;>") 147 | for(i=1;#items;1){ 148 | winform.comboOrg.add(string.trim(items[i])) 149 | } 150 | 151 | } 152 | 153 | 154 | } 155 | 156 | winform.comboSupplier.onEditChange = function(){ 157 | var text = winform.comboSupplier.text; 158 | var items = table.filter( winform.comboSupplier.items, lambda(v) string.startWith(v,text) ); 159 | winform.comboSupplier.autoComplete(items); 160 | } 161 | 162 | winform.comboStore.onEditChange = function(){ 163 | var text = winform.comboStore.text; 164 | var items = table.filter( winform.comboStore.items, lambda(v) string.startWith(v,text) ); 165 | winform.comboStore.autoComplete(items); 166 | } 167 | 168 | winform.button2.oncommand = function(id,event){ 169 | winform.listview.clear(); 170 | } 171 | 172 | 173 | winform.listview.onnotify = function(id,code,ptr){ 174 | if(code = 0xFFFFFFFE/*_NM_CLICK*/ ){ 175 | 176 | var nm = winform.listview.getNotifyMessage(code,ptr); 177 | if( ! nm.iItem && nm.iSubItem ) return true;//不允许编辑项 178 | 179 | //一点击就出现编辑框, 不用先点一下, 再点一下 180 | //winform.listview.editLabel(nm.iItem, nm.iSubItem); 181 | //上面这一行只能编辑第一列, 第2列和后面的都不能编辑, 看了源码,不行 182 | var nCols = winform.listview.columnCount; 183 | if(nm.iSubItem0){ 66 | tv.clear(); 67 | } 68 | 69 | var item = {text = "显示全部数据"} 70 | var hItem = tv.insertItem(item) 71 | 72 | for(i=1;#filter_fields;1){ 73 | var item = {} 74 | /*{ 75 | text = "上级菜单"; 76 | { 77 | { text = "下级1" }; 78 | { text = "下级2" }; 79 | { text = "下级3" }; 80 | { text = "下级4" }; 81 | { text = "下级5" }; 82 | { text = "其他" }; 83 | } 84 | }*/ 85 | 86 | 87 | 88 | var k = filter_fields[i] 89 | var caption = model.headers[k] 90 | 91 | console.varDump(model.headers) 92 | console.log("caption, k",caption, k) 93 | 94 | item["text"] = string.format("按%s过滤", caption); 95 | //query["filter_field"] = k 96 | 97 | var sql = string.format("select distinct %s from %s", k, model.tablename) 98 | var items = model.getTable(sql) 99 | 100 | var data = {} 101 | for(i=1;#items;1){ 102 | table.push(data, {text = items[i][k]; filter_field = k}) 103 | } 104 | 105 | table.push(item, data) 106 | 107 | var hItem = tv.insertItem(item) 108 | 109 | } 110 | 111 | tv.expandAll() 112 | 113 | 114 | } 115 | 116 | winform.button.oncommand = function(id,event){ 117 | 118 | if(winform.model == null){ 119 | winform.msgbox("窗口未设置model对象, 无法正确显示数据") 120 | } 121 | 122 | keyword = winform.edit.text; 123 | winform.load_data(keyword) 124 | 125 | } 126 | 127 | 128 | 129 | winform.load_data = function(keyword=""){ 130 | var items={}; 131 | var query = {}; 132 | if(type(keyword)=="table"){ 133 | query = keyword 134 | }elseif(type(keyword)=="string"){ 135 | query["keyword"] = keyword; 136 | } 137 | query["QUERY_MODE"] = "SEARCH"; 138 | 139 | winform.CURR_QUERY = query; //记录到全局变量CURR_QUERY中 140 | //log(table.tostring(CURR_QUERY)); 141 | items = winform.model.search(query); 142 | 143 | winform.resetlistview(items) 144 | 145 | 146 | } 147 | 148 | 149 | 150 | winform.resetlistview = function(items){ 151 | winform.statusbar.setText("公司总数:" + #items); 152 | 153 | 154 | if(#items){ 155 | winform.listview.clear(); 156 | }else { 157 | winform.listview.clear(); 158 | } 159 | 160 | 161 | //for(i=1;#items;1){ 162 | // console.varDump(items[i]) 163 | //} 164 | 165 | 166 | //如果获取了数据, 那么清空listview 167 | var n = winform.listview.columnCount; 168 | for(i=1;winform.listview.columnCount;1){ 169 | winform.listview.delColumn(n+1-i); 170 | } 171 | 172 | var display_fields = winform.model.display_fields; 173 | for(i=1;#display_fields;1){ 174 | var k = display_fields[i] 175 | var caption = winform.model.headers[k] 176 | winform.listview.insertColumn(caption, 140, i); 177 | } 178 | 179 | winform.listview.setColumn({cx=40},1) 180 | winform.listview.setColumn({cx=180},2) 181 | winform.listview.setColumn({cx=80},3) 182 | 183 | 184 | 185 | for(i=1;#items;1){ 186 | //winform.listview.add(items[i]['title']); 187 | //console.log("query[i]") 188 | //console.varDump(items[i]) 189 | 190 | var row ={} 191 | for(j=1;#display_fields;1){ 192 | k = display_fields[j]; 193 | //if(k=="id"){ 194 | // table.push(data, tostring(i)) 195 | // continue 196 | //} 197 | //console.log('k', k); 198 | if(items[i][k]!=null){ 199 | table.push(row, items[i][k]) 200 | }else { 201 | table.push(row, "") 202 | } 203 | 204 | 205 | } 206 | // 207 | //console.varDump(items[i]) 208 | // 209 | 210 | winform.listview.addItem({ 211 | text = row 212 | }); 213 | } 214 | 215 | if(items["ITEMS_PERPAGE"]){ 216 | winform.comboItemsPerpage.text = tostring(items["ITEMS_PERPAGE"]) 217 | } 218 | if(items["PAGES"]){ 219 | winform.comboCurrPage.clear(); 220 | for(i=1;items["PAGES"];1){ 221 | winform.comboCurrPage.add(tostring(i)) 222 | } 223 | } 224 | if(items["CURR_PAGE"]!=null){ 225 | winform.comboCurrPage.text = tostring(items["CURR_PAGE"]+1) 226 | } 227 | } 228 | 229 | 230 | winform.init = function(model){ 231 | 232 | //winform.center() 233 | winform.model = model; 234 | 235 | var state = config.settings.autoclose_company_form; 236 | // 237 | //console.log(" config autoclose_company_form " ++ state) 238 | // 239 | 240 | if(state == null){ 241 | state = false; 242 | config.saveAll() 243 | } 244 | // 245 | //console.log(" started " ++ state) 246 | // 247 | win.ui.statusbar( winform ).addItem("公司:", 100/*宽度*/) 248 | 249 | winform.statusbar.addItem("数据库:", 500); 250 | 251 | initTreeview(winform.model, winform.treeview) 252 | 253 | winform.load_data(winform.edit.text); 254 | } 255 | 256 | 257 | 258 | winform.treeview.onnotify = function(id,code,ptr){ 259 | if(code = 0xFFFFFFFE/*_NM_CLICK*/){ 260 | //单击 261 | var x,y = mouse.getPos() 262 | var hItem,tvht = winform.treeview.hitTest(x,y,true); 263 | 264 | if(!hItem){ 265 | return 266 | } 267 | 268 | winform.treeview.setSelected(hItem); 269 | winform.treeview.expandAll() 270 | 271 | var hitem = winform.treeview.getSelection() 272 | //winform.text = winform.treeview.getItemData(hitem); 273 | var data = winform.treeview.getItemData(hitem); 274 | 275 | var filter_field = data["filter_field"]; 276 | //if(filter_field == null){ 277 | // return 278 | //} 279 | 280 | var keyword = ""; 281 | 282 | if(data == null or #data>0){ 283 | //未选中节点, 或者选中节点有子节点(根节点) 284 | keyword = "" 285 | //return 286 | }else { 287 | //没有子节点的节点,如果是根节点, 那么也是在这里处理, 但是没有filter_field数据, 所以后面的filter 288 | // 会因为没有filter_field数据, 而返回全部数据, 忽略keyword 289 | keyword = data["text"]; 290 | if(string.indexOf(keyword, "|")){ 291 | keyword = string.split(keyword, "<|>")[1] 292 | } 293 | //winform.text = data["text"] ++ " 单位"; 294 | } 295 | 296 | var query = {}; 297 | query["filter_field"] = filter_field; 298 | query["keyword"] = keyword; 299 | var items_perpage = tonumber(winform.comboItemsPerpage.text); 300 | query["ITEMS_PERPAGE"] = items_perpage 301 | query["QUERY_MODE"] = "FILTER"; 302 | 303 | CURR_QUERY = query; 304 | winform.log(table.tostring(CURR_QUERY)); 305 | 306 | var items = winform.model.filter(query) 307 | 308 | winform.resetlistview(items); 309 | 310 | } 311 | } 312 | 313 | 314 | winform.item_detail = function(id){ 315 | 316 | var mform = sqlitemodel.modelForm(winform.model, winform, id); 317 | mform.doModal(winform); 318 | winform.load_data(winform.edit.text); 319 | } 320 | 321 | winform.delete_items = function(ids){ 322 | 323 | if(!ids){ 324 | return ; 325 | } 326 | 327 | if(type(ids) != type.table){ 328 | return ; 329 | } 330 | 331 | if(#ids==0){ 332 | return ; 333 | } 334 | 335 | var confirmed = false; //默认不删除 336 | if(config.settings.confirm_delete){ 337 | confirmed = winform.msgboxTest("确认删除吗?"); //看用户选择 338 | }else { 339 | confirmed = true; //无需确认 340 | } 341 | 342 | //console.log("confirmed",confirmed, winform.model.tablename) 343 | if(confirmed){ 344 | var deletes = {} 345 | for(i=1;#ids;1){ 346 | var query = {["id"]=ids[i]}; 347 | //console.log(table.tostring(query)) 348 | var deleted, _msg = winform.model.delete(query); 349 | table.push(deletes, {ids[i]; deleted}); 350 | } 351 | 352 | var failed = false; 353 | for(i=1;#deletes;1){ 354 | if(!deletes[i][2]){ 355 | failed = true; 356 | winform.log(string.format("id(%s) 已经删除失败(%s)", deletes[i][1], tostring(deletes[i][2]))) 357 | }else { 358 | winform.log(string.format("id(%s) 已经删除成功(%s)", deletes[i][1], tostring(deletes[i][2]))) 359 | } 360 | } 361 | 362 | if(!failed){ 363 | winform.load_data(); 364 | winform.msgbox("删除成功!") 365 | }else { 366 | winform.msgbox("删除失败!") 367 | } 368 | } 369 | } 370 | 371 | 372 | 373 | winform.listview.onnotify = function(id,code,ptr){ 374 | 375 | select(code) { 376 | 377 | case 0xFFFFFFFD/*_NM_DBLCLK*/ { 378 | //双击编辑 379 | var x,y = mouse.getPos() 380 | var iRow, iCol = winform.listview.hitTest(x,y,true); 381 | if(iRow){ 382 | //console.log("选中行列", iRow, iCol) 383 | winform.listview.setSelected(iRow) 384 | winform.lastListviewSelected = iRow; 385 | var id = winform.listview.getItemText(iRow, 1); 386 | //console.log("----id", id) 387 | winform.item_detail(id); 388 | } 389 | 390 | } 391 | case 0xFFFFFFFB/*_NM_RCLICK*/ { 392 | //右键菜单 393 | var x,y = mouse.getPos() 394 | var iRow, iCol = winform.listview.hitTest(x,y,true); 395 | if(iRow){ 396 | winform.listview.setSelected(iRow) 397 | winform.lastListviewSelected = iRow; 398 | } 399 | 400 | var menu = win.ui.popmenu(winform) 401 | 402 | menu.add("详细信息", 403 | function(){ 404 | var iRow = winform.listview.getSelection(); //选中的行 405 | if(!iRow){ 406 | winform.msgbox("请选中一项再操作"); 407 | return 408 | }else { 409 | var id = winform.listview.getItemText(iRow, 1) 410 | winform.item_detail(id); 411 | } 412 | } 413 | ); 414 | 415 | 416 | var filter_fields = winform.model.filter_fields 417 | 418 | var filter_menus = {} 419 | 420 | 421 | 422 | for(i=1;#filter_fields;1){ 423 | var item = {} 424 | 425 | var k = filter_fields[i] 426 | var caption = headers[k] 427 | if(caption==null){ 428 | continue 429 | } 430 | 431 | table.push(item, string.format("更改选中项的%s为", caption)) 432 | var sql = string.format("select distinct %s from %s", k, winform.model.tablename) 433 | var items = winform.model.getTable(sql) 434 | 435 | //console.log("items") 436 | //console.varDump(items) 437 | 438 | var data = {} 439 | for(i=1;#items;1){ 440 | //console.log("items[i][k]", items[i][k]); 441 | var x = { 442 | tostring(items[i][k]); //tostring() 避免 USTRING ERROR 443 | function(id){ 444 | //winform.msgbox(tostring(items[i][k])) 445 | change_company_field(k,items[i][k]); 446 | } 447 | } 448 | //console.log(" console.varDump(x)") 449 | //console.varDump(x) 450 | table.push(data, x) 451 | } 452 | 453 | if(#data){ 454 | //console.log("console.varDump(data)") 455 | //console.varDump(data) 456 | table.push(item, data) 457 | }else { 458 | continue; 459 | } 460 | 461 | //console.log("continue;") 462 | 463 | //console.varDump(item) 464 | table.push(filter_menus, item) 465 | } 466 | 467 | //console.varDump(filter_menus) 468 | if(#filter_menus){ 469 | menu.addTable( 470 | //{filter_menus} 471 | filter_menus 472 | ) 473 | } 474 | 475 | menu.add({}); 476 | 477 | menu.add("全选", 478 | function(){ 479 | for(i=1;winform.listview.count;1){ 480 | winform.listview.setSelected(i) 481 | } 482 | } 483 | ); 484 | 485 | 486 | 487 | menu.add("导出选中项数据", 488 | function(){ 489 | var items = {} 490 | //console.log(winform.listview.columnCount) 491 | var ids = {} 492 | for(i=1;winform.listview.count;1){ 493 | if(winform.listview.getSelected(i)){ 494 | table.push(ids, winform.listview.getItemText(i,1)); //每一行的第1列就是id 495 | //var query = {} 496 | //console.log(table.tostring(winform.model.display_fields)) 497 | //for(i=1;#winform.model.display_fields;1){ 498 | // k = winform.model.display_fields[i] 499 | // query[k] = winform.listview.getItemText(iRow, i) 500 | //} 501 | } 502 | } 503 | if(#ids){ 504 | var TABLE_NAME = winform.model.tablename; 505 | var sql = "SELECT * FROM [" ++ TABLE_NAME ++ "] where id in (" + string.join(ids, ", ") + ")" 506 | items = winform.model.getTable(sql); 507 | export_model(winform.model, items); 508 | } 509 | 510 | } 511 | ); 512 | 513 | 514 | menu.add({}); 515 | 516 | 517 | menu.add("修改", 518 | function(){ 519 | var iRow, iCol = winform.listview.hitTest(x,y,true); 520 | if(iRow){ 521 | //console.log("选中行列", iRow, iCol) 522 | winform.listview.setSelected(iRow) 523 | winform.lastListviewSelected = iRow; 524 | var id = winform.listview.getItemText(iRow, 1); 525 | winform.item_detail(id); 526 | } 527 | } 528 | ); 529 | menu.add({}); 530 | 531 | menu.add("删除选中项", 532 | function(){ 533 | //console.log("删除选中项") 534 | var items = {} 535 | var ids = {} 536 | for(i=1;winform.listview.count;1){ 537 | if(winform.listview.getSelected(i)){ 538 | table.push(ids, winform.listview.getItemText(i,1)); //每一行的第1列就是id 539 | } 540 | } 541 | winform.delete_items(ids) 542 | } 543 | ); 544 | //menu.add("调换班级", 545 | /// function(){ 546 | // 547 | // } 548 | //); 549 | menu.popup(x,y,true); 550 | 551 | } 552 | else { 553 | } 554 | } 555 | } 556 | 557 | winform.button3.oncommand = function(id,event){ 558 | var mform = sqlitemodel.modelForm(winform.model, winform); 559 | mform.text = string.format("添加%s数据", winform.model.label ) 560 | mform.doModal(); 561 | 562 | winform.load_data(winform.model) 563 | } 564 | 565 | winform.button6.oncommand = function(id,event){ 566 | winform.load_data(winform.model) 567 | } 568 | 569 | //winform.init(); 570 | 571 | winform.button4.oncommand = function(id,event){ 572 | var filepath = fsys.dlg.open("Excel文件(*.xls;*xlsx)|*.xls;*xlsx","请选择Excel文件",,winform) 573 | if(filepath){ 574 | import_model(winform.model, filepath); 575 | } 576 | } 577 | 578 | winform.btnPrev.oncommand = function(id,event){ 579 | var curr_page = winform.comboCurrPage.text 580 | var prev_page = tonumber(curr_page) - 1; 581 | if(prev_page<0){ 582 | prev_page = 0 583 | } 584 | var model = winform.model; 585 | var query = winform.CURR_QUERY; 586 | if(!query){ 587 | query = {} 588 | query["keyword"] =""; 589 | } 590 | query["CURR_PAGE"] = prev_page 591 | var items = {} 592 | select(query["QUERY_MODE"]) { 593 | case "FILTER" { 594 | items = model.filter(query); 595 | } 596 | case "SEARCH" { 597 | items = model.search(query); 598 | } 599 | else { 600 | 601 | } 602 | } 603 | 604 | winform.resetlistview(items); 605 | winform.log(table.tostring(query)) 606 | } 607 | 608 | winform.btnNext.oncommand = function(id,event){ 609 | var model = winform.model; 610 | var query = winform.CURR_QUERY; 611 | if(!query){ 612 | query={}; 613 | query["keyword"] =""; 614 | } 615 | 616 | var curr_page = winform.comboCurrPage.text 617 | var pages = table.map(winform.comboCurrPage.items,function(v,k,result){ 618 | return tonumber(v); 619 | }) 620 | var min, max = table.range(pages) 621 | var next_page = tonumber(curr_page) + 1; 622 | if(next_page>max){ 623 | next_page = max 624 | } 625 | 626 | query["CURR_PAGE"] = next_page; 627 | var items = {} 628 | select(query["QUERY_MODE"]) { 629 | case "FILTER" { 630 | items = model.filter(query); 631 | } 632 | case "SEARCH" { 633 | items = model.search(query); 634 | } 635 | else { 636 | 637 | } 638 | } 639 | 640 | winform.resetlistview(items); 641 | 642 | log(table.tostring(query)) 643 | } 644 | 645 | winform.comboItemsPerpage.oncommand = function(id,event){ 646 | if(event = 4/*_CBN_KILLFOCUS*/){ 647 | winform.log("winform.comboItemsPerpage.oncommand _CBN_KILLFOCUS") 648 | var n = winform.LAST_ITEMS_PERPAGE; 649 | 650 | try{ 651 | n = tonumber(winform.comboItemsPerpage.text) 652 | if(n != winform.LAST_ITEMS_PERPAGE){ 653 | var model = winform.model; 654 | var query = winform.CURR_QUERY; 655 | if(query == null){ 656 | query = {}; 657 | query["keyword"] = ""; 658 | query["QUERY_MODE"] = "SEARCH"; 659 | } 660 | 661 | query["CURR_PAGE"] = 1; 662 | query["ITEMS_PERPAGE"] = n; 663 | winform.CURR_QUERY = query; 664 | var items = {} 665 | select(query["QUERY_MODE"]) { 666 | case "FILTER" { 667 | items = model.filter(query); 668 | } 669 | case "SEARCH" { 670 | items = model.search(query); 671 | } 672 | else { 673 | 674 | } 675 | } 676 | 677 | winform.resetlistview(items); 678 | 679 | //console.varDump(items) 680 | 681 | winform.log(table.tostring(query)) 682 | winform.LAST_ITEMS_PERPAGE = n; 683 | } 684 | } 685 | catch(e){ 686 | log(tostring(e)) 687 | } 688 | 689 | } 690 | } 691 | 692 | winform.edit.oncommand = function(id,event){ 693 | if(event=0x300/*_EN_CHANGE*/){ 694 | winform.button.oncommand(); 695 | } 696 | } 697 | 698 | winform.enableDpiScaling(); 699 | winform.show(); 700 | 701 | win.loopMessage(); 702 | return winform; -------------------------------------------------------------------------------- /dlg/select_fields.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import math; 3 | /*DSG{{*/ 4 | var winform = win.form(text="选择字段";right=628;bottom=539) 5 | winform.add( 6 | button={cls="button";text=">>";left=254;top=83;right=295;bottom=119;z=3}; 7 | button2={cls="button";text="<<";left=254;top=142;right=295;bottom=178;z=4}; 8 | button3={cls="button";text="上移";left=565;top=83;right=606;bottom=119;z=6}; 9 | button4={cls="button";text="下移";left=565;top=142;right=606;bottom=178;z=7}; 10 | button5={cls="button";text="确定";left=441;top=497;right=540;bottom=529;z=8}; 11 | button6={cls="button";text=">>>";left=254;top=241;right=295;bottom=277;z=9}; 12 | button7={cls="button";text="<<<";left=255;top=297;right=296;bottom=333;z=10}; 13 | checklist={cls="checklist";left=5;top=32;right=241;bottom=455;edge=1;items={};msel=1;vscroll=1;z=1}; 14 | listbox={cls="listbox";left=314;top=32;right=550;bottom=455;edge=1;items={};msel=1;vscroll=1;z=5}; 15 | static={cls="static";text="可选字段";left=19;top=10;right=168;bottom=29;transparent=1;z=2} 16 | ) 17 | /*}}*/ 18 | 19 | winform.button5.oncommand = function(id,event){ 20 | //winform.msgbox( winform.button.text ); 21 | var labels = {} 22 | 23 | for(i=1;winform.listbox.count;1){ 24 | table.push(labels, winform.listbox.getItemText(i)) 25 | } 26 | 27 | 28 | 29 | winform.endModal( labels ) 30 | 31 | } 32 | 33 | winform.onClose = function(){ 34 | winform.button5.oncommand() 35 | } 36 | 37 | winform.button.oncommand = function(id,event){ 38 | var ids = {} 39 | for(i=1;winform.checklist.count;1){ 40 | if(winform.checklist.getChecked(i)){ 41 | table.push(ids, i) 42 | winform.listbox.add(winform.checklist.getItemText(i)) 43 | } 44 | } 45 | 46 | table.reverse(ids); 47 | 48 | for(i=1;#ids;1){ 49 | winform.checklist.delItem(ids[i]); 50 | } 51 | 52 | } 53 | 54 | winform.button2.oncommand = function(id,event){ 55 | var ids = {} 56 | for(i=1;winform.listbox.count;1){ 57 | if(i<=3){ 58 | continue; 59 | } 60 | if(winform.listbox.getSelected(i)){ 61 | table.push(ids, i) 62 | winform.checklist.addItem(winform.listbox.getItemText(i)) 63 | } 64 | } 65 | 66 | var idx = 1; 67 | 68 | 69 | if(#ids>0){ 70 | table.reverse(ids); 71 | for(i=1;#ids;1){ 72 | winform.listbox.delete(ids[i]); 73 | } 74 | 75 | //console.log("ids") 76 | //console.varDump(ids) 77 | 78 | maxid = ids[1] - #ids + 1 79 | 80 | idx = math.min(winform.listbox.count, maxid) 81 | 82 | //console.log("maxid", maxid) 83 | //console.log("winform.listbox.count", winform.listbox.count) 84 | //console.log("idx", idx) 85 | }else { 86 | idx = winform.listbox.count; 87 | } 88 | 89 | 90 | if(winform.listbox.count>3){ 91 | //winform.listbox.selIndex = idx; 92 | winform.listbox.setSelected(idx); 93 | } 94 | } 95 | 96 | winform.button3.oncommand = function(id,event){ 97 | var idx = winform.listbox.selIndex 98 | var txt = winform.listbox.selText 99 | 100 | var upperIdx = idx - 1 101 | var upperTxt = winform.listbox.getItemText(upperIdx) 102 | 103 | var n = winform.listbox.count 104 | 105 | if(idx <=4 or txt==null){ 106 | return 107 | } 108 | 109 | winform.listbox.delete(idx) //删掉当前项 110 | winform.listbox.add(upperTxt,idx) //又把当前项,加回来 111 | 112 | winform.listbox.delete(upperIdx) //删掉上一项 113 | winform.listbox.add(txt,upperIdx) //又把上一项,加回来 114 | 115 | winform.listbox.selIndex = upperIdx //一直选中, 就可以一直点 上移 116 | } 117 | 118 | winform.button4.oncommand = function(id,event){ 119 | var n = winform.listbox.count 120 | 121 | var idx = winform.listbox.selIndex 122 | var txt = winform.listbox.selText 123 | 124 | if(idx == n or idx<=3 or txt==null){ 125 | return 126 | } 127 | 128 | var lowerIdx = idx + 1 129 | var lowerTxt = winform.listbox.getItemText(lowerIdx) 130 | 131 | winform.listbox.delete(idx) //删掉当前项 132 | winform.listbox.add(lowerTxt,idx) //又把当前项,加回来 133 | 134 | winform.listbox.delete(lowerIdx) //删掉上一项 135 | winform.listbox.add(txt,lowerIdx) //又把上一项,加回来 136 | 137 | winform.listbox.selIndex = lowerIdx //一直选中, 就可以一直点 下移 138 | } 139 | 140 | winform.button6.oncommand = function(id,event){ 141 | var ids = {} 142 | for(i=1;winform.checklist.count;1){ 143 | 144 | table.push(ids, i) 145 | winform.listbox.add(winform.checklist.getItemText(i)) 146 | 147 | } 148 | 149 | table.reverse(ids); 150 | 151 | for(i=1;#ids;1){ 152 | winform.checklist.delItem(ids[i]); 153 | } 154 | } 155 | 156 | winform.button7.oncommand = function(id,event){ 157 | var reversedTopN = 3; 158 | 159 | var ids = {} 160 | for(i=1;winform.listbox.count;1){ 161 | if(i<=reversedTopN){ 162 | continue; 163 | } 164 | 165 | table.push(ids, i) 166 | winform.checklist.addItem(winform.listbox.getItemText(i)) 167 | 168 | } 169 | 170 | table.reverse(ids); 171 | for(i=1;#ids;1){ 172 | winform.listbox.delete(ids[i]); 173 | } 174 | 175 | if(winform.listbox.count>reversedTopN){ 176 | winform.listbox.selIndex = winform.listbox.count 177 | } 178 | } 179 | 180 | winform.show(); 181 | win.loopMessage(); 182 | return winform; -------------------------------------------------------------------------------- /dlg/settings.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import fsys.dlg; 3 | import config; 4 | /*DSG{{*/ 5 | var winform = win.form(text="设置";right=423;bottom=216;max=false;parent=...) 6 | winform.add( 7 | button={cls="button";text="选择";left=345;top=6;right=414;bottom=32;z=3}; 8 | button2={cls="button";text="确定";left=346;top=183;right=415;bottom=209;z=7}; 9 | button3={cls="button";text="取消";left=227;top=184;right=296;bottom=210;z=8}; 10 | edit_Orgs={cls="edit";left=106;top=115;right=341;bottom=174;autohscroll=false;edge=1;multiline=1;vscroll=1;z=11}; 11 | edit_companyname={cls="edit";left=105;top=84;right=340;bottom=108;edge=1;multiline=1;z=9}; 12 | edit_dbpath={cls="edit";left=104;top=7;right=339;bottom=31;edge=1;multiline=1;z=1}; 13 | rdConfirmDelete1={cls="radiobutton";text="是";left=106;top=50;right=175;bottom=69;z=5}; 14 | rdConfirmDelete2={cls="radiobutton";text="否";left=185;top=50;right=254;bottom=69;z=6}; 15 | static={cls="static";text="数据库路径";left=21;top=12;right=97;bottom=34;transparent=1;z=2}; 16 | static2={cls="static";text="单位名称";left=20;top=85;right=96;bottom=107;transparent=1;z=10}; 17 | static3={cls="static";text="部门处室";left=21;top=116;right=97;bottom=138;transparent=1;z=12}; 18 | static5={cls="static";text="删除要求确认";left=21;top=51;right=105;bottom=73;transparent=1;z=4} 19 | ) 20 | /*}}*/ 21 | 22 | winform.button.oncommand = function(id,event){ 23 | var lastpath = config.settings.dbpath; 24 | if(lastpath!=null and lastpath !=""){ 25 | if(!io.exist(lastpath)){ 26 | lastpath = "D:\" 27 | } 28 | } 29 | 30 | var path = fsys.dlg.opendir(lastpath) 31 | if(path==null){ 32 | winform.msgbox("未选择数据库路径, 程序将不能正确运行") 33 | }else { 34 | winform.edit_dbpath.text=path 35 | config.settings.dbpath = path; 36 | } 37 | } 38 | 39 | 40 | winform.bindConfig( config.settings,{ 41 | edit_dbpath = "text"; 42 | edit_companyname = "text"; 43 | edit_Orgs = "text"; 44 | rdConfirmDelete1 = "checked"; 45 | rdConfirmDelete2 = "checked"; 46 | } ); 47 | 48 | 49 | 50 | init = function(){ 51 | winform.edit_dbpath.text = config.settings.dbpath; 52 | if(config.settings.confirm_delete){ 53 | winform.rdConfirmDelete1.checked = true; 54 | }else { 55 | winform.rdConfirmDelete2.checked = true; 56 | } 57 | 58 | } 59 | 60 | winform.rdConfirmDelete1.oncommand = function(id,event){ 61 | config.settings.confirm_delete = true; 62 | } 63 | 64 | winform.rdConfirmDelete2.oncommand = function(id,event){ 65 | config.settings.confirm_delete = false; 66 | } 67 | 68 | winform.button2.oncommand = function(id,event){ 69 | config.saveAll(); 70 | winform.close(); 71 | } 72 | 73 | 74 | winform.button3.oncommand = function(id,event){ 75 | winform.close(); 76 | } 77 | 78 | init() 79 | 80 | winform.enableDpiScaling(); 81 | winform.show(); 82 | 83 | win.loopMessage(); 84 | return winform; -------------------------------------------------------------------------------- /lib/config.aardio: -------------------------------------------------------------------------------- 1 | //config 配置文件 2 | import fsys.config; 3 | config = ..fsys.config("/config/"); 4 | 5 | /** 6 | config = ..fsys.config( 7 | ..fsys.joinpath( ..fsys.getSpecial( 0x1c /*_CSIDL_LOCAL_APPDATA*/ ),"应用程序名" ) 8 | ); 9 | **/ 10 | 11 | //不需要序列化的配置名字前请添加下划线 12 | namespace config { 13 | __appName = "应用程序名"; 14 | __appVersion = "1.0.0.01"; 15 | __appDescription = "这是一个测试程序"; 16 | __website = "http://www.aardio.com/"; 17 | } 18 | 19 | /**intellisense(config) 20 | __appName = 应用程序名 21 | __appVersion = 应用程序内部版本号 22 | __appDescription = 程序说明 23 | __website = 官方网站 24 | 25 | saveAll() = 写入所有配置到文件 26 | mainForm.load() = 从配置文件(文件名"default")载入\n加载成功返回对象,加载失败返回null空值\n!fsys_table. 27 | mainForm.save() = 存储到配置文件(文件名"default") 28 | mainForm.mixin = @.mixin(\n 键名 = 值__;\n 键名 = 值;\n);//该数会自动调用save函数保存配置到文件 29 | mainForm.控件名称 = 控件默认值\n调用save()函数同步控件当前值 30 | mainForm.属性名 = 自配置文件(文件名"default")读写属性\n属性值可以是支持序列化的普通变量,支持table对象.\n配置文件在首次使用时自动加载,退出程序时自动保存. 31 | end intellisense**/ 32 | -------------------------------------------------------------------------------- /lib/sqlitemodel/_.aardio: -------------------------------------------------------------------------------- 1 | //sqlitemodel 数据库操作 2 | 3 | import string.lcid; 4 | import sqlite; 5 | import time; 6 | import math; 7 | import console; 8 | namespace sqlitemodel; 9 | 10 | class Model { 11 | 12 | //db 数据库连接 13 | //tablename 数据表名称 14 | ctor(db, tablename, sql, 15 | filter_fields, 16 | search_fields, 17 | display_fields, 18 | field_choices, 19 | string_fields, //显示为字符串的字段 20 | DEFAULT_ITEMS_PERPAGE=100, ... ) { 21 | if(db==null){ 22 | error("db is null, db connection must be initialized first",2) 23 | } 24 | this.db = db; 25 | this.tablename = tablename; 26 | this.label = tablename; 27 | this.sql = sql; 28 | if(this.sql == null){ 29 | var msg = ..string.format("table(%s) sql is null, sql must be set first", tablename) 30 | error(msg, 2) 31 | } 32 | this.DEFAULT_ITEMS_PERPAGE = DEFAULT_ITEMS_PERPAGE; 33 | //filter_fields = { 34 | // "fullname"; 35 | // "category"; 36 | //} 37 | this.filter_fields = filter_fields; 38 | this.search_fields = search_fields; 39 | this.display_fields = display_fields; 40 | this.string_fields = string_fields; 41 | this.field_choices = field_choices; 42 | this.required_fields = {}; //导入Excel的时候必须要有的字段 43 | this.headers = {} //field_name -> 中文 44 | if(display_fields == null){ 45 | this.display_fields= {} 46 | } 47 | this.fields = {}; //默认的全部fields列表, 不含数据id 48 | 49 | // this.field_names 是一个table{{};{};...{}} 50 | // 每一项是一个table = {name = xxx; label=yyy} 51 | // name是英文的字段名, label是中文的显示名称, 数据来源于 create_table_sql 建表语句 52 | // 特殊的sql语句, 里面的注释中包含中文显示名称 53 | this.field_names = {} 54 | this.item = {} //single record 55 | //init 56 | this.field_names = get_field_names(this.sql) //包含id字段 57 | 58 | var table_name= get_tablename(this.sql); 59 | if(table_name != tablename){ 60 | var msg = ..string.format("tablename(%s) in function parameters, donot match the tablename(%s) in the sql", tablename, table_name ) 61 | error(msg,2) 62 | } 63 | 64 | for(k,v in this.field_names){ 65 | this.headers[v["name"]] = v["label"] 66 | } 67 | 68 | if(#this.display_fields <= 1){ 69 | ..table.clear(this.display_fields) 70 | for(k,v in this.field_names){ 71 | ..table.push(this.display_fields, v["name"]) 72 | } 73 | } 74 | 75 | //..console.log(..table.tostring(this.headers)) 76 | check_fields_exists(filter_fields, this, "filter_fields") 77 | check_fields_exists(search_fields, this, "search_fields") 78 | check_fields_exists(display_fields, this, "display_fields") 79 | 80 | if(#(this.required_fields)==0){ 81 | this.required_fields = get_required_fields(this) 82 | } 83 | 84 | //..console.log(db, tablename, sql) 85 | if(!db.existsTable(tablename)){ 86 | ..console.log(tablename,"not exists") 87 | db.exec(sql) 88 | }else { 89 | //..console.log(tablename,"ALREADY EXISTS!") 90 | } 91 | 92 | //..console.varDump(this.field_names) 93 | 94 | //..table.mixin(this,tm) 95 | }; 96 | 97 | 98 | @_meta; 99 | //@_metaProperty; 100 | } 101 | 102 | namespace Model{ 103 | //import util.metaProperty; 104 | //_metaProperty = util.metaProperty( 105 | 106 | _meta = { 107 | _type = "sqlite.table"; 108 | 109 | _tostring = function(){ 110 | return tostring( owner.string_fields ); 111 | } 112 | 113 | 114 | //_serialize = function(){ 115 | // return ..string.format(`..Model.ole(%s,"%s")`,tonumber(owner), owner.format); 116 | //} 117 | 118 | 119 | 120 | 121 | save = function(query){ 122 | 123 | } 124 | 125 | 126 | //query is table type 127 | create = function(query){ 128 | var field_names = owner.field_names; //不含id 129 | 130 | // 131 | //..console.log("field_names") 132 | //..console.varDump(field_names) 133 | // 134 | 135 | // 136 | ..console.log("insert query") 137 | ..console.varDump(query) 138 | // 139 | 140 | var field_values = {} 141 | 142 | for(i=1;#field_names;1){ 143 | //create 需要屏蔽id 144 | if(field_names[i]["name"] == "id"){ 145 | continue; 146 | } 147 | ..table.push(field_values, "@" ++field_names[i]["name"]) 148 | } 149 | var str_field_values = ..string.join(field_values, ", ") 150 | str_field_values = " VALUES (null, " + str_field_values ++ ");" 151 | 152 | // 153 | //console.log(str_field_values) 154 | // 155 | 156 | 157 | 158 | 159 | var command = owner.db.prepare("INSERT INTO "+ owner.tablename + str_field_values ) ; 160 | 161 | //以下非空字段, 要在for循环前绑定, 绑不上去. 162 | //command.bind.parameterByName("", "@boss_name") //给@boss_name 绑定数据 "" 163 | //command.bind.parameterByName("", "@boss_cellphone") //给@boss_cellphone 绑定数据 "" 164 | 165 | //command.bind.parameterByName("", "@charger_name") 166 | //command.bind.parameterByName("", "@charger_cellphone") 167 | 168 | //command.bind.parameterByName(time.now(), "@created") 169 | //command.bind.parameterByName(time.now(), "@updated") 170 | 171 | //给 query 设置默认值 172 | query["created_at"] = default_value(query["created"], ..time.now()) 173 | query["updated_at"] = default_value(query["updated"], ..time.now()) 174 | 175 | //..console.varDump(query) 176 | 177 | for(i=1;#field_names;1){ 178 | //args["@"++company_field_names[i]] = query[company_field_names[i]]; 179 | 180 | // 181 | //console.log(company_field_names[i]["name"]," ", tostring(query[company_field_names[i]["name"]])) 182 | // 183 | 184 | var field = field_names[i]["name"] 185 | var value = query[field] 186 | 187 | //给 将数据绑定到 @field 188 | command.bind.parameterByName(value, '@' + field ) 189 | 190 | } 191 | 192 | var ret = command.step(); 193 | 194 | /* 195 | var sql = "select last_insert_rowid() from " + owner.tablename 196 | ..console.log(sql) 197 | var lastid = owner.db.exec(sql) 198 | ..console.log("lastid") 199 | ..console.varDump(lastid) 200 | */ 201 | //上面的sql执行了没用. 202 | var lastid = owner.db.lastInsertRowid() 203 | ..console.varDump(lastid) 204 | 205 | 206 | 207 | 208 | ..console.log("sql insert result ", ret) 209 | command.finalize(); 210 | 211 | // 212 | ..console.log(command.sql); 213 | // 214 | 215 | // 216 | //console.varDump(query) 217 | // 218 | 219 | if(ret<100){ 220 | ..console.log(owner.db.lasterr()) 221 | ..console.log("insert failed!") 222 | return false; 223 | }else { 224 | return lastid 225 | } 226 | //return true 227 | } 228 | 229 | /*update{{*/ 230 | update = function(query){ 231 | if(query["id"]==null or query["id"]==""){ 232 | ..console.log("Failed , no query['id']") 233 | return false; 234 | } 235 | 236 | // 237 | //console.varDump(query) 238 | // 239 | 240 | old_data = owner.db.stepQuery("SELECT * FROM ["+ owner.tablename +"]", { id = query["id"]}) 241 | 242 | ..console.log("get old data by id") 243 | ..console.varDump(old_data) 244 | 245 | if(old_data == null){ 246 | return false; 247 | } 248 | 249 | var stmts = {} 250 | 251 | for(k,v in query){ 252 | if(k=="created_at" or k=="updated_at"){ 253 | continue 254 | } 255 | if(owner.headers[k]==null){ 256 | ..console.log("not found:", k, ..table.tostring(owner.headers)); 257 | 258 | continue 259 | } 260 | if(old_data[k] != v){ 261 | ..table.push(stmts, " "+ k + " = @" ++ k) 262 | } 263 | } 264 | 265 | ..console.log("to be updated fileds:") 266 | ..console.varDump(stmts) 267 | 268 | 269 | if(#stmts<=0){ 270 | //console.log("no fields to be updated") 271 | return false; 272 | }else { 273 | var k = "updated_at" 274 | ..table.push(stmts, " "+ k + " = @" ++ k) 275 | query[k] = ..time.now() 276 | } 277 | 278 | 279 | var str_set_stmts = ..string.join(stmts, ", ") 280 | str_set_stmts = " SET " + str_set_stmts ++ " WHERE id = @id;" 281 | 282 | //console.log("str_set_stmts") 283 | 284 | //console.log(str_set_stmts) 285 | 286 | 287 | 288 | 289 | var sql = "UPDATE ["+ owner.tablename + "] " + str_set_stmts; 290 | ..console.log("upadte sql:"+sql); 291 | ..console.log("user query:", ..table.tostring(query)) 292 | var updated = false; 293 | try{ 294 | owner.db.exec(sql, query); 295 | updated = true; 296 | //return true; //这里try语句里的 return true 并不能真的返回值, 函数最后返回的是null 297 | } 298 | catch(e){ 299 | //console.varDump(e); 300 | //console.log(tostring(e)) 301 | //return false;//这里try的catch语句里的 return false却可以真正使函数返回.函数最后返回的是false 302 | updated = false; 303 | } 304 | 305 | //console.log("updated!!!!") 306 | 307 | return updated 308 | }; 309 | /*}}*/ 310 | 311 | /*delete{{*/ 312 | delete = function(query){ 313 | var msg = { 314 | "Failed , query['id'] is null or empty" 315 | }; 316 | 317 | if(query["id"]==null or query["id"]==""){ 318 | return false, msg[1]; 319 | } 320 | 321 | var sql = "DELETE FROM ["+ owner.tablename + "] WHERE id = @id;" 322 | //..console.log("sql:"+sql); 323 | var ret = owner.db.exec(sql, query); 324 | //..console.log("sql delete result ", ret) 325 | return true, "successed"; 326 | }; 327 | /*}}*/ 328 | 329 | /*filter{{*/ 330 | filter = function(query){ 331 | //..console.log("filter data") 332 | //..console.varDump(query) 333 | 334 | var filter_fields = {} 335 | 336 | for(k,v in query){ 337 | //..console.log(" k, v",k,v) 338 | if(..string.endWith(k, "_lt")){ 339 | // < 340 | var field = ..string.left(k, -4); 341 | //..console.log(" filter field",field) 342 | if(owner.headers[field] != null){ 343 | ..table.push(filter_fields, " "+ field + " < @" ++ k); 344 | } 345 | 346 | }elseif(..string.endWith(k, "_lte")){ 347 | // <= 348 | var field = ..string.left(k, -5); 349 | if(owner.headers[field] != null){ 350 | ..table.push(filter_fields, " "+ field + " <= @" ++ k); 351 | } 352 | 353 | } 354 | elseif(..string.endWith(k, "_gt")){ 355 | // > 356 | var field = ..string.left(k, -4); 357 | if(owner.headers[field] != null){ 358 | ..table.push(filter_fields, " "+ field + " > @" ++ k); 359 | } 360 | 361 | } 362 | elseif(..string.endWith(k, "_gte")){ 363 | // >= 364 | var field = ..string.left(k, -5); 365 | if(owner.headers[field] != null){ 366 | ..table.push(filter_fields, " "+ field + " >= @" ++ k); 367 | } 368 | 369 | }else{ 370 | if(owner.headers[k] != null){ 371 | // = 372 | ..table.push(filter_fields, " "+ k + " = @" ++ k); 373 | } 374 | } 375 | } 376 | 377 | //..console.log("to be filte fileds:") 378 | //..console.varDump(filter_fields) 379 | 380 | 381 | if(#filter_fields<=0){ 382 | return {}; 383 | } 384 | 385 | var where_stmts = ..string.join(filter_fields, " AND ") 386 | if(where_stmts!=""){ 387 | where_stmts = " WHERE " + where_stmts ++ " " 388 | } 389 | //..console.log("where_stmts",where_stmts) 390 | 391 | var items = {} 392 | var filter_field = query["filter_field"] 393 | if(!query["model_name"]){ 394 | query["model_name"] = owner.tablename 395 | } 396 | 397 | var keyword = query["keyword"] 398 | 399 | if(keyword == null){ 400 | keyword="" 401 | } 402 | TABLE_NAME = owner.tablename 403 | DEFAULT_ITEMS_PERPAGE = owner.DEFAULT_ITEMS_PERPAGE 404 | 405 | if(query["ITEMS_PERPAGE"]){ 406 | DEFAULT_ITEMS_PERPAGE = query["ITEMS_PERPAGE"] 407 | } 408 | 409 | CURR_PAGE = 0 410 | if(query["CURR_PAGE"]){ 411 | CURR_PAGE = query["CURR_PAGE"] - 1; 412 | } 413 | 414 | // 415 | //console.log("keyword:"++keyword) 416 | // 417 | 418 | var sql = "Select * From ["+ TABLE_NAME + "] LIMIT " ++ DEFAULT_ITEMS_PERPAGE ++ " OFFSET " ++ DEFAULT_ITEMS_PERPAGE ++ " * " ++ CURR_PAGE ++ ";"; 419 | var count_sql = "Select count(id) as total From ["+ TABLE_NAME + "]; " 420 | if(where_stmts != ""){ 421 | sql = "Select * From ["+ TABLE_NAME + "] " + where_stmts +" LIMIT " ++ DEFAULT_ITEMS_PERPAGE ++ " OFFSET " ++ DEFAULT_ITEMS_PERPAGE ++ " * " ++ CURR_PAGE ++ ";"; 422 | count_sql = "Select count(id) as total From ["+ TABLE_NAME + "] "+ where_stmts +";"; 423 | } 424 | 425 | //..console.log("sql ", sql); 426 | //..console.log("count_sql ", count_sql); 427 | 428 | //所以最后只能使用手工sql 429 | items = owner.db.getTable(sql, query);//func(sql, paras) 430 | var total = owner.db.stepQuery(count_sql, query)["total"] 431 | 432 | var PAGES = ..math.ceil( total / DEFAULT_ITEMS_PERPAGE) 433 | 434 | items["CURR_PAGE"] = CURR_PAGE; 435 | items["ITEMS_PERPAGE"] = DEFAULT_ITEMS_PERPAGE; 436 | items["PAGES"] = PAGES; 437 | items["COUNT"] = total; 438 | 439 | if(items["CURR_PAGE"] >= items["PAGES"]){ 440 | items["CURR_PAGE"] = items["PAGES"] -1 441 | } 442 | 443 | return items; 444 | }; 445 | /*}}*/ 446 | 447 | bulk_create = function(queryset){ 448 | owner.db.beginTrans() 449 | for(i=1;#queryset;1){ 450 | var query = queryset[i]; 451 | 452 | var field_names = owner.field_names; 453 | var field_values = {} 454 | 455 | for(i=1;#field_names;1){ 456 | //create 需要屏蔽id 457 | if(field_names[i]["name"] == "id"){ 458 | continue; 459 | } 460 | ..table.push(field_values, "@" ++field_names[i]["name"]) 461 | } 462 | var str_field_values = ..string.join(field_values, ", ") 463 | str_field_values = " VALUES (null, " + str_field_values ++ ");" 464 | 465 | var command = owner.db.prepare("INSERT INTO "+ owner.tablename + str_field_values ) ; 466 | 467 | //以下非空字段, 要在for循环前绑定, 绑不上去. 468 | //command.bind.parameterByName("", "@boss_name") //给@boss_name 绑定数据 "" 469 | //command.bind.parameterByName("", "@boss_cellphone") //给@boss_cellphone 绑定数据 "" 470 | 471 | //给 query 设置默认值 472 | query["created_at"] = default_value(query["created"], ..time.now()) 473 | query["updated_at"] = default_value(query["updated"], ..time.now()) 474 | 475 | for(i=1;#field_names;1){ 476 | var field = field_names[i]["name"] 477 | var value = query[field] 478 | //给 将数据绑定到 @field 479 | command.bind.parameterByName(value, '@' + field ) 480 | } 481 | var ret = command.step(); 482 | } 483 | owner.db.commitTrans(); 484 | } 485 | 486 | exclude = function(query){ 487 | 488 | }; 489 | 490 | search = function(query){ 491 | if(!query){ 492 | query = {} 493 | } 494 | 495 | var keyword = "" 496 | if(type(query) == "table"){ 497 | keyword = query["keyword"] 498 | if(!query["model_name"]){ 499 | query["model_name"] = owner.tablename 500 | } 501 | 502 | }elseif(type(query) == "string"){ 503 | keyword = query 504 | query = {["keyword"]=keyword} 505 | } 506 | 507 | 508 | if(keyword==null){ 509 | keyword="" 510 | } 511 | //..console.log("keyword") 512 | //..console.varDump(keyword) 513 | var items = {} 514 | 515 | TABLE_NAME = owner.tablename; 516 | DEFAULT_ITEMS_PERPAGE = owner.DEFAULT_ITEMS_PERPAGE; 517 | if(type(query) == "table" and query["ITEMS_PERPAGE"]){ 518 | DEFAULT_ITEMS_PERPAGE = query["ITEMS_PERPAGE"] 519 | } 520 | 521 | if(!DEFAULT_ITEMS_PERPAGE){ 522 | DEFAULT_ITEMS_PERPAGE = 100; 523 | } 524 | 525 | CURR_PAGE = 0 526 | if(query["CURR_PAGE"]){ 527 | CURR_PAGE = query["CURR_PAGE"]-1; 528 | if(CURR_PAGE<0){ 529 | CURR_PAGE = 0 530 | } 531 | } 532 | 533 | //..console.varDump(owner.search_fields) 534 | var sql = "Select * From ["+ TABLE_NAME + "] LIMIT " ++ DEFAULT_ITEMS_PERPAGE ++ " OFFSET " ++ DEFAULT_ITEMS_PERPAGE ++ " * " ++ CURR_PAGE ++ ";"; 535 | var count_sql = "Select count(id) as total From ["+ TABLE_NAME + "];" 536 | if(keyword!=""){ 537 | var where_stmts = {}; 538 | 539 | for(i=1;#owner.search_fields;1){ 540 | ..table.push(where_stmts, owner.search_fields[i] ++ " LIKE '%" ++ keyword ++ "%'") 541 | } 542 | 543 | if(#where_stmts){ 544 | sql = "Select * From ["+ TABLE_NAME + "] WHERE " ++ ..string.join(where_stmts, " OR ") ++ " LIMIT " ++ DEFAULT_ITEMS_PERPAGE ++ " OFFSET " ++ DEFAULT_ITEMS_PERPAGE ++ " * " ++ CURR_PAGE ++ ";"; 545 | count_sql = "Select count(id) as total From ["+ TABLE_NAME + "] WHERE " ++ ..string.join(where_stmts, " OR ") ++ ";" 546 | } 547 | 548 | 549 | } 550 | 551 | //..console.log("") 552 | //..console.log("sql:",sql) 553 | //..console.log("count_sql:",count_sql) 554 | //..console.log("#items",#items) 555 | 556 | //不太清楚 sql = "SELECT * FROM ["+ TABLE_NAME + "] WHERE fullname LIKE '%@keyword%' LIMIT " ++ DEFAULT_ITEMS_PERPAGE 557 | // 和 558 | 559 | //var command = db.prepare(sql) ; 560 | //console.log(command.sql); 561 | //command.bind.parameterByName(keyword, '@keyword') 562 | //var ret = command.step(); 563 | //items = command.getTable(sql) 564 | //console.log("sql select result ", ret) 565 | //command.finalize(); 566 | //console.log(command.sql); 567 | //if(ret<100){ 568 | // console.log("insert failed!") 569 | // return false; 570 | //} 571 | //具体表现, 就是不知道这些参数是怎么最后表现的, 所以, like语句不好用parameterBy...之类的 572 | // 573 | //所以最后只能使用手工sql 574 | items = owner.db.getTable(sql); 575 | 576 | total = owner.db.stepQuery(count_sql)["total"] 577 | var PAGES = ..math.ceil( total / DEFAULT_ITEMS_PERPAGE) 578 | 579 | items["CURR_PAGE"] = CURR_PAGE; 580 | items["ITEMS_PERPAGE"] = DEFAULT_ITEMS_PERPAGE; 581 | items["PAGES"] = PAGES; 582 | if(items["CURR_PAGE"] >= items["PAGES"]){ 583 | items["CURR_PAGE"] = items["PAGES"] -1 584 | } 585 | //..console.log("#items",#items) 586 | return items; 587 | } 588 | 589 | 590 | exec = function(sql, query){ 591 | ..console.log("exec sql:", sql, '\r\n', "query:") 592 | ..console.varDump(query) 593 | return owner.db.exec(sql, query); 594 | } 595 | 596 | getTable = function(sql, query){ 597 | //..console.log(sql) 598 | return owner.db.getTable(sql, query); 599 | } 600 | 601 | get = function(query){ 602 | //var TABLE_NAME = owner.tablename; 603 | //var id = query["id"]; 604 | //return owner.db.stepQuery("SELECT * FROM ["+ TABLE_NAME +"]", { id = id}) 605 | //if(type(query) != type.table){ 606 | // error("query must be table", 0) 607 | //} 608 | //..console.log("sqlitemodel.get query") 609 | //..console.varDump(query) 610 | var items = owner.filter(query) 611 | //..console.log("sqlitemodel.get items") 612 | //..console.varDump(items) 613 | if(#items>0){ 614 | return items[1] 615 | }else { 616 | return {} 617 | } 618 | } 619 | 620 | get_or_create = function(query){ 621 | return owner._fromnumber( ( tonumber(owner)*1440 + span)/1440 ) 622 | } 623 | 624 | one = function(query){ 625 | return owner.get(query) 626 | } 627 | 628 | all = function(query){ 629 | return owner.get(query) 630 | } 631 | 632 | 633 | objects = function(query){ 634 | return owner.filter(query) 635 | } 636 | 637 | 638 | 639 | 640 | } // _meta 641 | ..table.mix(_meta, { _get = _meta}, ..sqlitemodel._meta); 642 | 643 | //) //_metaProperty 644 | 645 | } 646 | 647 | namespace Model{ 648 | /*get_field_names{{*/ 649 | get_field_names = function(create_table_sql, include_id = true){ 650 | // 返回一个table{{};{};...{}} 651 | // 每一项是一个table = {name = xxx; label=yyy} 652 | // name是英文的字段名, label是中文的显示名称, 数据来源于 create_table_sql 建表语句 653 | // 特殊的sql语句, 里面的注释中包含中文显示名称 654 | // create_table_sql 类似于 655 | // CREATE TABLE "company" ( 656 | // "id" INTEGER NOT NULL PRIMARY KEY, 657 | // "fullname" VARCHAR(32) NOT NULL, /*姓名*/ 658 | // "bank_opened" VARCHAR(32), /*开户行*/ 659 | // "bank_name" VARCHAR(32), /*银行名称*/ 660 | // "bank_account" VARCHAR(32), /*银行账号*/ 661 | // "telephone" VARCHAR(32), /*电话*/ 662 | // "logger_name" VARCHAR(32) NOT NULL, /*登记人*/ 663 | // "logger_cellphone" VARCHAR(32) NOT NULL, /*登记人电话*/ 664 | // "status" VARCHAR(16), /*公司状态*/ 665 | // "created_at" DATE NOT NULL, /*创建时间*/ 666 | // "updated_at" DATE NOT NULL /*更新时间*/ 667 | // ); 668 | // 669 | // include_id = true,则会包含ID, 默认不包含, 670 | // 因为导入的Excel中不需要,担心会覆盖已有的数据 671 | // 重置局部变量 field_names 672 | var field_names = {} //原来是全局变量, 加 var 变局部变量 673 | 674 | if(create_table_sql == null){ 675 | create_table_sql = owner.sql; 676 | } 677 | 678 | var start_pos = ..string.indexOf(create_table_sql, "("); //第一个( 679 | var end_pos = ..string.lastIndexOf(create_table_sql, ")") //最后一个) 680 | 681 | // 682 | //..console.log(..string.sub(create_table_sql, start_pos+1, end_pos-1)) 683 | // 684 | 685 | var str_fields = ..string.sub(create_table_sql, start_pos+1, end_pos-1) 686 | var field_lines = ..string.split(str_fields, '\r\n') 687 | 688 | for(i=1;#field_lines;1){ 689 | // 每行数据格式, 显示列信息, 然后是自定义的注释/*单位名称*/作为中文名字 690 | // "fullname" VARCHAR(32) NOT NULL, /*单位名称*/ 691 | // 692 | var line = ""; 693 | line = ..string.trim(field_lines[i]) 694 | if(line == ""){ 695 | continue 696 | } 697 | var field = ..string.split(line, ' ')[1]; 698 | field = ..string.trim(field, '"') 699 | if(field == "" or field == null){ 700 | continue 701 | } 702 | 703 | var field_type = ..string.split(line, ' ')[2]; 704 | 705 | var comment = ..string.match(line,"\/\*(.*)\*\/");//获得注释中的中文 706 | if(comment == null){ 707 | comment = field;//如果没有中文注释, 使用英文字段名 708 | } 709 | 710 | // 711 | //..console.log(tostring(comment)) 712 | // 713 | 714 | // 获取choices,选择数据 715 | var cs = {} 716 | var tmp = ..string.split(comment, "<:>") 717 | if(tmp[2]!=null){ 718 | cs = ..string.split(tmp[2], "<,>") 719 | comment = tmp[1] 720 | } 721 | // 722 | //..console.log(..table.tostring(cs)) 723 | // 724 | 725 | 726 | var notnull = ..string.match(line,"\s+(<@@NOT@>\s+<@@NULL@>)");//获得 NOT NULL 727 | if(notnull == null){ 728 | required = false;// 729 | }else { 730 | required = true; 731 | } 732 | 733 | // 734 | //..console.log(field, "tostring(notnull)", tostring(notnull)) 735 | // 736 | 737 | 738 | if(field == "id"){ 739 | // 740 | //console.log("id is find") 741 | // 742 | if(include_id){ 743 | ..table.push(field_names, {name=field;label=comment;field_type=field_type;choices=cs;required=required}) 744 | } 745 | continue 746 | }else { 747 | ..table.push(field_names, {name=field;label=comment;field_type=field_type;choices=cs;required=required}) 748 | } 749 | 750 | 751 | } 752 | 753 | return field_names 754 | } 755 | /*}}*/ 756 | 757 | 758 | /*get_tablename{{*/ 759 | get_tablename = function(create_table_sql){ 760 | // create_table_sql 类似于 761 | // CREATE TABLE "company" ( 762 | // ... 763 | // ) 764 | var field_names = {} //原来是全局变量, 加 var 变局部变量 765 | 766 | if(create_table_sql == null){ 767 | create_table_sql = owner.sql; 768 | } 769 | 770 | var start_pos = 0 771 | var end_pos = ..string.indexOf(create_table_sql, "(") //第一个( 772 | 773 | var str_maybe = ..string.sub(create_table_sql, start_pos, end_pos-1); 774 | //..console.log(str_maybe) 775 | 776 | var table_name = ..string.match(str_maybe, '\"(.*)\"');//获得""的tablename 777 | if(table_name == null){ 778 | table_name = "notfound"; 779 | } 780 | 781 | return table_name 782 | } 783 | /*}}*/ 784 | 785 | /*default_value{{*/ 786 | default_value = function(value, default){ 787 | if(value == null){ 788 | return default 789 | } 790 | return value 791 | } 792 | /*}}*/ 793 | 794 | check_fields_exists = function(fields, model, label=""){ 795 | for(i=1;#fields;1){ 796 | var find = false 797 | var field_name = fields[i] 798 | for(j=1;#model.field_names;1){ 799 | //..console.log("choices:",..table.tostring(model.field_names[j]["choices"])) 800 | if(field_name == model.field_names[j]["name"]){ 801 | find=true; 802 | break 803 | } 804 | } 805 | if(find == false){ 806 | var msg = ..string.format("%s('%s') not in table('%s') "++'\r\n'+"sql: %s", label, field_name, model.tablename, model.sql); 807 | error(msg, 2); 808 | } 809 | } 810 | } 811 | 812 | get_required_fields = function(model){ 813 | var find = false 814 | var fields = {} 815 | for(j=1;#model.field_names;1){ 816 | //..console.log(model.field_names[j]["name"], "required:", model.field_names[j]["required"]) 817 | if(model.field_names[j]["required"]){ 818 | ..table.push(fields, model.field_names[j]["name"]) 819 | } 820 | } 821 | return fields; 822 | } 823 | 824 | } 825 | 826 | 827 | 828 | 829 | /*intellisense() 830 | sqlitemodel.Model(.(db, __, sql, filter_fields, search_fields) = !sqlitemodel_model. 831 | sqlitemodel.Model( = !sqlitemodel_model. 832 | sqlitemodel.Model() = !sqlitemodel_model. 833 | sqlitemodel.Model.now() = !sqlitemodel_model. 834 | sqlitemodel.Model.default_value(value, default) = 计算默认值 835 | sqlitemodel.Model.get_field_names(sql, true) = 计算fields_names 836 | end intellisense*/ 837 | 838 | /**intellisense(!sqlitemodel_model) 839 | get(query)= 获取某个id的数据 840 | create(query/*指定table数据对象*/) = 根据item(query)中的数据,创建一条数据 841 | update(query/*指定table数据对象*/) = 根据item(query)中的数据,更新一条数据 842 | delete(query/*指定table数据对象*/) = 根据item(query)中的数据,删除一条数据 843 | search(query/*指定table数据对象*/) = 根据item(query)中的数据,查找数据 844 | save(query/*指定table数据对象*/) = 根据item(query)中的数据,保存数据 845 | field_names = model的field_names 846 | default_value(value, default) = 计算默认值 847 | end intellisense**/ 848 | 849 | 850 | -------------------------------------------------------------------------------- /lib/sqlitemodel/modelForm.aardio: -------------------------------------------------------------------------------- 1 | //modelForm model表单窗口库 2 | 3 | import string.lcid; 4 | import sqlite; 5 | import time; 6 | import math; 7 | import console; 8 | 9 | import win.ui; 10 | import math; 11 | import config; 12 | import win.ui.accelerator; 13 | namespace sqlitemodel; 14 | 15 | import util.metaProperty; 16 | class modelForm{ 17 | ctor(model, parent, id){ 18 | 19 | 20 | //..console.log( "modelForm id",id) 21 | 22 | var data = {}; 23 | var field_names = model.field_names 24 | // 25 | //..console.varDump(field_names) 26 | // 27 | 28 | //for(i=1;#field_names;1){ 29 | // ..console.varDump(field_names[i]) 30 | //} 31 | 32 | 33 | 34 | var form_caption = ..string.format("添加%s数据", model.label); 35 | var btn_text="添加" 36 | 37 | if(id){ 38 | var query = {} 39 | query["id"] = id 40 | data = model.get(query) //如果不存在, 就会突然赋值为null了 41 | 42 | form_caption = "修改数据" 43 | btn_text = "保存" 44 | 45 | if(data == null){ 46 | data = {} 47 | } 48 | //..console.log( "modelForm data") 49 | //..console.varDump(data) 50 | } 51 | 52 | this = ..win._form(cls="";text="aardio form";border="resizable";max=false; 53 | right=642;bottom=437;parent=parent) 54 | //this = ..win.loadForm("\dlg\model_form.aardio",,parent); 55 | 56 | this.model = model; 57 | 58 | //..console.log(model.tablename) 59 | //..console.log(..table.tostring(model)) 60 | 61 | this.add( 62 | button={cls="button";text="添加公司";left=95;top=379;right=199;bottom=407;dl=1;dt=1;z=1}; 63 | checkbox={cls="checkbox";text="自动关闭本窗口";left=350;top=386;right=460;bottom=402;dl=1;dt=1;z=2} 64 | ) 65 | 66 | 67 | 68 | var frmChild_width = 0 69 | var COLS_PADDING = 5 //列与列之间的间隔, 每列由一个标签和一个文本框组成 70 | var ROWS_PER_COL = 15; 71 | var LABEL_WIDTH = 84; 72 | var EDIT_WIDTH = 320; // 420; 73 | 74 | var ROW_WIDTH = EDIT_WIDTH + COLS_PADDING*2; 75 | 76 | var LABEL_HEIGHT = 20; 77 | var EDIT_HEIGHT = 20; 78 | 79 | var ROW_HEIGHT = LABEL_HEIGHT + EDIT_HEIGHT + 5; 80 | 81 | this.width = COLS_PADDING*2 + (..math.floor((#field_names-1) / ROWS_PER_COL)+1) * ROW_WIDTH + 200; 82 | 83 | for(i=1;#field_names;1){ 84 | 85 | var k = field_names[i]["name"] 86 | var label = field_names[i]["label"] 87 | var field_type = field_names[i]["field_type"] 88 | //..console.log("modelForm ctor for loop") 89 | //var aaa = model.filter_fields; 90 | var field_choices = model.field_choices; //当sqlitemodel用_metaProperty的时候, 这一句会调用model.get("field_choices") 91 | //但是 model.filter_fields; 不会调用model.get("filter_fields");很奇怪 92 | //当sqlitemodel用_meta的时候, 并使用..table.mix(_meta, { _get = _meta}, 93 | // ..sqlitemodel._meta);就不会有这种现象 94 | //最后使用了 _meta 95 | //..console.log("modelForm ctor field_choices") 96 | //..console.varDump(field_choices) 97 | //var choices = field_names[i]["choices"] //这里会导致修改了分类后, 新建窗口不更新 98 | var field_required = field_names[i]["required"] 99 | var value = "" 100 | //..console.log("modelForm ctor init field") 101 | //..console.log(k,label) 102 | //..console.log("data:") 103 | //..console.varDump(data) 104 | //..console.log(k,"type(choices)",type(choices)) 105 | //if(#choices>0){ 106 | // ..console.varDump(choices) 107 | //} 108 | 109 | //if(type(choices) == "table"){ 110 | //这里会导致修改了分类后, 新建窗口不更新 111 | //if(#choices == 0){ 112 | var choices = {} 113 | if(field_choices){ 114 | var bind_model = field_choices[k]; 115 | if(bind_model != null){ 116 | var items = bind_model.search(); //这里会导致修改了分类后, 新建窗口不更新 117 | for(i=1;#items;1){ 118 | var s = "" 119 | //..console.log("tostring", tostring()) 120 | for(j=1; #bind_model.string_fields;1){ 121 | var sfield = bind_model.string_fields[j] 122 | s = s ++ ..string.format("%s|%s", items[i]["id"], items[i][sfield]) 123 | } 124 | ..table.push(choices, s) 125 | } 126 | } 127 | } 128 | //} 129 | //} 130 | //..console.log("..table.tostring(choices)") 131 | //..console.varDump(choices) 132 | if(#choices==0){ 133 | //如果数据库中没有数据, 用sql定义中设置的初始数据 134 | choices = field_names[i]["choices"] 135 | } 136 | 137 | 138 | if(data[k] != null){ 139 | value = tostring(data[k]) 140 | } 141 | 142 | // 143 | //log(k++":"++label) 144 | // 145 | 146 | var ctrl = this["edit_"+k] 147 | if(ctrl!=null){ 148 | ctrl.text = value 149 | }else { 150 | 151 | var staticLeft = COLS_PADDING + ..math.floor((i - 1) / ROWS_PER_COL) * ROW_WIDTH; //每一列的left是相同的。 152 | var staticTop = 13 + 22 * (i - (..math.floor((i - 1) / ROWS_PER_COL) * ROWS_PER_COL + 1)); 153 | //console.log(staticLeft,", ", staticTop) 154 | 155 | if(field_required){ 156 | this.add( 157 | ["static_" + k ] = { 158 | //border=1; 159 | cls="static"; text=label; notify=1; dl=1;dt=1; 160 | color=255;font=LOGFONT( name='宋体'; h=-13;weight=700 ); 161 | transparent=1; 162 | bottom=staticTop + LABEL_HEIGHT;right=staticLeft+LABEL_WIDTH; 163 | left=staticLeft;top=staticTop;z=1; 164 | }; 165 | ) 166 | }else { 167 | this.add( 168 | ["static_" + k ] = { 169 | //border=1; 170 | cls="static"; text=label; notify=1; dl=1;dt=1;font=LOGFONT( name='宋体' ); 171 | bottom=staticTop + LABEL_HEIGHT;right=staticLeft+LABEL_WIDTH; 172 | left=staticLeft;top=staticTop;z=1; 173 | }; 174 | ) 175 | } 176 | 177 | 178 | 179 | if(k=="id" or k=="taxno" or k=="created_at" or k=="updated_at" or k=="created" or k=="updated"){ 180 | this.add( 181 | ["edit_" + k ] = { 182 | cls="edit"; text=value; disabled=1;notify=1; dl=1;dt=1; 183 | font=LOGFONT(name='Consolas'); 184 | bottom=staticTop+EDIT_HEIGHT;right=staticLeft + EDIT_WIDTH; 185 | left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 186 | }; 187 | ) 188 | }else { 189 | 190 | if(field_required){ 191 | if(#choices >= 1){ 192 | this.add( 193 | ["edit_" + k ] = { 194 | cls="combobox"; 195 | items = choices; 196 | mode="dropdown"; 197 | tabstop=i; notify=1; db=1;dl=1;edge=1; 198 | font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT; 199 | right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 200 | required=1;name=label; 201 | }; 202 | ) 203 | }else { 204 | this.add( 205 | ["edit_" + k ] = { 206 | cls="edit"; text=value; tabstop=i; notify=1; dl=1;dt=1; 207 | font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT; 208 | right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 209 | required=1;name=label; 210 | }; 211 | ) 212 | } 213 | }else { 214 | 215 | if(#choices >= 1){ 216 | this.add( 217 | ["edit_" + k ] = { 218 | cls="combobox"; 219 | items = choices; 220 | mode="dropdown"; 221 | tabstop=i; notify=1; db=1;dl=1;edge=1; 222 | font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT; 223 | right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 224 | 225 | }; 226 | ) 227 | }else { 228 | this.add( 229 | ["edit_" + k ] = { 230 | cls="edit"; text=value; tabstop=i; notify=1; dl=1;dt=1; 231 | font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT; 232 | right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 233 | }; 234 | ) 235 | } 236 | 237 | } 238 | 239 | 240 | 241 | } 242 | 243 | 244 | 245 | 246 | // 247 | //log("ctrl edit_" + k + " 不存在!创建一个") 248 | // 249 | } 250 | } 251 | 252 | 253 | 254 | 255 | this.text = form_caption 256 | this.button.text = btn_text 257 | 258 | this.onInitDialog = function(hwnd,message,wParam,lParam){ 259 | //this.input.setFocus(); 260 | var state = ..config.settings.autoclose_model_form; 261 | // 262 | //..console.log("..config.autoclose_model_form " ++ state); 263 | // 264 | 265 | if(state == null){ 266 | state = false; 267 | } 268 | this.checkbox.checked = state; 269 | 270 | }; 271 | 272 | this.button.oncommand = function(id,event){ 273 | 274 | var field_names = this.model.field_names; 275 | var is_valid = true; 276 | for(i=1;#field_names;1){ 277 | k = field_names[i]["name"] 278 | var ctrl = this["edit_"+k]; 279 | if(ctrl==null){ 280 | continue 281 | } 282 | if(ctrl.required){ 283 | if(..string.trim(ctrl.text) == ""){ 284 | is_valid = false; //校验表单失败 285 | 286 | this.msgbox(..string.format("【%s】数据不能为空!", ctrl.name)) 287 | ctrl.setFocus(); 288 | break; 289 | } 290 | } 291 | 292 | } 293 | 294 | if(!is_valid){ 295 | return 296 | } 297 | 298 | 299 | if(this.button.text = "添加") 300 | { 301 | item = {} 302 | 303 | //..console.varDump(this["model"]) 304 | 305 | var field_names = this["model"].field_names; 306 | for(i=1;#field_names;1){ 307 | k = field_names[i]["name"] 308 | if(k=="id"){ 309 | //添加数据不需要id 310 | continue; 311 | } 312 | var ctrl = this["edit_"+k]; 313 | if(ctrl==null){ 314 | // 315 | //console.log("ctrl edit_"+k +" does not exist") 316 | // 317 | item[k] = null; 318 | continue 319 | } 320 | //..console.log("console.varDump(ctrl);") 321 | //..console.varDump(ctrl); 322 | item[k] = ctrl.text; 323 | } 324 | // 325 | //..console.varDump(item); 326 | // 327 | 328 | 329 | for(k,v in model.field_choices){ 330 | item[k] = ..string.split(item[k],"<|>")[1] 331 | } 332 | 333 | model.create(item); 334 | 335 | //this.msgbox("添加公司成功!"); 336 | //抖动文件夹 337 | hwnd = this.hwnd; 338 | if(hwnd){ 339 | ..shakewindow(hwnd,5,30) 340 | } 341 | 342 | if(this.checkbox.checked){ 343 | ..win.delay(300); 344 | this.close(); 345 | this.endModal(); 346 | }else { 347 | for(i=1;#field_names;1){ 348 | k = field_names[i]["name"] 349 | var ctrl = this["edit_"+k]; 350 | if(ctrl==null){ 351 | continue 352 | } 353 | ctrl.text=""; 354 | } 355 | } 356 | 357 | 358 | }else { 359 | if(this["edit_id"].text==""){ 360 | this.msgbox("不能保存, 不是正确的数据库id") 361 | return ; 362 | } 363 | 364 | //console.log(modelCompany.field_names) 365 | 366 | item = {} 367 | var field_names = this.model.field_names; 368 | for(i=1;#field_names;1){ 369 | k = field_names[i]["name"] 370 | var ctrl = this["edit_"+k]; 371 | if(ctrl==null){ 372 | // 373 | //console.log("ctrl edit_"+k +" does not exist") 374 | // 375 | item[k] = null; 376 | continue 377 | } 378 | //..console.log("update: console.varDump(ctrl);") 379 | //..console.varDump(ctrl); 380 | item[k] = ctrl.text; 381 | } 382 | 383 | for(k,v in model.field_choices){ 384 | item[k] = ..string.split(item[k],"<|>")[1] 385 | } 386 | 387 | //console.log("update database use new item data:---------------------") 388 | model.update(item); 389 | 390 | //console.log("reload data:---------------------") 391 | //load_company() 392 | //this.msgbox("添加公司成功!"); 393 | //抖动文件夹 394 | hwnd = this.hwnd; 395 | if(hwnd){ 396 | ..shakewindow(hwnd,5,30) 397 | } 398 | 399 | //oldRow = tonumber(this["edit_id"].text); 400 | if(this.checkbox.checked){ 401 | ..win.delay(300); 402 | this.close(); 403 | } 404 | 405 | //this.endModal( tonumber(this["edit_id"].text)); 406 | this.endModal(); 407 | 408 | 409 | } 410 | 411 | ..config.settings.autoclose_model_form = this.checkbox.checked 412 | ..config.saveAll(); 413 | 414 | //..console.log("..config.settings.autoclose_model_form", ..config.settings.autoclose_model_form, this.checkbox.checked) 415 | 416 | //restoreListviewPos(); 417 | }; 418 | 419 | 420 | /*快捷键{{*/ 421 | var accelerator = ..win.ui.accelerator({ 422 | 423 | { 424 | ctrl = true; vkey = 'S'#; //保存 425 | oncommand = function(){ 426 | this.button.oncommand() 427 | }; 428 | }; 429 | }, this); 430 | /*}}*/ 431 | 432 | 433 | 434 | this.onClose = function(){ 435 | this.endModal(); 436 | }; 437 | 438 | } 439 | 440 | } 441 | 442 | 443 | namespace modelForm{ 444 | 445 | _metaProperty = ..util.metaProperty( 446 | _type = "sqlite.modelform"; 447 | 448 | 449 | _tostring = function(format, locale){ 450 | return owner.systemFormat(format,locale); 451 | }; 452 | 453 | _serialize = function(){ 454 | return ..string.format(`..Model.ole(%s,"%s")`,tonumber(owner), owner.format); 455 | } 456 | 457 | save = function(){ 458 | 459 | } 460 | 461 | 462 | //query is table type 463 | render = function(query){ 464 | var field_names = get_field_names(owner.sql) 465 | 466 | // 467 | //..console.log("field_names") 468 | //..console.varDump(field_names) 469 | // 470 | 471 | // 472 | //..console.log("query") 473 | //..console.varDump(query) 474 | // 475 | 476 | var field_values = {} 477 | 478 | for(i=1;#field_names;1){ 479 | ..table.push(field_values, "@" ++field_names[i]["name"]) 480 | } 481 | var str_field_values = ..string.join(field_values, ", ") 482 | str_field_values = " VALUES (null, " + str_field_values ++ ");" 483 | 484 | // 485 | //console.log(str_field_values) 486 | // 487 | 488 | 489 | 490 | 491 | var command = owner.db.prepare("INSERT INTO "+ owner.tablename + str_field_values ) ; 492 | 493 | //以下非空字段, 要在for循环前绑定, 绑不上去. 494 | //command.bind.parameterByName("", "@boss_name") //给@boss_name 绑定数据 "" 495 | //command.bind.parameterByName("", "@boss_cellphone") //给@boss_cellphone 绑定数据 "" 496 | 497 | //command.bind.parameterByName("", "@charger_name") 498 | //command.bind.parameterByName("", "@charger_cellphone") 499 | 500 | //command.bind.parameterByName(time.now(), "@created") 501 | //command.bind.parameterByName(time.now(), "@updated") 502 | 503 | //给 query 设置默认值 504 | query["created_at"] = default_value(query["created_at"], ..time.now()) 505 | query["updated_at"] = default_value(query["updated_at"], ..time.now()) 506 | 507 | for(i=1;#field_names;1){ 508 | //args["@"++company_field_names[i]] = query[company_field_names[i]]; 509 | 510 | // 511 | //console.log(company_field_names[i]["name"]," ", tostring(query[company_field_names[i]["name"]])) 512 | // 513 | 514 | var field = field_names[i]["name"] 515 | var value = query[field] 516 | 517 | //给 将数据绑定到 @field 518 | command.bind.parameterByName(value, '@' + field ) 519 | 520 | } 521 | 522 | var ret = command.step(); 523 | 524 | ..console.log("sql insert result ", ret) 525 | command.finalize(); 526 | 527 | // 528 | ..console.log(command.sql); 529 | // 530 | 531 | // 532 | //console.varDump(query) 533 | // 534 | 535 | if(ret<100){ 536 | ..console.log(owner.db.lasterr()) 537 | ..console.log("insert failed!") 538 | return false; 539 | } 540 | return true 541 | } 542 | 543 | validate = function(query){ 544 | if(query["id"]==null or query["id"]==""){ 545 | //..console.log("Failed , no query['id']") 546 | return false; 547 | } 548 | 549 | // 550 | //console.varDump(query) 551 | // 552 | 553 | old_data = owner.db.stepQuery("SELECT * FROM ["+ owner.tablename +"]", { id = query["id"]}) 554 | 555 | //..console.log("get old data by id") 556 | //..console.varDump(old_data) 557 | 558 | if(old_data == null){ 559 | return false; 560 | } 561 | 562 | var stmts = {} 563 | 564 | for(k,v in query){ 565 | if(k=="created_at" or k=="updated_at"){ 566 | continue 567 | } 568 | if(old_data[k] != v){ 569 | ..table.push(stmts, " "+ k + " = @" ++ k) 570 | } 571 | } 572 | 573 | ..console.log("to be updated fileds:") 574 | ..console.varDump(stmts) 575 | 576 | 577 | if(#stmts<=0){ 578 | //console.log("no fields to be updated") 579 | return false; 580 | }else { 581 | var k = "updated_at" 582 | ..table.push(stmts, " "+ k + " = @" ++ k) 583 | query[k] = ..time.now() 584 | } 585 | 586 | 587 | var str_set_stmts = ..string.join(stmts, ", ") 588 | str_set_stmts = " SET " + str_set_stmts ++ " WHERE id = @id;" 589 | 590 | var sql = "UPDATE ["+ owner.tablename + "] " + str_set_stmts; 591 | //console.log("sql:"+sql); 592 | var updated = false; 593 | try{ 594 | owner.db.exec(sql, query); 595 | updated = true; 596 | //return true; //这里try语句里的 return true 并不能真的返回值, 函数最后返回的是null 597 | } 598 | catch(e){ 599 | //console.varDump(e); 600 | //console.log(tostring(e)) 601 | //return false;//这里try的catch语句里的 return false却可以真正使函数返回.函数最后返回的是false 602 | updated = false; 603 | } 604 | 605 | //console.log("updated!!!!") 606 | 607 | return updated 608 | }; 609 | 610 | show = function(){ 611 | 612 | }; 613 | 614 | ) 615 | } 616 | 617 | 618 | /***intellisense() 619 | sqlitemodel.modelForm = 输入对话框 620 | sqlitemodel.modelForm( = 创建一个model编辑(添加,修改)窗口 621 | sqlitemodel.modelForm(.(model, 父窗口, id) = 创建一个model编辑(添加,修改)窗口,所有参数可选\nmodel为sqlitemodel.Model 622 | sqlitemodel.modelForm() = !modelform. 623 | end intellisense***/ 624 | 625 | /***intellisense(!modelform) 626 | doModal() = 弹出输入对话框\n该函数返回用户输入的值\n取消则返回null空值 627 | onInitDialog = @.onInitDialog = function(hwnd,message,wParam,lParam){\n ??.center()__/*输入框初始化完成触发该函数*/\n} 628 | center() = 居中显示 629 | info = !edit. 630 | input = !edit. 631 | text = 输入框标题 632 | setPos(.(x,y,宽,高,插入位置,参数) = 调整窗口位置或排序\n所有参数可选 633 | getPos() = 返回相对坐标,宽,高 634 | topmost()=窗体始终最前 635 | topmost(false)=取消窗体始终最前 636 | modifyStyle(.(remove,add) = 如果指定第三个参数,则使用此参数调用::SetWidnowPos 637 | modifyStyleEx(.(remove,add) = 如果指定第三个参数,则使用此参数调用::SetWidnowPos 638 | setInterval = @var tmId = ??.setInterval( \n 1000,\n function(id){\n /*定时回调函数*/\n } \n) 639 | clearInterval(__/*请输入ID*/) = 删除定时器 640 | changeInterval(__/*请输入ID*/,1000) = 重新设定定时器的延时时间 641 | setTimeout(.(函数名,延时,其他参数) = 延时执行函数 642 | end intellisense***/ 643 | 644 | -------------------------------------------------------------------------------- /main.aardio: -------------------------------------------------------------------------------- 1 | import win.ui; 2 | import win.inputBox; 3 | import win.ui.menu; 4 | import win.ui.statusbar; 5 | import win.ui.accelerator; 6 | import win.cur; 7 | import win.ui.toolbar; 8 | 9 | import fsys; 10 | import fsys.dlg; 11 | import sqlite; 12 | import time; 13 | import config; 14 | import com.excel; 15 | import mouse; 16 | import process; 17 | 18 | import console 19 | //console.open() 20 | 21 | import sqlitemodel; 22 | import sqlitemodel.modelForm; //如果不导入, 后面调用就会报错 modelForm是null 23 | //===// 24 | /*DSG{{*/ 25 | mainForm = win.form(text="简易进销存";right=945;bottom=617) 26 | mainForm.add( 27 | btnGotoNPage={cls="button";text="转到第N页";left=650;top=353;right=724;bottom=374;db=1;dl=1;z=10}; 28 | btnNext={cls="button";text="下一页";left=385;top=353;right=450;bottom=374;db=1;dl=1;z=8}; 29 | btnPrev={cls="button";text="上一页";left=305;top=353;right=370;bottom=374;db=1;dl=1;z=7}; 30 | btnRefresh={cls="button";text="刷新";left=490;top=28;right=554;bottom=51;dl=1;dt=1;z=11}; 31 | button={cls="button";text="搜索";left=417;top=28;right=481;bottom=51;dl=1;dt=1;z=4}; 32 | button7={cls="button";text="选择显示字段";left=563;top=28;right=660;bottom=51;dl=1;dt=1;z=12}; 33 | comboCurrPage={cls="combobox";left=562;top=353;right=643;bottom=374;db=1;dl=1;edge=1;items={};mode="dropdown";z=9}; 34 | comboItemsPerpage={cls="combobox";left=215;top=354;right=293;bottom=374;db=1;dl=1;edge=1;items={"10";"20";"30";"50";"100"};mode="dropdown";z=5}; 35 | edit={cls="edit";left=163;top=28;right=408;bottom=51;dl=1;dt=1;edge=1;z=13}; 36 | listbox={cls="listbox";left=161;top=377;right=941;bottom=592;db=1;dl=1;dr=1;edge=1;hscroll=1;items={};vscroll=1;z=2}; 37 | listview={cls="listview";left=162;top=56;right=934;bottom=346;db=1;dl=1;dr=1;dt=1;edge=1;font=LOGFONT(name='Consolas');fullRow=1;gridLines=1;hscroll=1;vscroll=1;z=3}; 38 | static={cls="static";text="每页条数";left=160;top=354;right=211;bottom=369;db=1;dl=1;transparent=1;z=6}; 39 | treeview={cls="treeview";left=5;top=56;right=156;bottom=592;asel=false;bgcolor=16777215;db=1;dl=1;dt=1;edge=1;vscroll=1;z=1} 40 | ) 41 | /*}}*/ 42 | 43 | //============= 44 | newLine = '\r\n' 45 | //==== 46 | driver = null; 47 | browser = null; 48 | 49 | var mcur0 = win.cur.load(0x7F00/*_IDC_ARROW*/) 50 | var mcur1 = win.cur.load(32649/*_IDC_HAND*/) 51 | var mcur2 = win.cur.load(0x7F02/*_IDC_WAIT*/) 52 | var mcur3 = win.cur.load(0x7F88/*_IDC_NO*/) 53 | 54 | //var ss = win.cur.loadfile("e:\up_rm.cur");//这里可以是你自己制作的鼠标文件 55 | 56 | 57 | default_value = function(value, default){ 58 | if(value == null){ 59 | return default 60 | } 61 | return value 62 | } 63 | 64 | 65 | log=function(text){ 66 | mainForm.listbox.add(tostring(text)) 67 | mainForm.listbox.selIndex=mainForm.listbox.count 68 | } 69 | 70 | help = function(text){ 71 | if(text != null and text != ""){ 72 | mainForm.msgbox(tostring(text)) 73 | }else { 74 | mainForm.msgbox("如需帮助 "++newLine++newLine++"请发邮件至330906552@QQ.com") 75 | } 76 | } 77 | 78 | 79 | // 全局变量 80 | 81 | 82 | // 全局变量, 数据库路径 83 | DEFAULT_DB_PATH = "/data/biz.db" 84 | dbpath = config.settings.dbpath; 85 | 86 | 87 | var exists = io.exist(io.fullpath(dbpath)) 88 | if(exists){ 89 | log(" 数据库文件是否存在: 是", dbpath); 90 | }else { 91 | log(" 数据库文件是否存在: 否", dbpath); 92 | } 93 | 94 | DEFAULT_ITEMS_PERPAGE = 200 //默认每页显示100条 95 | LAST_ITEMS_PERPAGE = DEFAULT_ITEMS_PERPAGE; 96 | 97 | 98 | 99 | 100 | if( dbpath==null or dbpath=="" or (io.exist(io.fullpath(dbpath))==null) ){ 101 | 102 | log("数据库文件路径未设置, 请到config目录设置正确的 dbpath 参数!!!") 103 | mainForm.msgbox("数据库文件路径的文件不存在, 程序将创建和使用默认数据库!"++newLine++DEFAULT_DB_PATH) 104 | 105 | dbpath = DEFAULT_DB_PATH 106 | parentDir = fsys.getParentDir(dbpath) 107 | 108 | if(!fsys.isDir(parentDir)){ 109 | fsys.createDir(parentDir) 110 | } 111 | 112 | config.settings.dbpath=dbpath; 113 | config.saveAll() 114 | 115 | } 116 | 117 | // 全局变量, 数据库连接 118 | db = sqlite(dbpath); 119 | 120 | // 全局变量,数据库表模型定义 121 | /*company和model表定义{{*/ 122 | default_company_sql = string.load("/res/models/company.sql.aardio"); 123 | 124 | //必须的字段,改进中,按照顺序显示 125 | //这些字段,必须在导入和导出Excel中用到,还要在listview中显示 126 | //有些字段,虽然不可少, 但是可以用默认值来填充,比如时间 127 | display_headers = { 128 | "id"; 129 | "name"; 130 | "created_at"; 131 | } 132 | 133 | 134 | company_required_fields = { 135 | //类似于headers, 格式如下 136 | name="姓名"; 137 | } 138 | 139 | company_filter_fields = { 140 | "name"; 141 | } 142 | 143 | 144 | 145 | 146 | 147 | //全局变量headers, 主要是保存中文标题(含英文的字段) 148 | //用途: 149 | // listview的显示标题(中文) 150 | // 数据导出到Excel的第一行的标题(中文) 151 | headers = { 152 | //类似于 required_headers, 格式如下 153 | //zhangtaohao = "账套号"; 154 | //shebao = "社保" 155 | } 156 | 157 | 158 | 159 | 160 | company_search_fields = { 161 | "name"; 162 | }; 163 | 164 | modCompany = sqlitemodel.Model(db, 'company', 165 | default_company_sql, company_filter_fields, company_search_fields) 166 | modCompany.label = "企业"; 167 | /*}}*/ 168 | 169 | /*goods_category和model表定义{{*/ 170 | default_goods_category_sql = string.load("/res/models/goods_category.sql.aardio"); 171 | 172 | goods_category_filter_fields = { 173 | "parent"; 174 | } 175 | 176 | goods_category_search_fields = { 177 | "name"; 178 | }; 179 | 180 | goods_category_string_fields = { 181 | "name"; 182 | }; 183 | 184 | modGoodsCategory = sqlitemodel.Model(db, 'goods_category', default_goods_category_sql, 185 | goods_category_filter_fields, 186 | goods_category_search_fields, 187 | /*display_fields*/, 188 | /*field_choices*/, 189 | goods_category_string_fields 190 | ) 191 | 192 | /*}}*/ 193 | 194 | /*store和model表定义{{*/ 195 | default_store_sql = string.load("/res/models/store.sql.aardio"); 196 | 197 | store_filter_fields = { 198 | "cate"; 199 | } 200 | 201 | store_search_fields = { 202 | "name";"code"; 203 | }; 204 | 205 | modStore = sqlitemodel.Model(db, 'store', default_store_sql, 206 | store_filter_fields, 207 | store_search_fields 208 | ) 209 | modStore.label = "仓库"; 210 | /*}}*/ 211 | 212 | /*purchase和model表定义{{*/ 213 | default_purchase_sql = /**CREATE TABLE "purchase" ( 214 | "id" INTEGER NOT NULL PRIMARY KEY, 215 | "name" VARCHAR(32) NOT NULL, /*名称*/ 216 | "org" VARCHAR(16) NOT NULL, /*部门*/ 217 | "applier" VARCHAR(8) NOT NULL, /*申请人*/ 218 | "subject" VARCHAR(16), /*事由*/ 219 | "position" VARCHAR(16), /*位置*/ 220 | "cate" VARCHAR(16), /*分类*/ 221 | "from_store" VARCHAR(40), /*来源仓库*/ 222 | "to_store" VARCHAR(40), /*去向仓库*/ 223 | "created_at" DATE NOT NULL, /*创建时间*/ 224 | "updated_at" DATE NOT NULL /*更新时间*/ 225 | ); 226 | **/ 227 | 228 | purchase_filter_fields = { 229 | "cate"; 230 | } 231 | 232 | purchase_search_fields = { 233 | "name"; 234 | }; 235 | 236 | modPurchase = sqlitemodel.Model(db, 'purchase', default_purchase_sql, purchase_filter_fields, purchase_search_fields) 237 | modPurchase.label = "采购"; 238 | /*}}*/ 239 | 240 | /*supplier和model表定义{{*/ 241 | default_supplier_sql = /**CREATE TABLE "supplier" ( 242 | "id" INTEGER NOT NULL PRIMARY KEY, 243 | "name" VARCHAR(32) NOT NULL, /*名称*/ 244 | "position" VARCHAR(16), /*位置*/ 245 | "cate" VARCHAR(16), /*地址*/ 246 | "cellphone" VARCHAR(32), /*手机号码*/ 247 | "tellphone" VARCHAR(32), /*电话号码*/ 248 | "pos" INTEGER DEFAULT 0, /*排序*/ 249 | "disabled" BOOLEAN DEFAULT 0, /*禁用*/ 250 | "created_at" DATE NOT NULL, /*创建时间*/ 251 | "updated_at" DATE NOT NULL /*更新时间*/ 252 | ); 253 | **/ 254 | 255 | supplier_filter_fields = { 256 | "cate"; 257 | } 258 | 259 | supplier_search_fields = { 260 | "name"; 261 | }; 262 | 263 | modSupplier = sqlitemodel.Model(db, 'supplier', default_supplier_sql, supplier_filter_fields, supplier_search_fields) 264 | modSupplier.label = "供应商" 265 | /*}}*/ 266 | 267 | /*category和model表定义{{*/ 268 | default_category_sql = /**CREATE TABLE "category" ( 269 | "id" INTEGER NOT NULL PRIMARY KEY, 270 | "parent" INTEGER, /*父分类*/ 271 | "name" VARCHAR(32) NOT NULL, /*名称*/ 272 | "cate_type" VARCHAR(32) NOT NULL, /*名称*/ 273 | "pos" VARCHAR(16), /*排序*/ 274 | "created_at" DATE NOT NULL, /*创建时间*/ 275 | "updated_at" DATE NOT NULL /*更新时间*/ 276 | ); 277 | **/ 278 | 279 | category_filter_fields = { 280 | "cate_type"; 281 | } 282 | 283 | category_search_fields = { 284 | "name"; 285 | }; 286 | 287 | modCategory = sqlitemodel.Model(db, 'category', default_category_sql, 288 | category_filter_fields, 289 | category_search_fields 290 | ) 291 | modCategory.label = "分类" 292 | /*}}*/ 293 | 294 | /*client和model表定义{{*/ 295 | default_client_sql = /**CREATE TABLE "client" ( 296 | "id" INTEGER NOT NULL PRIMARY KEY, 297 | "name" VARCHAR(32) NOT NULL, /*名称*/ 298 | "code" VARCHAR(32), /*代码*/ 299 | "cellphone" VARCHAR(16), /*联系电话*/ 300 | "cid" INTEGER, /*分类ID*/ 301 | "cate" VARCHAR(16), /*分类*/ 302 | "org" VARCHAR(64), /*单位*/ 303 | "orgid" VARCHAR(64), /*单位ID*/ 304 | "pos" INTEGER DEFAULT 0, /*排序*/ 305 | "created_at" DATE NOT NULL, /*创建时间*/ 306 | "updated_at" DATE NOT NULL /*更新时间*/ 307 | ); 308 | **/ 309 | 310 | client_filter_fields = { 311 | "cate";"org"; 312 | } 313 | 314 | client_search_fields = { 315 | "name";"code";"cellphone"; 316 | }; 317 | 318 | modClient = sqlitemodel.Model(db, 'client', default_client_sql, client_filter_fields, client_search_fields) 319 | modClient.label = "客户" 320 | /*}}*/ 321 | 322 | /*purchase_order和model表定义{{*/ 323 | default_purchase_order_sql = /**CREATE TABLE "purchase_order" ( 324 | "id" INTEGER NOT NULL PRIMARY KEY, 325 | "name" VARCHAR(32) NOT NULL, /*名称*/ 326 | "position" VARCHAR(16), /*位置*/ 327 | "cate" VARCHAR(16), /*地址*/ 328 | "created_at" DATE NOT NULL, /*创建时间*/ 329 | "updated_at" DATE NOT NULL /*更新时间*/ 330 | ); 331 | **/ 332 | 333 | purchase_order_filter_fields = { 334 | "cate"; 335 | } 336 | 337 | purchase_order_search_fields = { 338 | "name"; 339 | }; 340 | 341 | modPurchaseOrder = sqlitemodel.Model(db, 'purchase_order', 342 | default_purchase_order_sql, 343 | purchase_order_filter_fields, 344 | purchase_order_search_fields 345 | ) 346 | modPurchaseOrder.label = "采购订单" 347 | /*}}*/ 348 | 349 | /*order_goods和model表定义{{*/ 350 | default_order_goods_sql = /**CREATE TABLE "order_goods" ( 351 | "id" INTEGER NOT NULL PRIMARY KEY, 352 | "name" VARCHAR(32) NOT NULL, /*名称*/ 353 | "position" VARCHAR(16), /*位置*/ 354 | "cate" VARCHAR(16), /*地址*/ 355 | "created_at" DATE NOT NULL, /*创建时间*/ 356 | "updated_at" DATE NOT NULL /*更新时间*/ 357 | ); 358 | **/ 359 | 360 | order_goods_filter_fields = { 361 | "cate"; 362 | } 363 | 364 | order_goods_search_fields = { 365 | "name"; 366 | }; 367 | 368 | modOrderGoods = sqlitemodel.Model(db, 'order_goods', 369 | default_order_goods_sql, 370 | order_goods_filter_fields, 371 | order_goods_search_fields 372 | ) 373 | modOrderGoods.label = "订单商品" 374 | /*}}*/ 375 | 376 | /*goods和model表定义{{*/ 377 | default_goods_sql = /**CREATE TABLE "goods" ( 378 | "id" INTEGER NOT NULL PRIMARY KEY, 379 | "name" VARCHAR(32) NOT NULL, /*名称*/ 380 | "code" VARCHAR(32) NOT NULL, /*代码*/ 381 | "cid" INTEGER, /*分类ID*/ 382 | "specs" VARCHAR(255), /*规格*/ 383 | "price" FLOAT DEFAULT 1, /*单价*/ 384 | "unit" VARCHAR(16), /*单位:个,把,包,盒,只*/ 385 | "status" VARCHAR(16), /*状态*/ 386 | "disabled" BOOLEAN DEFAULT 0, /*禁用*/ 387 | "created_at" DATE NOT NULL, /*创建时间*/ 388 | "updated_at" DATE NOT NULL /*更新时间*/ 389 | ); 390 | **/ 391 | 392 | goods_filter_fields = { 393 | "cid";"unit"; 394 | } 395 | 396 | goods_search_fields = { 397 | "name";"code"; 398 | }; 399 | 400 | goods_field_choices = { 401 | ["cid"] = modGoodsCategory; 402 | } 403 | 404 | modGoods = sqlitemodel.Model(db, 'goods', 405 | default_goods_sql, goods_filter_fields, goods_search_fields,/*display_fields*/, 406 | goods_field_choices) 407 | modGoods.label = "商品"; 408 | /*}}*/ 409 | 410 | /*goods_price和model表定义{{*/ 411 | default_goods_price_sql = /**CREATE TABLE "goods_price" ( 412 | "id" INTEGER NOT NULL PRIMARY KEY, 413 | "goods_id" INTEGER NOT NULL, /*排序*/ 414 | "name" VARCHAR(32) NOT NULL, /*名称*/ 415 | "price" FLOAT DEFAULT 1, /*单价*/ 416 | "created_at" DATE NOT NULL, /*创建时间*/ 417 | "updated_at" DATE NOT NULL /*更新时间*/ 418 | ); 419 | **/ 420 | 421 | goods_price_filter_fields = { 422 | "goods_id";"price"; 423 | } 424 | 425 | goods_price_search_fields = { 426 | "name"; 427 | }; 428 | 429 | goods_price_field_choices = { 430 | ["goods_id"] = modGoods; 431 | } 432 | 433 | modGoodsPrice = sqlitemodel.Model(db, 'goods_price', 434 | default_goods_price_sql, goods_price_filter_fields, goods_price_search_fields,/*display_fields*/, 435 | goods_price_field_choices) 436 | modGoodsPrice.label = "商品价格"; 437 | /*}}*/ 438 | 439 | 440 | /*goods_journal和model表定义{{*/ 441 | default_goods_journal_sql = /**CREATE TABLE "goods_journal" ( 442 | "id" INTEGER NOT NULL PRIMARY KEY, 443 | "ps_id" INTEGER DEFAULT 0, /*单据ID*/ 444 | "goods_id" INTEGER NOT NULL, /*商品ID*/ 445 | "name" VARCHAR(32) NOT NULL, /*名称*/ 446 | "unit" VARCHAR(16), /*单位:个,把,包,盒,只*/ 447 | "quantity" INTEGER NOT NULL, /*数量*/ 448 | "price" FLOAT DEFAULT 1, /*单价*/ 449 | "amount" DECIMAL, /*金额*/ 450 | "store_id" INTEGER NOT NULL, /*库房ID*/ 451 | "cate_id" INTEGER, /*分类ID*/ 452 | "cate_name" VARCHAR(32), /*分类名称*/ 453 | "trans_dir" VARCHAR(8), /*出入库方向*/ 454 | "trans_type" INTEGER NOT NULL, /*出入库类型*/ 455 | "trans_id" INTEGER DEFAULT 0, /*转库ID*/ 456 | "balance" INTEGER, /*库存*/ 457 | "created_at" DATE NOT NULL, /*创建时间*/ 458 | "updated_at" DATE NOT NULL /*更新时间*/ 459 | ); 460 | **/ 461 | 462 | goods_journal_filter_fields = { 463 | "store_id";"goods_id"; 464 | } 465 | 466 | goods_journal_search_fields = { 467 | "name"; 468 | }; 469 | 470 | goods_journal_field_choices = { 471 | ["goods_id"] = modGoods; 472 | } 473 | 474 | modGoodsJournal = sqlitemodel.Model(db, 'goods_journal', 475 | default_goods_journal_sql, goods_journal_filter_fields, goods_journal_search_fields,/*display_fields*/, 476 | goods_journal_field_choices) 477 | modGoodsJournal.label = "出入库记录"; 478 | /*}}*/ 479 | 480 | 481 | /*goods_trans和model表定义{{*/ 482 | default_goods_trans_sql = /**CREATE TABLE "goods_trans" ( 483 | "id" INTEGER NOT NULL PRIMARY KEY, 484 | "goods_id" INTEGER NOT NULL, /*商品ID*/ 485 | "name" VARCHAR(32) NOT NULL, /*名称*/ 486 | "quantity" INTEGER NOT NULL, /*数量*/ 487 | "amount" DECIMAL, /*金额*/ 488 | 489 | "from_store_id" INTEGER NOT NULL, /*出库ID*/ 490 | "from_store_name" VARCHAR(32), /*出库名称*/ 491 | "from_journal_id" INTEGER NOT NULL, /*出库记录ID*/ 492 | 493 | "to_store_id" INTEGER NOT NULL, /*入库ID*/ 494 | "to_store_name" VARCHAR(32), /*入库名称*/ 495 | "to_journal_id" INTEGER NOT NULL, /*入库记录ID*/ 496 | 497 | "created_at" DATE NOT NULL, /*创建时间*/ 498 | "updated_at" DATE NOT NULL /*更新时间*/ 499 | ); 500 | **/ 501 | 502 | goods_trans_filter_fields = { 503 | "from_store_id";"to_store_id"; 504 | } 505 | 506 | goods_trans_search_fields = { 507 | "name"; 508 | }; 509 | 510 | goods_trans_field_choices = { 511 | ["goods_id"] = modGoods; 512 | } 513 | 514 | modGoodsTrans = sqlitemodel.Model(db, 'goods_trans', 515 | default_goods_trans_sql, goods_trans_filter_fields, goods_trans_search_fields,/*display_fields*/, 516 | goods_trans_field_choices) 517 | modGoodsTrans.label = "转库"; 518 | /*}}*/ 519 | 520 | /*goods_balance和model表定义{{*/ 521 | default_goods_balance_sql = /**CREATE TABLE "goods_balance" ( 522 | "id" INTEGER NOT NULL PRIMARY KEY, 523 | "goods_id" INTEGER NOT NULL, /*商品ID*/ 524 | "name" VARCHAR(32) NOT NULL, /*名称*/ 525 | 526 | "store_id" INTEGER NOT NULL, /*库房ID*/ 527 | "in_quantity" INTEGER NOT NULL, /*总入库数量*/ 528 | "out_quantity" INTEGER NOT NULL, /*总出库数量*/ 529 | "balance" INTEGER, /*总库存*/ 530 | "amount" DECIMAL, /*总金额*/ 531 | "created_at" DATE NOT NULL, /*创建时间*/ 532 | "updated_at" DATE NOT NULL /*更新时间*/ 533 | ); 534 | **/ 535 | 536 | goods_balance_filter_fields = { 537 | "goods_id";"store_id"; 538 | } 539 | 540 | goods_balance_search_fields = { 541 | "name"; 542 | }; 543 | 544 | goods_balance_field_choices = { 545 | ["goods_id"] = modGoods; 546 | } 547 | 548 | modGoodsBalance = sqlitemodel.Model(db, 'goods_balance', 549 | default_goods_balance_sql, goods_balance_filter_fields, goods_balance_search_fields,/*display_fields*/, 550 | goods_balance_field_choices) 551 | modGoodsBalance.label = "库存"; 552 | /*}}*/ 553 | 554 | /*purchase_goods和model表定义{{*/ 555 | default_purchase_goods_sql = /**CREATE TABLE "purchase_goods" ( 556 | "id" INTEGER NOT NULL PRIMARY KEY, 557 | "purchase_id" INTEGER, /*采购单ID*/ 558 | "goods_id" INTEGER, /*商品ID*/ 559 | "name" VARCHAR(32), /*商品名称*/ 560 | "price" FLOAT DEFAULT 0.0, /*单价*/ 561 | "quantity" INTEGER, /*数量*/ 562 | "unit" VARCHAR(16), /*单位:个,把,包,盒,只*/ 563 | "amount" DECIMAL, /*金额*/ 564 | "disabled" BOOLEAN DEFAULT 0, /*禁用*/ 565 | "created_at" DATE NOT NULL, /*创建时间*/ 566 | "updated_at" DATE NOT NULL /*更新时间*/ 567 | ); 568 | **/ 569 | 570 | purchase_goods_filter_fields = { 571 | "purchase_id";"goods_id"; 572 | } 573 | 574 | purchase_goods_search_fields = { 575 | "name"; 576 | }; 577 | 578 | purchase_goods_field_choices = { 579 | ["purchase_id"] = modPurchase; 580 | } 581 | 582 | modPurchaseGoods = sqlitemodel.Model(db, 'purchase_goods', 583 | default_purchase_goods_sql, purchase_goods_filter_fields, purchase_goods_search_fields,/*display_fields*/, 584 | purchase_goods_field_choices) 585 | modPurchaseGoods.label = "采购商品清单"; 586 | /*}}*/ 587 | 588 | 589 | /*contact和model表定义{{*/ 590 | default_contact_sql = /**CREATE TABLE "contact" ( 591 | "id" INTEGER NOT NULL PRIMARY KEY, 592 | "cid" INTEGER, /*分类ID*/ 593 | "name" VARCHAR(32) NOT NULL, /*名称*/ 594 | "sfzhm" VARCHAR(32), /*身份证号码*/ 595 | "cellphone" VARCHAR(32) NOT NULL, /*手机号码*/ 596 | "tellphone" VARCHAR(32), /*电话号码*/ 597 | "shortnum" VARCHAR(6), /*短号*/ 598 | "note" VARCHAR(64), /*备注*/ 599 | "created_at" DATE NOT NULL, /*创建时间*/ 600 | "updated_at" DATE NOT NULL /*更新时间*/ 601 | ); 602 | **/ 603 | 604 | contact_filter_fields = { 605 | "cid"; 606 | } 607 | 608 | contact_search_fields = { 609 | "name"; 610 | "cellphone"; 611 | "tellphone"; 612 | "shortnum"; 613 | }; 614 | 615 | modContact = sqlitemodel.Model(db, 'contact', default_contact_sql, 616 | contact_filter_fields, 617 | contact_search_fields 618 | ) 619 | modContact.label = "联系人"; 620 | /*}}*/ 621 | 622 | 623 | CURR_QUERY = {}; //整个程序中的当前查询query, table数据结构 624 | CURR_MODEL = modGoods; //整个程序中的当前model 625 | mainForm.lastListviewSelected = null; 626 | mainForm.model = modGoods; 627 | 628 | mainForm.onDestroy = function(){ 629 | if(db != null){ 630 | db.close(); 631 | } 632 | } 633 | 634 | /*主菜单{{*/ 635 | var menu = win.ui.menu(mainForm);//创建主菜单 636 | //------------------------------------ 637 | var menuGoods = win.ui.popmenu(mainForm);//创建弹出菜单 638 | 639 | 640 | var idFileNew = menuGoods.add( 641 | '添加商品(&A)', 642 | function(id){ 643 | goodsform = sqlitemodel.modelForm(modGoods, mainForm); 644 | goodsform.doModal(mainForm); 645 | load_model_data(modGoods); 646 | } 647 | ); 648 | 649 | menuGoods.add( 650 | '商品分类(&C)', 651 | function(id){ 652 | goodsCategoryMgr(); 653 | } 654 | ); 655 | 656 | menuGoods.add( 657 | '商品管理(&G)', 658 | function(id){ 659 | goodsMgr(); 660 | } 661 | ); 662 | 663 | menuGoods.add(); //添加分隔线 664 | menuGoods.add( 665 | "批量导入商品", 666 | function(id){ 667 | //import_company(); 668 | var filepath = fsys.dlg.open("Excel文件(*.xsl;*xlsx)|*.xsl;*xlsx","请选择Excel文件",,mainForm) 669 | if(filepath){ 670 | import_model(modGoods, filepath); 671 | } 672 | } 673 | ) 674 | 675 | menuGoods.add(); //添加分隔线 676 | menuGoods.add( 677 | "退出(&X)", 678 | function(id){ 679 | mainForm.close() 680 | } 681 | ) 682 | 683 | 684 | menu.add('商品(&G)',menuGoods) 685 | 686 | 687 | 688 | //------------------------------------- 689 | var menuFile = win.ui.popmenu(mainForm);//创建弹出菜单 690 | menuFile.addTable({ 691 | 692 | { 693 | "采购单(&I)"; 694 | function(id){ 695 | 696 | menu_goods_purchase() 697 | 698 | } 699 | }; 700 | 701 | { 702 | "历史采购单(&I)"; 703 | function(id){ 704 | 705 | menu_goods_purchase_history() 706 | 707 | } 708 | }; 709 | 710 | { 711 | "供应商管理(&E)"; 712 | function(id){ 713 | supplierMgr(); 714 | } 715 | }; 716 | 717 | 718 | }) 719 | 720 | menu.add('入库(&R)',menuFile) 721 | //------------------------------------- 722 | 723 | var menuFile = win.ui.popmenu(mainForm);//创建弹出菜单 724 | menuFile.addTable({ 725 | 726 | { 727 | "出库单(&O)"; 728 | function(id){ 729 | //import_company(); 730 | menu_goods_sell(); 731 | } 732 | }; 733 | 734 | { 735 | "历史出库单(&I)"; 736 | function(id){ 737 | 738 | menu_goods_sell(); 739 | 740 | } 741 | }; 742 | 743 | { 744 | "客户管理(&C)"; 745 | function(id){ 746 | clientMgr(); 747 | } 748 | }; 749 | 750 | 751 | }) 752 | 753 | menu.add('出库(&C)',menuFile) 754 | //------------------------------------- 755 | var menuFile = win.ui.popmenu(mainForm);//创建弹出菜单 756 | menuFile.addTable({ 757 | 758 | { 759 | "库存查询(&I)"; 760 | function(id){ 761 | //import_company(); 762 | mainForm.msgbox("批量导入工酬数据") 763 | } 764 | }; 765 | 766 | { 767 | "物流情况(&I)"; 768 | function(id){ 769 | goodsTransMgr(); 770 | } 771 | }; 772 | 773 | { 774 | "仓库管理(&E)"; 775 | function(id){ 776 | storeMgr(); 777 | } 778 | }; 779 | 780 | 781 | }) 782 | 783 | menu.add('库存(&K)',menuFile) 784 | //------------------------------------ 785 | var menuFinance = win.ui.popmenu(mainForm);//创建弹出菜单 786 | 787 | 788 | menuFinance.add( 789 | "现金日记账", 790 | function(id){ 791 | mainForm.msgbox("现金日记账") 792 | } 793 | ) 794 | menuFinance.add(); //添加分隔线 795 | 796 | menuFinance.addTable( { 797 | { "存款日记账"; 798 | function(id){ 799 | mainForm.msgbox("存款日记账") 800 | } 801 | }; 802 | 803 | } ) 804 | menu.add('财务(&F)',menuFinance) 805 | //------------------------------------ 806 | var menuReports = win.ui.popmenu(mainForm);//创建弹出菜单 807 | 808 | 809 | menuReports.add( 810 | "采购报表", 811 | function(id){ 812 | mainForm.msgbox("版权所有") 813 | } 814 | ) 815 | 816 | menuReports.addTable( { 817 | { "销售报表"; 818 | function(id){ 819 | mainForm.msgbox("如需帮助 "++newLine++newLine++"请发邮件至330906552@QQ.com") 820 | } 821 | }; 822 | 823 | {}; 824 | 825 | { "客户销量"; 826 | function(id){ 827 | help(); 828 | } 829 | }; 830 | 831 | 832 | { "商品销量"; 833 | function(id){ 834 | mainForm.msgbox("如需帮助 "++newLine++newLine++"请发邮件至330906552@QQ.com") 835 | } 836 | }; 837 | 838 | } ) 839 | 840 | menu.add('报表(&B)',menuReports) 841 | 842 | //---------------------------------------- 843 | menu.addTable( { 844 | 845 | 846 | { "设置(&S)"; 847 | { 848 | { "选项(&O)"; 849 | function(id){ 850 | 851 | config_setting(); 852 | 853 | } 854 | }; 855 | 856 | { "商品管理(&G)"; 857 | function(id){ 858 | goodsMgr(); 859 | } 860 | }; 861 | 862 | { "客户管理(&Z)"; 863 | function(id){ 864 | clientMgr(); 865 | } 866 | }; 867 | { "供应商管理(&S)"; 868 | function(id){ 869 | supplierMgr(); 870 | } 871 | }; 872 | { "仓库设置(&Y)"; 873 | function(id){ 874 | storeMgr(); 875 | } 876 | }; 877 | { "出入库流水账(&Y)"; 878 | function(id){ 879 | journalMgr(); 880 | } 881 | }; 882 | { "通讯录(&C)"; 883 | function(id){ 884 | contactMgr(); 885 | } 886 | } 887 | 888 | } 889 | }; 890 | 891 | /**{ "数据库(&R)"; 892 | { 893 | { 894 | "备份数据库(&B)"; 895 | function(id){ 896 | 897 | var items = {} 898 | items = db.getTable("SELECT * FROM [company] ") 899 | export_company(items); 900 | } 901 | }; 902 | 903 | {}; 904 | 905 | 906 | } 907 | }; **/ 908 | 909 | } ) 910 | //------------------------------------ 911 | var menuTools = win.ui.popmenu(mainForm);//创建弹出菜单 912 | menuTools.addTable({ 913 | 914 | { 915 | "计算器(&I)"; 916 | function(id){ 917 | process.execute("calc.exe") 918 | } 919 | }; 920 | 921 | 922 | { /*---分隔线---*/ }; 923 | 924 | }) 925 | 926 | menu.add('工具(&T)',menuTools) 927 | 928 | 929 | 930 | 931 | 932 | 933 | 934 | //------------------------------------ 935 | var menuHelp = win.ui.popmenu(mainForm);//创建弹出菜单 936 | 937 | 938 | menuHelp.add( 939 | "关于", 940 | function(id){ 941 | mainForm.msgbox("版权所有") 942 | } 943 | ) 944 | menuHelp.add(); //添加分隔线 945 | 946 | menuHelp.addTable( { 947 | { "帮助"; 948 | function(id){ 949 | mainForm.msgbox("如需帮助 "++newLine++newLine++"请发邮件至330906552@QQ.com") 950 | } 951 | }; 952 | 953 | } ) 954 | menu.add('帮助(&H)',menuHelp) 955 | 956 | //主菜单构建完成后要用下面这句更新,menu.addTable()会自动调用redraw() 957 | menu.redraw(); 958 | 959 | /*}}*/ 960 | 961 | /*菜单函数{{*/ 962 | clientMgr = function(){ 963 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 964 | frmChild.init(modClient); 965 | frmChild.doModal(mainForm); 966 | 967 | 968 | 969 | } 970 | 971 | 972 | supplierMgr = function(){ 973 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 974 | frmChild.init(modSupplier); 975 | frmChild.doModal(mainForm); 976 | } 977 | 978 | storeMgr = function(){ 979 | 980 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 981 | frmChild.init(modStore); 982 | frmChild.doModal(mainForm); 983 | } 984 | 985 | journalMgr = function(){ 986 | 987 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 988 | frmChild.init(modGoodsJournal); 989 | frmChild.doModal(mainForm); 990 | } 991 | 992 | contactMgr = function(){ 993 | 994 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 995 | frmChild.init(modContact); 996 | frmChild.doModal(mainForm); 997 | } 998 | 999 | goodsCategoryMgr = function(){ 1000 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 1001 | frmChild.init(modGoodsCategory); 1002 | //使用_metaProperty, modGoodsCategory.filter_fields 不会调用model.get("filter_fields") 1003 | //console.log("modGoodsCategory.filter_fields",modGoodsCategory.filter_fields); 1004 | //奇怪的是: 1005 | //使用_metaProperty, modGoodsCategory.field_choices 会调用model.get("field_choices") 1006 | //console.log("modGoodsCategory.field_choices", modGoodsCategory.field_choices); 1007 | 1008 | frmChild.doModal(mainForm); 1009 | } 1010 | 1011 | goodsMgr = function(){ 1012 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 1013 | frmChild.init(modGoods); 1014 | frmChild.doModal(mainForm); 1015 | } 1016 | 1017 | goodsTransMgr = function(){ 1018 | var frmChild = mainForm.loadForm("\dlg\model_list.aardio"); 1019 | frmChild.init(modGoodsTrans); 1020 | frmChild.doModal(mainForm); 1021 | } 1022 | 1023 | 1024 | /*}}*/ 1025 | 1026 | /*工具条{{*/ 1027 | var toolbar = win.ui.toolbar(mainForm); 1028 | toolbar.create( style = 0x1000/*_TBSTYLE_LIST*/ ); // 创建工具条 1029 | toolbar.showLabel = true; //在按钮上显示文字 1030 | toolbar.imageList = win.imageList( 16, 16 ).add($"\res\toolbar.gif",0xFF00FF/*透明色*/) ; 1031 | 1032 | toolbar.add();// 添加分隔条 1033 | toolbar.add( "新建", , 1, idFileNew/*重用现有命令ID*/ ); 1034 | 1035 | toolbar.add( 1036 | "采购", 1037 | function (id) { 1038 | menu_goods_purchase(); 1039 | }, 2 1040 | ); 1041 | 1042 | toolbar.add( 1043 | "禁用", 1044 | function (id) { 1045 | toolbar.getButton(4).disabled = false; 1046 | toolbar.getButtonById(id).disabled = true; 1047 | }, 3 1048 | ); 1049 | toolbar.add( 1050 | "禁用2", 1051 | , 4 1052 | ); 1053 | 1054 | /*}}*/ 1055 | 1056 | /*快捷键{{*/ 1057 | var accelerator = win.ui.accelerator({ 1058 | { 1059 | vkey = 0x70/*_VK_F1*/; //进货 1060 | oncommand = function(){ 1061 | menu_goods_purchase() 1062 | }; 1063 | }; 1064 | 1065 | { 1066 | vkey = 0x71/*_VK_F2*/; //销货 1067 | oncommand = function() mainForm.msgbox("销货"); 1068 | }; 1069 | 1070 | { 1071 | vkey = 0x72/*_VK_F3*/; //存货 1072 | oncommand = function() mainForm.msgbox("存货"); 1073 | }; 1074 | 1075 | { 1076 | vkey = 0x73/*_VK_F4*/; //财务 1077 | oncommand = function() mainForm.msgbox("财务"); 1078 | }; 1079 | 1080 | { 1081 | vkey = 0x74/*_VK_F5*/; //商品 1082 | oncommand = function(){ 1083 | //发消息到 前面定义好的菜单项, 要转换为pointer 1084 | ::SendMessage(mainForm.hwnd, 0x111/*_WM_COMMAND*/, topointer(idFileNew), topointer(0)); 1085 | } 1086 | }; 1087 | 1088 | { 1089 | vkey = 0x75/*_VK_F6*/; //报表 1090 | oncommand = function() mainForm.msgbox("报表"); 1091 | }; 1092 | 1093 | //F10:用来激活Windows或程序中的菜单,按下Shift+F10会出现右键快捷菜单。 1094 | //如果你先按了F10, 那么F1, F2按的时候可能会失效, 只要再按一次F10, 或者按ESC退出F10的菜单模式. 1095 | 1096 | { 1097 | vkey = 0x7B/*_VK_F12*/; //盘库 1098 | oncommand = function() mainForm.msgbox("盘库"); 1099 | }; 1100 | 1101 | { 1102 | ctrl = true; vkey = '1'#; //分类 1103 | oncommand = function(){ 1104 | goodsform = sqlitemodel.modelForm(modGoods, mainForm); 1105 | goodsform.doModal(mainForm); 1106 | load_model_data(modGoods); 1107 | } 1108 | }; 1109 | 1110 | { 1111 | ctrl = true; vkey = '2'#; // 1112 | oncommand = function() mainForm.msgbox("Ctrl+2"); 1113 | }; 1114 | 1115 | { 1116 | ctrl = true; vkey = '3'#; // 1117 | oncommand = function() mainForm.msgbox("Ctrl+3"); 1118 | }; 1119 | 1120 | { 1121 | ctrl = true; vkey = '`'#; //没反应不知道怎么回事 1122 | oncommand = function() mainForm.msgbox("Ctrl+`"); 1123 | }; 1124 | 1125 | { 1126 | ctrl = true; vkey = 'N'#; //没反应不知道怎么回事 1127 | oncommand = function(){ 1128 | goodsform = sqlitemodel.modelForm(modGoods, mainForm); 1129 | goodsform.doModal(mainForm); 1130 | load_model_data(modGoods); 1131 | }; 1132 | }; 1133 | 1134 | { 1135 | ctrl = true; vkey = 'A'#; //全选 1136 | oncommand = function(){ 1137 | mainForm.listview.setFocus(); 1138 | for(i=1;mainForm.listview.count;1){ 1139 | mainForm.listview.setSelected(i) 1140 | } 1141 | }; 1142 | }; 1143 | 1144 | 1145 | 1146 | 1147 | }, mainForm); 1148 | /*}}*/ 1149 | 1150 | 1151 | import_model = function(model, filepath){ 1152 | // 从excel中导入某个model的数据信息,必须的字段,定义在全局变量headers里 1153 | // 其中的字段,在excel中必须有(主要是中文的标题要一致) 1154 | // 理想的导入,就是 1155 | // 1. 【已实现】给一个Excel表,用电脑自带的office的com接口打开 1156 | // 2. 【已实现】先检查第一行的标题,从第1列检查到最后一列的标题 1157 | // 3. 如果标题在数据库的字段里,就保留,并登记好对应第几列 1158 | // 4. 如果标题不在数据库的字段里,就舍弃 1159 | // 5. 如果数据库中的字段,并不在Excel的标题里,即缺少数据库必须的字段,则终止报错 1160 | // 1161 | var TABLE_NAME = model.tablename 1162 | var header_cols={} //Excel中的标题在第N列, 则model.headers中的英文Key对应在第N列 1163 | //数据导入用 1164 | for(k,v in model.headers){ 1165 | //model.headers 是 {"name"="中文" ;...} 1166 | //标题位于第几列(第1列是A列,第2列是B列...), 1167 | //初始化默认设置为0列(默认不正常,正常的列应该从1开始). 1168 | header_cols[k]=0; 1169 | } 1170 | 1171 | //导入的时候,忽略以下字段 1172 | header_cols["id"] = null; 1173 | header_cols["created_at"] = null; 1174 | header_cols["updated_at"] = null; 1175 | 1176 | var required_cols = { 1177 | //类似与header_cols 1178 | } 1179 | 1180 | //数据导入用 1181 | for(i=1;#model.required_fields;1){ 1182 | k = model.required_fields[i]; 1183 | //标题位于第几列(第1列是A列,第2列是B列...), 1184 | //初始化默认设置为0列(默认不正常,正常的列应该从1开始). 1185 | required_cols[k]=0; 1186 | } 1187 | 1188 | required_cols["id"] = null; 1189 | required_cols["created_at"] = null; 1190 | required_cols["updated_at"] = null; 1191 | 1192 | if(io.exist(filepath)){ 1193 | var excel = com.excel(); 1194 | excel.Visible = true; 1195 | var workbook = excel.Open( filepath ) 1196 | 1197 | sheet = workbook.Sheets(1); //默认只处理第一个标签 1198 | 1199 | var colCount = excel.Sheets(1).UsedRange.Columns.Count; //多少列 1200 | var rowCount = excel.Sheets(1).UsedRange.Rows.Count; //多少行 1201 | var cimP = excel.Sheets(1).Cells(1,colCount).value2; 1202 | var cellValue; 1203 | 1204 | var msgs ={info = {};errors={};warning={}} 1205 | win.cur.setCur(mcur2); //鼠标设置为忙碌状态, 使用户不去进行其他操作 1206 | 1207 | //【读取第1行】,第1行必须是标题,且标题必须在headers中定义好 1208 | //根据第1行的标题, 在headers中查找,是否存在 1209 | //然后反过来设置查header_cols表,该标题对应第几列 1210 | //比如 假设第5列的标题AAA,在headers的values中, 就在 1211 | //header_cols中设置header_cols[k]=5, 这个k是headers中headers[k]=AAA的k 1212 | for(i=1;colCount;1){ 1213 | var cellValue = excel.Sheets(1).Cells(1,i).value2; 1214 | log("第"++i++"列: "++tostring(cellValue)) //第i列是什么标题, 标题是汉字 1215 | 1216 | // header_cols, 可选字段所在列, 可选字段是包含全部字段的. 1217 | 1218 | for(k,v in model.headers){ 1219 | //遍历model.headers, 查找excel中的标题是否在headers里 1220 | //k 是英文字段名, v是中文字段名 1221 | //在 header_cols 设置该标题在headers中的key, 对应第几列数据 1222 | //【TODO】: 这里的循环有个逻辑问题, 就是外面的标题(cellValue), 1223 | //如果Excel中的标题有重复的, 就会有问题.除非两个同名列内容是一样的。 1224 | if(v==cellValue){ 1225 | if(required_cols[k] != null){ 1226 | //看看必须字段中, 是否有这个可选字段, 如果有, 设置所在列为i 1227 | required_cols[k]=i; //key->123 1228 | } 1229 | 1230 | header_cols[k]=i; //key->123 1231 | } 1232 | } 1233 | } 1234 | 1235 | 1236 | for(k,v in required_cols){ 1237 | var msg = "" 1238 | if(v==0){ 1239 | msg = "!!!!Excel文件不符合规范, 文件第1行标题行缺少 '"++model.headers[k]++"' 列, 程序将无法运行!" 1240 | 1241 | table.push(msgs.errors, msg) 1242 | } 1243 | } 1244 | 1245 | 1246 | 1247 | for(k,v in header_cols){ 1248 | // 1249 | //console.log(k,v, headers[k]) 1250 | // 1251 | var msg = "" 1252 | if(v==0){ 1253 | msg = "!!!!Excel文件不完善, 文件第1行标题行缺少 '"++model.headers[k]++"' 列, 可以导入, 但是不保证数据完整" 1254 | 1255 | table.push(msgs.warning, msg) 1256 | } 1257 | } 1258 | 1259 | /* 1260 | required_cols = { 1261 | 1262 | key1 = 0; 1263 | key2 = 2; 1264 | key3 = 1; 1265 | ... 1266 | } 1267 | */ 1268 | 1269 | 1270 | if(#msgs.errors>0){ 1271 | for(i=1;#msgs.errors;1){ 1272 | log(msgs.errors[i]) 1273 | } 1274 | return; 1275 | 1276 | } 1277 | 1278 | if(#msgs.warning>0){ 1279 | for(i=1;#msgs.warning;1){ 1280 | log(msgs.warning[i]) 1281 | } 1282 | } 1283 | 1284 | var items = {} //每次导入都初始化一次 1285 | 1286 | 1287 | //从第2行开始读取数据 1288 | for(iRow=2;sheet.UsedRange.Rows.Count;1){ 1289 | //////log("第"++ iRow ++ "行") 1290 | data = {} 1291 | for(k,v in header_cols){ 1292 | var currentKeyCol = header_cols[k] 1293 | 1294 | //log(k++"当前列:"++currentKeyCol) 1295 | 1296 | if(currentKeyCol==0){ 1297 | msg = "!!!!列的index为0,跳过忽略第 '"++iRow++"' 行数据!" 1298 | table.push(msgs.warning, msg) 1299 | continue; //列的index为0, 会出错, 跳过, 即忽略这一行数据 1300 | } 1301 | 1302 | data[k] = default_value(sheet.Cells(iRow, currentKeyCol).getValue2(), ""); 1303 | 1304 | } 1305 | 1306 | //////for(k,v in data){ 1307 | ////// log(headers[k] ++ ":" ++ tostring(v) +" ") // + tostring(type(v))) 1308 | //////} 1309 | //////log("") 1310 | 1311 | table.push(items, data); 1312 | 1313 | 1314 | } 1315 | 1316 | for(i=1;#items;1){ 1317 | var item = items[i] 1318 | 1319 | //var tab_text = {tostring(i)} //初始化序号id, 因为前面剔除了 1320 | //for(j=1;#display_headers;1){ 1321 | // var v = data[display_headers[j]] 1322 | // if(v != null){ 1323 | // table.push(tab_text, v) 1324 | // } 1325 | //} 1326 | 1327 | 1328 | var r = model.create(item); 1329 | 1330 | //if(r){//添加成功, 就加到listview中 1331 | // mainForm.listview.addItem({ 1332 | // text=tab_text 1333 | // }); 1334 | //} 1335 | 1336 | } 1337 | 1338 | //不再一条一条的往listview中添加. 直接加载数据库 1339 | //因为一条一条添加, 未能正确设置id 1340 | //load_model_data(model) 1341 | mainForm.msgbox("导入成功,请刷新窗口数据") 1342 | 1343 | win.cur.setCur(mcur0);//复原鼠标 1344 | 1345 | }else { 1346 | mainForm.msgbox("未选择数据表!") 1347 | } 1348 | 1349 | } 1350 | 1351 | 1352 | /*export_model{{*/ 1353 | export_model = function(model, items, fields){ 1354 | // 导出公司数据 1355 | // 1. 根据model.headers中定义的字段进行导出(必须包含的字段) 1356 | // 2. 根据items进行导出, 每个item都是一个table 1357 | // 是不是要给个框框, 让用户选择字段? 1358 | 1359 | var flat_items = {} 1360 | var display_fields = {} //获取全部显示的fields, 或者用户自定义的fields 1361 | 1362 | 1363 | if(fields == null){ 1364 | var ub = #model.field_names 1365 | 1366 | //console.log("--------model.field_names"); 1367 | //console.varDump(table.map(model.field_names,lambda(x) x.name)); 1368 | 1369 | 1370 | //从全局变量model.field_names中获取field 1371 | for(i=1;ub;1){ 1372 | table.push(display_fields, model.field_names[i]["name"]) 1373 | } 1374 | 1375 | //剔除以下字段 1376 | table.removeByValue(display_fields, "created_at"); 1377 | table.removeByValue(display_fields, "updated_at"); 1378 | 1379 | }else { 1380 | if(type(fields)!= type.table){ 1381 | mainForm.msgbox("程序错误, 参数display_fields类型不正确, 应该为table") 1382 | return 1383 | }else { 1384 | display_fields = fields; 1385 | } 1386 | } 1387 | 1388 | console.log("--------display_fields"); 1389 | console.varDump(display_fields); 1390 | 1391 | //检查是否露了必须的字段, 没有就加进去 1392 | //比如前面去掉的created_at,这里又加回去了 1393 | for(i=1;#model.required_fields;1){ 1394 | if(table.find(display_fields, model.required_fields[i])){ 1395 | 1396 | }else { 1397 | table.push(display_fields, model.required_fields[i]) 1398 | } 1399 | 1400 | } 1401 | 1402 | if(#display_fields <= 0){ 1403 | mainForm.msgbox("程序错误, 数据字段display_fields未正确设置") 1404 | return 1405 | } 1406 | 1407 | // 1408 | //console.varDump(display_fields) 1409 | // 1410 | 1411 | //将items变为平展的数据, 即{"";"";"";...""}这种,可以快速给excel的一行赋值 1412 | for(i=1;#items;1){ 1413 | item = {} 1414 | for(j=1;#display_fields;1){ 1415 | var k = display_fields[j]; 1416 | var value = string.trimright(default_value(items[i][k], "")); 1417 | table.push(item, value) 1418 | } 1419 | table.push(flat_items, item); 1420 | } 1421 | 1422 | if(#flat_items<=0){ 1423 | mainForm.msgbox("无数据,或者未选中数据") 1424 | return 1425 | } 1426 | 1427 | import com.excel; 1428 | 1429 | var excel = com.excel(); 1430 | excel.Visible = 0xC/*_xlVisible*/; 1431 | var wkbook = excel.WorkBooks.Add(); 1432 | var sheet = wkbook.Sheets(1); 1433 | 1434 | excel.ActiveWorkbook.Sheets(1).Select(); 1435 | 1436 | //表头标题行,第1行 1437 | for(i=1;#display_fields;1){ 1438 | //从全局变量headers中获取field的中文标题 1439 | sheet.Cells(1,i).value2 = model.headers[display_fields[i]] 1440 | } 1441 | 1442 | var item_count = #flat_items + 1 1443 | 1444 | //cells(row1,col1),cells(row2,col2) 1445 | 1446 | //sheet.Range("A2:G"+item_count).value2= mainForm.listview.items 1447 | // 1448 | //for(k,v in items){ 1449 | // console.varDump(v) 1450 | //} 1451 | // 1452 | //console.log(#display_fields,0, #flat_items[1]) 1453 | //起点单元格, 终点单元格,宽度为7, items的宽度为9 1454 | //最后导出的数据就只有7列 1455 | sheet.Range(sheet.Cells(2,1), sheet.Cells(item_count, #display_fields)).value2 = flat_items;//Excel行快速赋值 1456 | var tm = time.now() 1457 | 1458 | newFilename = tostring(tm, "\" + model.tablename + "-%Y%m%d%H%M%S.xlsx", "chs"); 1459 | 1460 | log("导出文件至:" + io.fullpath(newFilename)) 1461 | 1462 | wkbook.SaveAs(io.fullpath(newFilename),0x33/*_xlOpenXMLWorkbook*/) 1463 | 1464 | wkbook.close(); 1465 | excel.Quit(); 1466 | 1467 | process.exploreSelect(io.fullpath(newFilename)); 1468 | } 1469 | /*}}*/ 1470 | 1471 | shakewindow = function(hwnd,r,s){ 1472 | x,y=win.getPos(hwnd) 1473 | win.setPos(hwnd,x-r,y-r) 1474 | win.delay(s) 1475 | win.setPos(hwnd,x+r,y-r) 1476 | win.delay(s) 1477 | win.setPos(hwnd,x+r,y+r) 1478 | win.delay(s) 1479 | win.setPos(hwnd,x-r,y+r) 1480 | win.delay(s) 1481 | win.setPos(hwnd,x,y) 1482 | } 1483 | 1484 | 1485 | 1486 | /*add_company{{*/ 1487 | add_company = function(query, default_sql){ 1488 | 1489 | var field_names = get_field_names(default_sql) 1490 | 1491 | // 1492 | //console.log("field_names") 1493 | //console.varDump(field_names) 1494 | // 1495 | 1496 | var field_values = {} 1497 | 1498 | for(i=1;#field_names;1){ 1499 | table.push(field_values, "@" ++field_names[i]["name"]) 1500 | } 1501 | var str_field_values = string.join(field_values, ", ") 1502 | str_field_values = " VALUES (null, " + str_field_values ++ ");" 1503 | 1504 | // 1505 | //console.log(str_field_values) 1506 | // 1507 | 1508 | 1509 | 1510 | 1511 | var command = db.prepare("INSERT INTO "+ TABLE_NAME + str_field_values ) ; 1512 | 1513 | //以下非空字段, 要在for循环前绑定, 绑不上去. 1514 | //command.bind.parameterByName("", "@boss_name") //给@boss_name 绑定数据 "" 1515 | //command.bind.parameterByName("", "@boss_cellphone") //给@boss_cellphone 绑定数据 "" 1516 | 1517 | //command.bind.parameterByName("", "@charger_name") 1518 | //command.bind.parameterByName("", "@charger_cellphone") 1519 | 1520 | //command.bind.parameterByName(time.now(), "@created") 1521 | //command.bind.parameterByName(time.now(), "@updated") 1522 | 1523 | //给item设置默认值 1524 | query["boss_name"] = default_value(query["boss_name"], "") 1525 | query["boss_cellphone"] = default_value(query["boss_cellphone"], "") 1526 | 1527 | query["charger_name"] = default_value(query["charger_name"], "") 1528 | query["charger_cellphone"] = default_value(query["charger_cellphone"], "") 1529 | 1530 | query["created"] = default_value(query["created"], time.now()) 1531 | query["updated"] = default_value(query["updated"], time.now()) 1532 | 1533 | 1534 | for(i=1;#field_names;1){ 1535 | 1536 | var field = field_names[i]["name"] 1537 | var value = query[field] 1538 | 1539 | //给 将数据绑定到 @field 1540 | command.bind.parameterByName(value, '@'+ field ) 1541 | 1542 | } 1543 | 1544 | 1545 | 1546 | 1547 | 1548 | 1549 | var ret = command.step(); 1550 | 1551 | //console.log("sql insert result ", ret) 1552 | command.finalize(); 1553 | 1554 | // 1555 | //console.log(command.sql); 1556 | // 1557 | 1558 | // 1559 | //console.varDump(query) 1560 | // 1561 | 1562 | if(ret<100){ 1563 | log(db.lasterr()) 1564 | log("insert failed!") 1565 | return false; 1566 | } 1567 | return true 1568 | } 1569 | /*}}*/ 1570 | 1571 | /*edit_company{{*/ 1572 | edit_company = function(query){ 1573 | if(query["id"]==null or query["id"]==""){ 1574 | //log("Failed , no query['id']") 1575 | return false; 1576 | } 1577 | 1578 | // 1579 | //console.varDump(query) 1580 | // 1581 | 1582 | old_data = db.stepQuery("SELECT * FROM ["+ TABLE_NAME +"]", { id = query["id"]}) 1583 | 1584 | //console.log("get old data by id") 1585 | //console.varDump(old_data) 1586 | 1587 | var stmts = {} 1588 | 1589 | for(k,v in query){ 1590 | if(k=="created" or k=="updated"){ 1591 | continue 1592 | } 1593 | if(old_data[k] != v){ 1594 | table.push(stmts, " "+ k + " = @" ++ k) 1595 | } 1596 | } 1597 | 1598 | //console.log("to be updated fileds:") 1599 | //console.varDump(stmts) 1600 | 1601 | 1602 | if(#stmts<=0){ 1603 | //console.log("no fields to be updated") 1604 | return false; 1605 | }else { 1606 | var k = "updated" 1607 | table.push(stmts, " "+ k + " = @" ++ k) 1608 | query[k]=time.now() 1609 | } 1610 | 1611 | 1612 | var str_set_stmts = string.join(stmts, ", ") 1613 | str_set_stmts = " SET " + str_set_stmts ++ " WHERE id = @id;" 1614 | 1615 | //console.log("str_set_stmts") 1616 | 1617 | //console.log(str_set_stmts) 1618 | 1619 | 1620 | 1621 | 1622 | var sql = "UPDATE ["+ TABLE_NAME + "] " + str_set_stmts; 1623 | //console.log("sql:"+sql); 1624 | var updated = false; 1625 | try{ 1626 | db.exec(sql, query); 1627 | updated = true; 1628 | //return true; //这里try语句里的 return true 并不能真的返回值, 函数最后返回的是null 1629 | } 1630 | catch(e){ 1631 | //console.varDump(e); 1632 | //console.log(tostring(e)) 1633 | //return false;//这里try的catch语句里的 return false却可以真正使函数返回.函数最后返回的是false 1634 | updated = false; 1635 | } 1636 | 1637 | 1638 | 1639 | 1640 | /* 1641 | 1642 | command.bind.parameterByName("", "@boss_name") 1643 | command.bind.parameterByName("", "@boss_cellphone") 1644 | 1645 | command.bind.parameterByName("", "@charger_name") 1646 | command.bind.parameterByName("", "@charger_cellphone") 1647 | 1648 | command.bind.parameterByName(time.now(), "@created") 1649 | command.bind.parameterByName(time.now(), "@updated") 1650 | 1651 | */ 1652 | //console.log("updated!!!!") 1653 | 1654 | return updated 1655 | } 1656 | /*}}*/ 1657 | 1658 | /*load_model_data{{*/ 1659 | load_model_data = function(model, user_query){ 1660 | var items={}; 1661 | var query = {} 1662 | if(type(user_query)=="table"){ 1663 | query = user_query 1664 | }elseif(type(user_query)=="string"){ 1665 | query["keyword"] = user_query; 1666 | } 1667 | query["QUERY_MODE"] = "SEARCH"; 1668 | query["model_name"] = model.tablename; 1669 | CURR_QUERY = query; //记录到全局变量CURR_QUERY中 1670 | CURR_MODEL = model; 1671 | log(table.tostring(CURR_QUERY)); 1672 | items = model.search(query); 1673 | console.log("items count:" ++ #items) 1674 | 1675 | reset_listview(model, items); 1676 | initTreeviewFilters(model) 1677 | 1678 | 1679 | } 1680 | /*}}*/ 1681 | 1682 | 1683 | 1684 | /*reset_listview{{*/ 1685 | reset_listview = function(model, items){ 1686 | 1687 | mainForm.statusbar.setText("数据总数:" + #items); 1688 | 1689 | //如果获取了数据, 那么清空listview 1690 | if(#items>=1){ 1691 | mainForm.listview.clear(); 1692 | }else { 1693 | mainForm.listview.clear(); 1694 | return 1695 | } 1696 | 1697 | var n = mainForm.listview.columnCount; 1698 | for(i=1;n;1){ 1699 | mainForm.listview.delColumn(n+1-i);//从倒数开始删除, 以免删除前面的, 后面的索引都变了. 1700 | } 1701 | 1702 | 1703 | for(i=1;#model.display_fields;1){ 1704 | var k = model.display_fields[i] 1705 | var caption = model.headers[k] 1706 | mainForm.listview.insertColumn(caption, 80, i); 1707 | } 1708 | 1709 | mainForm.listview.setColumn({cx=40},1) 1710 | mainForm.listview.setColumn({cx=180},2) 1711 | mainForm.listview.setColumn({cx=100},3) 1712 | 1713 | 1714 | 1715 | for(i=1;#items;1){ 1716 | 1717 | var data ={} 1718 | for(j=1;#model.display_fields;1){ 1719 | k = model.display_fields[j]; 1720 | //if(k=="id"){ 1721 | // table.push(data, tostring(i)) 1722 | // continue 1723 | //} 1724 | //console.log('k', k); 1725 | if(items[i][k]!=null){ 1726 | table.push(data, items[i][k]) 1727 | }else { 1728 | table.push(data, "") 1729 | } 1730 | 1731 | 1732 | } 1733 | // 1734 | //console.varDump(items[i]) 1735 | // 1736 | 1737 | mainForm.listview.addItem({ 1738 | text = data 1739 | }); 1740 | } 1741 | 1742 | if(items["ITEMS_PERPAGE"]){ 1743 | mainForm.comboItemsPerpage.text = tostring(items["ITEMS_PERPAGE"]) 1744 | } 1745 | if(items["PAGES"]){ 1746 | mainForm.comboCurrPage.clear(); 1747 | for(i=1;items["PAGES"];1){ 1748 | mainForm.comboCurrPage.add(tostring(i)) 1749 | } 1750 | } 1751 | if(items["CURR_PAGE"]!=null){ 1752 | mainForm.comboCurrPage.text = tostring(items["CURR_PAGE"]+1) 1753 | } 1754 | } 1755 | /*}}*/ 1756 | 1757 | initTreeviewFilters = function(model){ 1758 | 1759 | var filter_fields = model.filter_fields 1760 | if(#filter_fields>0){ 1761 | mainForm.treeview.clear(); 1762 | } 1763 | 1764 | var item = {text = "显示全部数据"} 1765 | var hItem = mainForm.treeview.insertItem(item) 1766 | 1767 | console.log("filter_fields:") 1768 | console.varDump(filter_fields) 1769 | 1770 | for(i=1;#filter_fields;1){ 1771 | var item = {} 1772 | /*{ 1773 | text = "按区划分"; 1774 | { 1775 | { text = "芙蓉区"; filter_field ="furong" }; 1776 | { text = "天心区"; filter_field ="tianxin" }; 1777 | { text = "岳麓区" }; 1778 | { text = "开福区" }; 1779 | { text = "雨花区" }; 1780 | { text = "未分区" }; 1781 | } 1782 | }*/ 1783 | 1784 | 1785 | 1786 | var field = filter_fields[i] 1787 | var caption = model.headers[field] 1788 | 1789 | item["text"] = string.format("按%s过滤", caption); 1790 | item["field"] = "" 1791 | //query["filter_field"] = field 1792 | 1793 | var sql = string.format("SELECT DISTINCT %s FROM [%s]", field, model.tablename) 1794 | var items = model.getTable(sql) 1795 | 1796 | var data = {} 1797 | for(i=1;#items;1){ 1798 | var value = items[i][field]; 1799 | if(value == "" or value == null){ 1800 | table.push(data, {text = "空值";filter_field=field}) 1801 | }else { 1802 | table.push(data, {text = value; filter_field=field}) 1803 | } 1804 | } 1805 | 1806 | table.push(item, data) 1807 | 1808 | var hItem = mainForm.treeview.insertItem(item) 1809 | 1810 | } 1811 | 1812 | mainForm.treeview.expandAll() 1813 | } 1814 | 1815 | 1816 | menu_edit_item = function(){ 1817 | var iRow = mainForm.listview.getSelection(); //选中的行 1818 | if(!iRow){ 1819 | mainForm.msgbox("请选中一项再操作"); 1820 | return 1821 | }else { 1822 | var id = mainForm.listview.getItemText(iRow, 1) 1823 | var mform = sqlitemodel.modelForm(modGoods, mainForm, id); 1824 | mform.doModal(mainForm); 1825 | load_model_data(modGoods); 1826 | } 1827 | } 1828 | 1829 | menu_delete_item = function(){ 1830 | 1831 | var iRow = mainForm.listview.getSelection(); 1832 | 1833 | if(!iRow){ 1834 | return 1835 | } 1836 | 1837 | var query = {} 1838 | var model = mainForm.model; 1839 | var display_fields = model.display_fields; 1840 | for(i=1;#display_fields;1){ 1841 | k = display_fields[i] 1842 | query[k] = mainForm.listview.getItemText(iRow, i) 1843 | } 1844 | 1845 | var confirmed = false; //默认不删除 1846 | if(config.settings.confirm_delete){ 1847 | confirmed = mainForm.msgboxTest(string.format("确认删除%s数据(id=%s)吗?", mainForm.model.label,query["id"])); //看用户选择 1848 | }else { 1849 | confirmed = true; //无需确认 1850 | } 1851 | 1852 | if(confirmed){ 1853 | model.delete(query); 1854 | initTreeviewFilters(model); 1855 | load_model_data(model); 1856 | } 1857 | } 1858 | 1859 | 1860 | 1861 | mainForm.treeview.onnotify = function(id,code,ptr){ 1862 | if(code = 0xFFFFFFFE/*_NM_CLICK*/){ 1863 | //单击 1864 | var x,y = mouse.getPos() 1865 | var hItem,tvht = mainForm.treeview.hitTest(x,y,true); 1866 | 1867 | if(!hItem){ 1868 | return 1869 | } 1870 | 1871 | mainForm.treeview.setSelected(hItem); 1872 | mainForm.treeview.expandAll() 1873 | 1874 | var hitem = mainForm.treeview.getSelection() 1875 | //mainForm.text = mainForm.treeview.getItemData(hitem); 1876 | var data = mainForm.treeview.getItemData(hitem); 1877 | 1878 | var filter_field = data["filter_field"]; 1879 | //if(filter_field == null){ //点中了根节点,应该返回全部数据 1880 | // return 1881 | //} 1882 | 1883 | var keyword = ""; 1884 | 1885 | if(data == null or #data>0){ 1886 | //未选中节点, 或者选中节点有子节点(根节点) 1887 | keyword = "" 1888 | //return 1889 | }else { 1890 | //没有子节点的节点,如果是根节点, 那么也是在这里处理, 但是没有filter_field数据, 所以后面的filter 1891 | // 会因为没有filter_field数据, 而返回全部数据, 忽略keyword 1892 | keyword = data["text"]; 1893 | if(string.indexOf(keyword, "|")){ 1894 | keyword = string.split(keyword, "<|>")[1] 1895 | } 1896 | //mainForm.text = data["text"] ++ " 单位"; 1897 | } 1898 | 1899 | var query = {}; 1900 | if(filter_field != null){ 1901 | query[filter_field] = keyword; //filter, field = value, field_lt = value 1902 | } 1903 | 1904 | var items_perpage = tonumber(mainForm.comboItemsPerpage.text); 1905 | query["ITEMS_PERPAGE"] = items_perpage 1906 | query["QUERY_MODE"] = "FILTER"; 1907 | 1908 | CURR_QUERY = query; 1909 | log(table.tostring(CURR_QUERY)); 1910 | 1911 | 1912 | var model = modGoods; 1913 | CURR_MODEL = model; 1914 | 1915 | var items = model.filter(query) 1916 | reset_listview(model, items); 1917 | //initTreeviewFilters(CURR_MODEL) 1918 | 1919 | } 1920 | } 1921 | 1922 | change_model_field = function(model, field, value){ 1923 | var ids = {} 1924 | for(i=1;mainForm.listview.count;1){ 1925 | if(mainForm.listview.getSelected(i)){ 1926 | table.push(ids, mainForm.listview.getItemText(i, 1)); 1927 | } 1928 | } 1929 | 1930 | var str_ids = string.join(table.map(ids,function(v,k,result){ 1931 | return tostring(v) 1932 | }), ",") 1933 | 1934 | //console.log(str_ids, value) 1935 | 1936 | var sql = "UPDATE ["+ model.tablename +"] SET "+ field +"=@value where id in (" + str_ids + ")"; 1937 | var query = {} 1938 | query["value"] = value; 1939 | //console.log("sql:"+sql); 1940 | var updated = false; 1941 | try{ 1942 | var command = db.prepare(sql) 1943 | command.bind.parameterByName(value, "@value") //给@value 绑定数据 value 1944 | var ret = command.step() 1945 | command.finalize(); 1946 | 1947 | //db.exec(sql, query); 1948 | //console.log("updated success!") 1949 | updated = true; 1950 | //return true; //这里try语句里的 return true 并不能真的返回值, 函数最后返回的是null 1951 | } 1952 | catch(e){ 1953 | //console.varDump(e); 1954 | //console.log(tostring(e)) 1955 | //return false;//这里try的catch语句里的 return false却可以真正使函数返回.函数最后返回的是false 1956 | updated = false; 1957 | } 1958 | 1959 | load_model_data(model) 1960 | 1961 | } 1962 | 1963 | mainForm.listview.wndproc = function(hwnd,message,wParam,lParam){ 1964 | //无返回值则继续调用默认回调函数 1965 | select( message ) { 1966 | case 0x101/*_WM_KEYUP*/ { 1967 | if(wParam == 0x2E/*_VK_DELETE*/ ){ 1968 | var iRow = mainForm.listview.getSelection(); 1969 | menu_delete_item() 1970 | 1971 | if(mainForm.listview.count>0){ 1972 | if(mainForm.listview.count >= iRow){ 1973 | mainForm.listview.setSelected(iRow) 1974 | }else { 1975 | mainForm.listview.setSelected(mainForm.listview.count) 1976 | } 1977 | } 1978 | } 1979 | } 1980 | /** 1981 | case 0x202/*_WM_LBUTTONUP*/{ 1982 | var listview = ::NMLISTVIEW() 1983 | raw.convert(topointer(lParam), listview); 1984 | 1985 | //得到选中的列 1986 | column = listview.iSubItem; 1987 | hdr = listview.hdr; 1988 | 1989 | console.varDump(hdr); 1990 | 1991 | 1992 | //console.log("column",listview.iItem, listview.iSubItem) //, LOWORD(wParam)) 1993 | 1994 | if(hdr.code == 0xFFFFFEBA/*HDN_ENDTRACKW*/ || hdr.code == 0xFFFFFECE/*HDN_ENDTRACKA*/ ){ 1995 | // console.varDump(hdr); 1996 | console.log("column",listview.iItem, listview.iSubItem) //, LOWORD(wParam)) 1997 | return true; 1998 | } 1999 | } 2000 | **/ 2001 | case 0x4e/*_WM_NOTIFY*/{ 2002 | //这个片段虽然是mainForm中的,但是居然会影响每个winform中的listview, 2003 | //导致点击左键,程序就崩溃 2004 | //原因找到了, 不能直接使用lv = ::NMLISTVIEW(); 使用了就崩溃了。 2005 | var lv = win.ui.ctrl.listview.NMLISTVIEW(); 2006 | raw.convert(topointer(lParam), lv); 2007 | //console.varDump(lv) 2008 | 2009 | //得到选中的列 2010 | column = lv.iSubItem; 2011 | hdr = lv.hdr 2012 | 2013 | 2014 | 2015 | //console.varDump(hdr) 2016 | 2017 | //console.log("column",listview.iItem, listview.iSubItem) //, LOWORD(wParam)) 2018 | 2019 | if(hdr.code == 0xFFFFFEBA/*HDN_ENDTRACKW*/ || hdr.code == 0xFFFFFECE/*HDN_ENDTRACKA*/ ){ 2020 | console.varDump(lv); 2021 | console.varDump(hdr) 2022 | console.log("column",lv.iItem, lv.iSubItem , LOWORD(wParam), HIWORD(wParam)) 2023 | var lvcol = mainForm.listview.getColumn(,lv.iItem) 2024 | console.varDump(lvcol) 2025 | 2026 | console.log("lvcol.cx",lvcol.cx) 2027 | 2028 | return false; 2029 | } 2030 | //return true; 2031 | } 2032 | 2033 | } 2034 | 2035 | } 2036 | 2037 | mainForm.listview.onnotify = function(id,code,ptr){ 2038 | 2039 | select(code) { 2040 | 2041 | /** 2042 | case 0xFFFFFFFE/*_NM_CLICK*/ { 2043 | mainForm.msgbox("单击") 2044 | } 2045 | 2046 | case 0xFFFFFFF4 { // 调整列宽 2047 | lv = raw.convert( ptr, win.ui.ctrl.listview.NMLISTVIEW() ); 2048 | console.varDump(lv) 2049 | console.varDump(lv.hdr) 2050 | console.varDump(lv.ptAction) 2051 | return true; 2052 | } 2053 | **/ 2054 | case 0xFFFFFFFD/*_NM_DBLCLK*/ { 2055 | var x,y = mouse.getPos() 2056 | var iRow, iCol = mainForm.listview.hitTest(x,y,true); 2057 | if(iRow){ 2058 | mainForm.listview.setSelected(iRow);//利于后面的getSelection(); 2059 | mainForm.lastListviewSelected = iRow; 2060 | menu_edit_item() 2061 | } 2062 | } 2063 | case 0xFFFFFFFB/*_NM_RCLICK*/ { 2064 | var x,y = mouse.getPos() 2065 | var iRow, iCol = mainForm.listview.hitTest(x,y,true); 2066 | if(iRow){ 2067 | mainForm.listview.setSelected(iRow);//利于后面的getSelection(); 2068 | mainForm.lastListviewSelected = iRow; 2069 | } 2070 | 2071 | var menu = win.ui.popmenu(mainForm) 2072 | 2073 | menu.add("修改", 2074 | function(){ 2075 | menu_edit_item() 2076 | } 2077 | ); 2078 | 2079 | var model = CURR_MODEL; 2080 | var filter_fields = model.filter_fields 2081 | 2082 | var filter_menus = {} 2083 | 2084 | 2085 | 2086 | for(i=1;#filter_fields;1){ 2087 | var item = {} 2088 | 2089 | var k = filter_fields[i] 2090 | var caption = model.headers[k] 2091 | 2092 | table.push(item, string.format("更改选中项的%s为", caption)) 2093 | var sql = string.format("select distinct %s from %s", k, model.tablename) 2094 | var items = model.getTable(sql) 2095 | 2096 | //console.varDump(items) 2097 | 2098 | var data = {} 2099 | for(i=1;#items;1){ 2100 | //console.log("items[i][k]", items[i][k]); 2101 | var x = { 2102 | tostring(items[i][k]); //tostring() 避免 USTRING ERROR 2103 | function(id){ 2104 | //mainForm.msgbox(tostring(items[i][k])) 2105 | change_model_field(model, k, items[i][k]); 2106 | } 2107 | } 2108 | //console.log(" console.varDump(x)") 2109 | //console.varDump(x) 2110 | table.push(data, x) 2111 | } 2112 | 2113 | if(#data){ 2114 | //console.log("console.varDump(data)") 2115 | //console.varDump(data) 2116 | table.push(item, data) 2117 | }else { 2118 | continue; 2119 | } 2120 | 2121 | //console.log("continue;") 2122 | 2123 | //console.varDump(item) 2124 | table.push(filter_menus, item) 2125 | } 2126 | 2127 | //console.varDump(filter_menus) 2128 | if(#filter_menus){ 2129 | menu.addTable( 2130 | //{filter_menus} 2131 | filter_menus 2132 | ) 2133 | } 2134 | 2135 | menu.add({}); 2136 | 2137 | menu.add("全选 Ctrl+A", 2138 | function(){ 2139 | for(i=1;mainForm.listview.count;1){ 2140 | mainForm.listview.setSelected(i) 2141 | } 2142 | } 2143 | ); 2144 | 2145 | menu.add("反选", 2146 | function(){ 2147 | for(i=1;mainForm.listview.count;1){ 2148 | var status = mainForm.listview.getSelected(i); 2149 | mainForm.listview.setSelected(i,!status); 2150 | } 2151 | } 2152 | ); 2153 | 2154 | menu.add("采购选中商品", 2155 | function(){ 2156 | var items = {} 2157 | //console.log(mainForm.listview.columnCount) 2158 | var ids = {} 2159 | for(i=1;mainForm.listview.count;1){ 2160 | if(mainForm.listview.getSelected(i)){ 2161 | table.push(ids, mainForm.listview.getItemText(i,1)); //每一行的第1列就是goods_id 2162 | } 2163 | } 2164 | if(#ids){ 2165 | var TABLE_NAME = model.tablename; 2166 | var sql = "SELECT * FROM [" ++ TABLE_NAME ++ "] where id in (" + string.join(ids, ", ") + ")" 2167 | items = model.getTable(sql); 2168 | menu_goods_purchase(items); 2169 | } 2170 | } 2171 | ); 2172 | 2173 | 2174 | 2175 | menu.add("导出选中项数据", 2176 | function(){ 2177 | var items = {} 2178 | //console.log(mainForm.listview.columnCount) 2179 | var ids = {} 2180 | for(i=1;mainForm.listview.count;1){ 2181 | 2182 | if(mainForm.listview.getSelected(i)){ 2183 | table.push(ids, mainForm.listview.getItemText(i,1)); //每一行的第1列就是id 2184 | } 2185 | } 2186 | if(#ids){ 2187 | var TABLE_NAME = model.tablename; 2188 | var sql = "SELECT * FROM [" ++ TABLE_NAME ++ "] where id in (" + string.join(ids, ", ") + ")" 2189 | items = model.getTable(sql); 2190 | export_model(model, items); 2191 | } 2192 | 2193 | } 2194 | ); 2195 | 2196 | menu.add({}); 2197 | 2198 | menu.add("删除", 2199 | function(){ 2200 | menu_delete_item(); 2201 | } 2202 | ); 2203 | menu.popup(x,y,true); 2204 | } 2205 | 2206 | 2207 | //case _lvn_ 2208 | /* 2209 | case _hdn_ 2210 | HD_NOTIFY* pHDN = (HD_NOTIFY*)lParam; 2211 | switch(((NMHDR*)lParam)->code) 2212 | { 2213 | HDN_ENDTRACKW 2214 | 2215 | case HDN_BEGINTRACKW: 2216 | case HDN_BEGINTRACKA: 2217 | case HDN_DIVIDERDBLCLICKA: 2218 | case HDN_DIVIDERDBLCLICKW: 2219 | for(int i=0; iiItem == m_vFrozenCols[i]) //如果拖动的列是设定固定列宽的列之一 2222 | { 2223 | *pResult = TRUE; 2224 | return TRUE; 2225 | } 2226 | } 2227 | } 2228 | */ 2229 | 2230 | case !=0 { 2231 | } 2232 | else { 2233 | } 2234 | } 2235 | } 2236 | 2237 | menu_goods_add = function(){ 2238 | var data = {}; 2239 | var field_names = sqlitemodel.Model.get_field_names(modGoods.sql,true); //要包含id 2240 | // 2241 | //console.varDump(field_names) 2242 | // 2243 | 2244 | //for(i=1;#field_names;1){ 2245 | // console.varDump(field_names[i]) 2246 | //} 2247 | 2248 | 2249 | 2250 | var iRow = mainForm.listview.getSelection(); //选中的行 2251 | if(!iRow){ 2252 | mainForm.msgbox("请选中一项再操作") 2253 | return 2254 | form_caption = "添加数据" 2255 | btn_text = "添加" 2256 | }else { 2257 | //var id = mainForm.listview.getItemText(3, 1)//第三行, 第一列的数据 2258 | var id = mainForm.listview.getItemText(iRow, 1) 2259 | var query = {} 2260 | query["id"] = id 2261 | data = modGoods.get(query) 2262 | 2263 | form_caption = "修改数据" 2264 | btn_text = "保存" 2265 | 2266 | } 2267 | 2268 | var frmChild = mainForm.loadForm("\dlg\model_form.aardio"); 2269 | 2270 | var frmChild_width = 0 2271 | var COLS_PADDING = 5 //列与列之间的间隔, 每列由一个标签和一个文本框组成 2272 | var ROWS_PER_COL = 15; 2273 | var LABEL_WIDTH = 84; 2274 | var EDIT_WIDTH = 320; // 420; 2275 | 2276 | var ROW_WIDTH = EDIT_WIDTH + COLS_PADDING*2; 2277 | 2278 | var LABEL_HEIGHT = 20; 2279 | var EDIT_HEIGHT = 20; 2280 | 2281 | var ROW_HEIGHT = LABEL_HEIGHT + EDIT_HEIGHT + 5; 2282 | 2283 | frmChild.width = COLS_PADDING*2 + (math.floor((#field_names-1) / ROWS_PER_COL)+1) * ROW_WIDTH; 2284 | 2285 | for(i=1;#field_names;1){ 2286 | 2287 | var k = field_names[i]["name"] 2288 | var label = field_names[i]["label"] 2289 | var value = "" 2290 | 2291 | if(data[k]!=null){ 2292 | value = tostring(data[k]) 2293 | } 2294 | 2295 | // 2296 | //log(k++":"++label) 2297 | // 2298 | 2299 | var ctrl = frmChild["edit_"+k] 2300 | if(ctrl!=null){ 2301 | ctrl.text = value 2302 | }else { 2303 | 2304 | var staticLeft = COLS_PADDING + math.floor((i - 1) / ROWS_PER_COL) * ROW_WIDTH; //每一列的left是相同的。 2305 | var staticTop = 13 + 22 * (i - (math.floor((i - 1) / ROWS_PER_COL) * ROWS_PER_COL + 1)); 2306 | //console.log(staticLeft,", ", staticTop) 2307 | 2308 | 2309 | frmChild.add( 2310 | ["static_" + k ] = { 2311 | //border=1; 2312 | cls="static"; text=label; notify=1; dl=1;dt=1;font=LOGFONT( name='宋体' );bottom=staticTop + LABEL_HEIGHT;right=staticLeft+LABEL_WIDTH;left=staticLeft;top=staticTop;z=1; 2313 | }; 2314 | ) 2315 | 2316 | if(k=="id" or k=="taxno" or k=="created" or k=="updated"){ 2317 | frmChild.add( 2318 | ["edit_" + k ] = { 2319 | cls="edit"; text=value; disabled=1;notify=1; dl=1;dt=1;font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT;right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 2320 | }; 2321 | ) 2322 | }else { 2323 | frmChild.add( 2324 | ["edit_" + k ] = { 2325 | cls="edit"; text=value; tabstop=i; notify=1; dl=1;dt=1;font=LOGFONT(name='Consolas');bottom=staticTop+EDIT_HEIGHT;right=staticLeft + EDIT_WIDTH;left=staticLeft+LABEL_WIDTH + COLS_PADDING;top=staticTop;z=1; 2326 | }; 2327 | ) 2328 | } 2329 | 2330 | 2331 | 2332 | 2333 | // 2334 | //log("ctrl edit_" + k + " 不存在!创建一个") 2335 | // 2336 | } 2337 | } 2338 | 2339 | frmChild.text = form_caption 2340 | frmChild.button.text = btn_text 2341 | 2342 | frmChild.show(); 2343 | } 2344 | 2345 | 2346 | 2347 | menu_goods_purchase = function(items){ 2348 | 2349 | var frmChild,wb = mainForm.loadForm("\dlg\goods_purchase.aardio"); 2350 | 2351 | var user_define_fields = {"id"; "goods_id"; "name"; "specs"; "unit"; }; 2352 | frmChild.user_define_fields = user_define_fields; 2353 | 2354 | for(i=1;#items;1){ 2355 | items[i]["goods_id"] = items[i]["id"]; 2356 | items[i]["id"] = ""; 2357 | } 2358 | 2359 | if(items and #items>0){ 2360 | frmChild.reset_listview(modGoods, items, user_define_fields) 2361 | } 2362 | frmChild.doModal(); 2363 | } 2364 | 2365 | 2366 | menu_goods_purchase_history = function(items){ 2367 | 2368 | var frmChild,wb = mainForm.loadForm("\dlg\goods_purchase_history.aardio"); 2369 | frmChild.doModal(); 2370 | } 2371 | 2372 | 2373 | menu_goods_sell = function(items){ 2374 | 2375 | var frmChild, wb = mainForm.loadForm("\dlg\goods_sell.aardio"); 2376 | if(items and #items>0){ 2377 | var user_define_fields = {"id"; "name"; "specs"; "unit"} 2378 | frmChild.reset_listview(modGoods, items, user_define_fields) 2379 | } 2380 | frmChild.doModal(); 2381 | 2382 | } 2383 | 2384 | 2385 | 2386 | mainForm.button.oncommand = function(id,event){ 2387 | var query={} 2388 | var items_perpage = tonumber(mainForm.comboItemsPerpage.text); 2389 | query["ITEMS_PERPAGE"] = items_perpage; 2390 | query["keyword"] = string.trim(mainForm.edit.text); 2391 | CURR_QUERY = query; 2392 | CURR_MODEL = modGoods; 2393 | load_model_data(CURR_MODEL, CURR_QUERY); 2394 | //mainForm.listview.setSelected(1); 2395 | //mainForm.listview.setFocus(); 2396 | } 2397 | 2398 | mainForm.btnRefresh.oncommand = function(id,event){ 2399 | load_model_data(mainForm.model); 2400 | } 2401 | 2402 | restoreListviewPos = function(){ 2403 | if(mainForm.lastListviewSelected){ 2404 | mainForm.listview.setFocus(); 2405 | mainForm.listview.setSelected(mainForm.lastListviewSelected); 2406 | if(mainForm.lastListviewSelected+825){ 2408 | mainForm.listview.ensureVisible(mainForm.lastListviewSelected+8); 2409 | }else { 2410 | mainForm.listview.ensureVisible(mainForm.lastListviewSelected); 2411 | } 2412 | }else { 2413 | mainForm.listview.ensureVisible(mainForm.listview.count); 2414 | } 2415 | } 2416 | } 2417 | 2418 | mainForm.button7.oncommand = function(id,event){ 2419 | 2420 | 2421 | var frmChild = mainForm.loadForm("\dlg\select_fields.aardio"); 2422 | //var field_names = sqlitemodel.Model.get_field_names(modGoods.sql, true) 2423 | var field_names = modGoods.field_names; 2424 | for(i=1;#field_names;1){ 2425 | frmChild.checklist.addItem(field_names[i]["label"]) 2426 | } 2427 | 2428 | var reservedTopN = 7 2429 | for(i=1;reservedTopN;1){ 2430 | frmChild.listbox.add(frmChild.checklist.getItemText(i)); 2431 | 2432 | } 2433 | for(i=1;reservedTopN;1){ 2434 | frmChild.checklist.delItem(reservedTopN+1-i); 2435 | } 2436 | 2437 | 2438 | selected_labels = frmChild.doModal(mainForm); 2439 | 2440 | var selected_fields = {} 2441 | for(i=1;#selected_labels;1){ 2442 | for(j=1;#field_names;1){ 2443 | if(selected_labels[i] == field_names[j]["label"]){ 2444 | table.push(selected_fields, field_names[j]["name"]) 2445 | } 2446 | } 2447 | } 2448 | 2449 | //修改全局变量 2450 | if(#selected_fields){ 2451 | CURR_QUERY = {}; 2452 | 2453 | modGoods.display_fields = selected_fields; 2454 | CURR_MODEL = modGoods; 2455 | 2456 | load_model_data(CURR_MODEL, CURR_QUERY); 2457 | } 2458 | 2459 | 2460 | } 2461 | 2462 | config_setting = function(id,event){ 2463 | 2464 | 2465 | var frmChild = mainForm.loadForm("\dlg\settings.aardio"); 2466 | 2467 | var x = frmChild.doModal(mainForm); 2468 | 2469 | 2470 | } 2471 | 2472 | 2473 | init=function(){ 2474 | //初始化 2475 | var model = modGoods; 2476 | var headers = {}; 2477 | var header_cols = {}; 2478 | var required_cols = {}; 2479 | 2480 | for(k,v in model.field_names){ 2481 | //field_names有id 2482 | headers[v.name]=v.label 2483 | } 2484 | 2485 | headers["id"]="ID" 2486 | 2487 | //数据导入用, 根据optional_headers(即数据库的字段)重新初始化header_cols 2488 | for(k,v in headers){ 2489 | //标题位于第几列(第1列是A列,第2列是B列...), 初始化默认设置为0列(默认不正常,正常的列应该从1开始). 2490 | header_cols[k]=0; 2491 | } 2492 | header_cols["id"]=null; //导入的时候剔除 id 字段 2493 | required_cols["id"]=null; //导入的时候剔除 id 字段 2494 | 2495 | 2496 | win.ui.statusbar( mainForm ).addItem("公司:", 100/*宽度*/) 2497 | 2498 | mainForm.statusbar.addItem("数据库:"+io.fullpath(dbpath), 500); 2499 | mainForm.text = mainForm.text ++ " - 商品管理" 2500 | 2501 | /* 2502 | SELECT column-list 2503 | FROM table_name 2504 | WHERE [ conditions ] 2505 | GROUP BY column1, column2....columnN 2506 | ORDER BY column1, column2....columnN 2507 | */ 2508 | 2509 | for(i=1;#model.display_fields;1){ 2510 | var caption = headers[model.display_fields[i]] 2511 | mainForm.listview.insertColumn(caption, 60); 2512 | } 2513 | 2514 | 2515 | mainForm.listview.setColumn({cx=40},1) 2516 | mainForm.listview.setColumn({cx=160},2) 2517 | mainForm.listview.setColumn({cx=320},3) 2518 | mainForm.listview.setColumn({cx=80},4) 2519 | mainForm.listview.setColumn({cx=140},5) 2520 | mainForm.listview.setColumn({cx=140},6) 2521 | mainForm.listview.setColumn({cx=140},7) 2522 | mainForm.listview.setColumn({cx=140},8) 2523 | mainForm.listview.setColumn({cx=140},9) 2524 | 2525 | 2526 | initTreeviewFilters(model); 2527 | load_model_data(model); 2528 | 2529 | mainForm.edit.setFocus(); 2530 | 2531 | } 2532 | 2533 | 2534 | mainForm.btnNext.oncommand = function(id,event){ 2535 | 2536 | var model = CURR_MODEL; 2537 | var query = CURR_QUERY; 2538 | 2539 | var curr_page = mainForm.comboCurrPage.text 2540 | var pages = table.map(mainForm.comboCurrPage.items,function(v,k,result){ 2541 | return tonumber(v); 2542 | }) 2543 | var min, max = table.range(pages) 2544 | var next_page = tonumber(curr_page) + 1; 2545 | if(next_page>max){ 2546 | next_page = max 2547 | } 2548 | 2549 | query["CURR_PAGE"] = next_page; 2550 | var items = {} 2551 | select(query["QUERY_MODE"]) { 2552 | case "FILTER" { 2553 | items = model.filter(query); 2554 | } 2555 | case "SEARCH" { 2556 | items = model.search(query); 2557 | } 2558 | else { 2559 | 2560 | } 2561 | } 2562 | 2563 | reset_listview(model, items) 2564 | 2565 | log(table.tostring(query)) 2566 | } 2567 | 2568 | mainForm.btnPrev.oncommand = function(id,event){ 2569 | var curr_page = mainForm.comboCurrPage.text 2570 | var prev_page = tonumber(curr_page) - 1; 2571 | if(prev_page<0){ 2572 | prev_page = 0 2573 | } 2574 | var model = CURR_MODEL; 2575 | var query = CURR_QUERY; 2576 | query["CURR_PAGE"] = prev_page 2577 | var items = {} 2578 | select(query["QUERY_MODE"]) { 2579 | case "FILTER" { 2580 | items = model.filter(query); 2581 | } 2582 | case "SEARCH" { 2583 | items = model.search(query); 2584 | } 2585 | else { 2586 | 2587 | } 2588 | } 2589 | 2590 | reset_listview(model, items) 2591 | 2592 | log(table.tostring(query)) 2593 | } 2594 | 2595 | mainForm.btnGotoNPage.oncommand = function(id,event){ 2596 | var curr_page = mainForm.comboCurrPage.text 2597 | var model = CURR_MODEL; 2598 | var query = CURR_QUERY; 2599 | query["CURR_PAGE"] = tonumber(curr_page) 2600 | var items = {} 2601 | select(query["QUERY_MODE"]) { 2602 | case "FILTER" { 2603 | items = model.filter(query); 2604 | } 2605 | case "SEARCH" { 2606 | items = model.search(query); 2607 | } 2608 | else { 2609 | 2610 | } 2611 | } 2612 | 2613 | reset_listview(modGoods, items) 2614 | 2615 | log(table.tostring(query)) 2616 | } 2617 | 2618 | mainForm.onMouseClick = function(wParam,lParam){ 2619 | var x,y = win.getMessagePos(lParam); 2620 | mainForm.comboItemsPerpage.setFocus(false); 2621 | mainForm.edit.setFocus(); 2622 | } 2623 | 2624 | mainForm.comboItemsPerpage.oncommand = function(id,event){ 2625 | if(event = 4/*_CBN_KILLFOCUS*/){ 2626 | var n = LAST_ITEMS_PERPAGE; 2627 | 2628 | try{ 2629 | n = tonumber(mainForm.comboItemsPerpage.text) 2630 | if(n != LAST_ITEMS_PERPAGE){ 2631 | var model = CURR_MODEL; 2632 | var query = CURR_QUERY; 2633 | 2634 | query["CURR_PAGE"] = 1; 2635 | query["ITEMS_PERPAGE"] = n; 2636 | var items = {} 2637 | select(query["QUERY_MODE"]) { 2638 | case "FILTER" { 2639 | items = model.filter(query); 2640 | } 2641 | case "SEARCH" { 2642 | items = model.search(query); 2643 | } 2644 | else { 2645 | 2646 | } 2647 | } 2648 | 2649 | reset_listview(model, items) 2650 | 2651 | log(table.tostring(query)) 2652 | LAST_ITEMS_PERPAGE = n; 2653 | } 2654 | } 2655 | catch(e){ 2656 | log(tostring(e)) 2657 | } 2658 | 2659 | } 2660 | } 2661 | 2662 | mainForm.edit.translateAccelerator = function( msg ){ 2663 | //edit搜索框回车键,相当于点击“搜索”按钮 2664 | if( msg.wParam == 0xD/*_VK_ENTER*/ ){ 2665 | if( msg.message == 0x101/*_WM_KEYUP*/ ){ 2666 | mainForm.button.oncommand() 2667 | } 2668 | return true; 2669 | } 2670 | } 2671 | 2672 | mainForm.edit.oncommand = function(id,event){ 2673 | if(event=0x300/*_EN_CHANGE*/){ 2674 | mainForm.button.oncommand(); 2675 | } 2676 | } 2677 | 2678 | init() 2679 | 2680 | mainForm.enableDpiScaling(); 2681 | //mainForm.show(3/*_SW_MAXIMIZE*/); 2682 | mainForm.show(); 2683 | return win.loopMessage(); -------------------------------------------------------------------------------- /res/models/company.sql.aardio: -------------------------------------------------------------------------------- 1 | CREATE TABLE "company" ( 2 | "id" INTEGER NOT NULL PRIMARY KEY, 3 | "name" VARCHAR(32) NOT NULL, /*名称*/ 4 | "nsrsbh" VARCHAR(16), /*纳税人识别号*/ 5 | "cate" VARCHAR(16), /*分类*/ 6 | "created_at" DATE NOT NULL, /*创建时间*/ 7 | "updated_at" DATE NOT NULL /*更新时间*/ 8 | ); 9 | -------------------------------------------------------------------------------- /res/models/goods_category.sql.aardio: -------------------------------------------------------------------------------- 1 | CREATE TABLE "goods_category" ( 2 | "id" INTEGER NOT NULL PRIMARY KEY, 3 | "name" VARCHAR(32) NOT NULL, /*分类名称*/ 4 | "parent" INTEGER , /*上级分类*/ 5 | "pos" INTEGER DEFAULT 0, /*排序*/ 6 | "created_at" DATE NOT NULL, /*创建时间*/ 7 | "updated_at" DATE NOT NULL /*更新时间*/ 8 | ); 9 | -------------------------------------------------------------------------------- /res/models/store.sql.aardio: -------------------------------------------------------------------------------- 1 | CREATE TABLE "store" ( 2 | "id" INTEGER NOT NULL PRIMARY KEY, 3 | "name" VARCHAR(32) NOT NULL, /*名称*/ 4 | "code" VARCHAR(32), /*代码*/ 5 | "title" VARCHAR(32), /*联系人*/ 6 | "cellphone" VARCHAR(32), /*手机号码*/ 7 | "tellphone" VARCHAR(32), /*电话号码*/ 8 | "position" VARCHAR(16), /*位置*/ 9 | "cate" VARCHAR(16), /*分类:库房,供应商,客户*/ 10 | "created_at" DATE NOT NULL, /*创建时间*/ 11 | "updated_at" DATE NOT NULL /*更新时间*/ 12 | ); 13 | -------------------------------------------------------------------------------- /res/toolbar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/encorehu/sqlitemodel/5c418a9381c0d5104ef2d6a26d03d12211224ec7/res/toolbar.gif --------------------------------------------------------------------------------