Web App之记账本

时间:2022-12-21 10:53:39


运行截图如下

Web App之记账本

list.w

<?xml version="1.0" encoding="utf-8"?>

<div xmlns="http://www.w3.org/1999/xhtml" x class="window" component="$UI/system/components/justep/window/window"
design="device:m;">
<div component="$UI/system/components/justep/model/model" x style="height:auto;left:172px;top:187px;">
<div component="$UI/system/components/justep/data/baasData" autoLoad="true"
x idColumn="fID" limit="5" saveAction="saveAccount" queryAction="queryAccount" tableName="account" url="/justep/account">
<column label="主键" name="fID" type="String" x/>
<column label="创建时间" name="fCreateTime" type="DateTime" x/>
<column label="日期" name="fDate" type="Date" x/>
<column label="金额" name="fMoney" type="Decimal" x/>
<column label="备注" name="fDescription" type="String" x/>
<column label="收入\支出" name="fType" type="String" x/>
<column label="分类" name="fClass" type="String" x/>
<data x>[]</data>
</div>
</div>
<span component="$UI/system/components/justep/windowDialog/windowDialog" x
style="left:103px;top:198px;" src="$UI/demo/account/detail.w" title="记账" onReceived="detailDialogReceived">
<result concept="accountData" operation="edit" origin="accountData" x>
<mapping from="fID" to="fID" locator="true" x/>
<mapping from="fCreateTime" to="fCreateTime" x/>
<mapping from="fDate" to="fDate" x/>
<mapping from="fMoney" to="fMoney" x/>
<mapping from="fDescription" to="fDescription" x/>
<mapping from="fType" to="fType" x/>
<mapping from="fClass" to="fClass" x/>
</result>
</span>
<div component="$UI/system/components/justep/panel/panel" class="x-panel x-full"
x>
<div class="x-panel-top" x>
<div component="$UI/system/components/justep/titleBar/titleBar" class="x-titlebar"
x title="记账本">
<div class="x-titlebar-left" x>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="设置" x icon="icon-navicon-round" onClick="settingBtnClick">
<i x class="icon-navicon-round"/>
<span x>设置</span>
</a>
</div>
<div class="x-titlebar-title" x>记账本</div>
<div class="x-titlebar-right reverse" x>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="新增" x icon="icon-android-add" onClick="newBtnClick">
<i x class="icon-android-add"/>
<span x>新增</span>
</a>
</div>
</div>
</div>
<div class="x-panel-content x-scroll-view" x>
<div class="x-scroll" component="$UI/system/components/justep/scrollView/scrollView"
x>
<div class="x-content-center x-pull-down container" x>
<i class="x-pull-down-img glyphicon x-icon-pull-down" x/>
<span class="x-pull-down-label" x>下拉刷新...</span>
</div>
<div class="x-scroll-content" x>
<div component="$UI/system/components/justep/list/list" class="x-list"
x data="accountData">
<ul class="x-list-template" x>
<li x class="account-list-line" bind-css="{'account-income' : $object.val('fType') == '收入','account-payout' : $object.val('fType') == '支出'}">
<div component="$UI/system/components/justep/row/row" class="x-row x-row-center"
x>
<div class="x-col" x bind-click="listLineClick">
<div component="$UI/system/components/justep/row/row" class="x-row"
x>
<div class="x-col" x>
<div component="$UI/system/components/justep/output/output"
class="x-output h3" x bind-ref="ref('fClass')"/>
</div>
</div>
<div component="$UI/system/components/justep/row/row" class="x-row"
x>
<div class="x-col" x>
<div component="$UI/system/components/justep/output/output"
class="x-output" x bind-ref="ref('fDescription')"/>
</div>
</div>
</div>
<div class="x-col" x bind-click="listLineClick">
<div component="$UI/system/components/justep/row/row" class="x-row"
x>
<div class="x-col" x>
<div component="$UI/system/components/justep/output/output"
class="x-output h3" x bind-ref="ref('fMoney')"
format="0,000.00"/>
</div>
</div>
<div component="$UI/system/components/justep/row/row" class="x-row"
x>
<div class="x-col" x>
<div component="$UI/system/components/justep/output/output"
class="x-output" x bind-ref="ref('fDate')" format="yyyy-MM-dd"/>
</div>
</div>
</div>
<div class="x-col x-col-fixed" x style="width:50px;">
<a component="$UI/system/components/justep/button/button"
class="btn btn-link btn-only-icon account-delete" label="删除"
x icon="icon-android-close" onClick="deleteBtnClick">
<i x class="icon-android-close"/>
<span x>删除</span>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
<div class="x-content-center x-pull-up" x>
<span class="x-pull-up-label" x>加载更多...</span>
</div>
</div>
</div>
</div>
</div>

list.js

define(function(require) {
var $ = require("jquery");
var justep = require("$UI/system/lib/justep");

var Model = function() {
this.callParent();
};

Model.prototype.newBtnClick = function(event) {
// 调用对话框新增
this.comp("detailDialog").open({
"data" : {
"operator" : "new"
}
});
};

Model.prototype.listLineClick = function(event) {
// 调用对话框编辑,并传入当前行数据
var row = event.bindingContext.$object;
this.comp("detailDialog").open({
"data" : {
"operator" : "edit",
"rowData" : row.toJson()
}
});
};

Model.prototype.deleteBtnClick = function(event) {
// 行删除
var data = this.comp("accountData");
var row = event.bindingContext.$object;
data.deleteData([ row ], {
"async" : true,
"onSuccess" : function() {
data.saveData();
}
});
};

Model.prototype.detailDialogReceived = function(event) {
// 对话框返回后保存数据
this.comp("accountData").saveData();
};

Model.prototype.settingBtnClick = function(event) {
// 通过Shell显示左边的设置
justep.Shell.showLeft();
};

return Model;
});

list.css

.h3 {
margin : 0;
color : inherit;
font-size : 24px;
}
.x-output {
padding : 0px;
}
.account-list-line {
border-bottom: 1px solid lightgray;
overflow: hidden;
}
.account-list-line:active {
background-color: lightgray;
}
.account-income {
color : green;
}
.account-payout {
color : brown;
}

index.w

<?xml version="1.0" encoding="utf-8"?>

<div xmlns="http://www.w3.org/1999/xhtml" x class="window" component="$UI/system/components/justep/window/window"
design="device:m;">
<div component="$UI/system/components/justep/model/model" x onLoad="modelLoad"
style="height:auto;left:187px;top:249px;"/>
<div component="$UI/system/components/justep/wing/wing" class="x-wing" x display="push">
<div class="x-wing-left" x>
<div component="$UI/system/components/justep/titleBar/titleBar" class="x-titlebar"
x title="设置">
<div class="x-titlebar-left" x/>
<div class="x-titlebar-title" x>设置</div>
<div class="x-titlebar-right reverse" x/>
</div>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-lg"
label="设置分类" x onClick="classSettingBtnClick" style="width:100%;">
<i x/>
<span x>设置分类</span>
</a>
</div>
<div class="x-wing-content" x>
<div class="x-wing-backdrop" x/>
<div component="$UI/system/components/justep/contents/contents" class="x-contents x-full"
active="0" x/>
</div>
<div class="x-wing-right" x/>
</div>
</div>

index.js

define(function(require) {
var $ = require("jquery");
var justep = require("$UI/system/lib/justep");
var ShellImpl = require('$UI/system/lib/portal/shellImpl');
require("$UI/demo/account/appVersionChecker");

var Model = function() {
this.callParent();

this.shellImpl = new ShellImpl(this, {
contentsXid : "pages",
wingXid : "wing",
pageMappings : {
"list" : {
url : "$UI/demo/account/list.w"
},
"detail" : {
url : "$UI/demo/account/detail.w"
},
"classSetting" : {
url : "$UI/demo/account/classSetting.w"
}
}
});
};

Model.prototype.modelLoad = function(event) {
this.shellImpl.showPage("list");
};

Model.prototype.classSettingBtnClick = function(event) {
this.shellImpl.showPage("classSetting");
};

return Model;
});

index.css

.x-wing-left > .x-titlebar {
background-color : orange;

}

detail.w

<?xml version="1.0" encoding="utf-8"?>

<div xmlns="http://www.w3.org/1999/xhtml" x class="window" component="$UI/system/components/justep/window/window"
design="device:m;">
<div component="$UI/system/components/justep/model/model" x style="height:auto;left:233px;top:180px;"
onLoad="modelLoad">
<div component="$UI/system/components/justep/data/data" autoLoad="false"
x idColumn="fID" autoNew="false" onValueChanged="accountDataValueChanged">
<column label="主键" name="fID" type="String" x/>
<column label="创建时间" name="fCreateTime" type="DateTime" x/>
<column label="日期" name="fDate" type="Date" x/>
<column label="金额" name="fMoney" type="Decimal" x/>
<column label="备注" name="fDescription" type="String" x/>
<column label="收入\支出" name="fType" type="String" x/>
<column label="分类" name="fClass" type="String" x/>
<rule x>
<col name="fMoney" x>
<required x>
<expr x>true</expr>
<message x>请填写金额</message>
</required>
</col>
</rule>
<data x>[]</data>
</div>
<div component="$UI/system/components/justep/data/baasData" autoLoad="true"
x idColumn="fID" queryAction="queryAccount_class" tableName="account_class" url="/justep/account">
<column label="主键" name="fID" type="String" x/>
<column label="支出\收入" name="fType" type="String" x/>
<column label="分类" name="fClass" type="String" x/>
<data x>[]</data>
</div>
<div component="$UI/system/components/justep/data/data" autoLoad="true"
x idColumn="fType" limit="20">
<column label="fType" name="fType" type="String" x/>
<data x>[{"fType":"收入"},{"fType":"支出"}]</data>
</div>
</div>
<span component="$UI/system/components/justep/windowReceiver/windowReceiver"
x style="left:149px;top:283px;" onReceive="windowReceiver1Receive"/>
<div component="$UI/system/components/justep/panel/panel" class="x-panel x-full"
x>
<div class="x-panel-top" x>
<div component="$UI/system/components/justep/titleBar/titleBar" class="x-titlebar"
x title="记一笔">
<div class="x-titlebar-left" x>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="button" x onClick="{operation:'windowReceiver1.windowCancel'}">
<i x/>
<span x/>
</a>
</div>
<div class="x-titlebar-title" x>记一笔</div>
<div class="x-titlebar-right reverse" x>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="确定" x icon="icon-android-checkmark" onClick="okBtnClick">
<i x class="icon-android-checkmark"/>
<span x>确定</span>
</a>
</div>
</div>
</div>
<div class="x-panel-content" x>
<div component="$UI/system/components/justep/labelEdit/labelEdit" class="x-label-edit x-label30"
x>
<label class="x-label" x><![CDATA[类型]]></label>
<select component="$UI/system/components/justep/select/select" class="form-control x-edit"
x bind-ref="accountData.ref('fType')" bind-options="typeData"
bind-optionsValue="fType"/>
</div>
<div component="$UI/system/components/justep/labelEdit/labelEdit" class="x-label-edit x-label30"
x>
<label class="x-label" x><![CDATA[分类]]></label>
<select component="$UI/system/components/justep/select/select" class="form-control x-edit"
x bind-ref="accountData.ref('fClass')" bind-options="$model.classData.find(['fType'], [$model.accountData.getValue('fType')])"
bind-optionsValue="fClass"/>
</div>
<div component="$UI/system/components/justep/labelEdit/labelEdit" class="x-label-edit x-label30"
x>
<label class="x-label" x><![CDATA[日期]]></label>
<input component="$UI/system/components/justep/input/input" class="form-control x-edit"
x bind-ref="accountData.ref('fDate')"/>
</div>
<div component="$UI/system/components/justep/labelEdit/labelEdit" class="x-label-edit x-label30"
x>
<label class="x-label" x><![CDATA[金额]]></label>
<input component="$UI/system/components/justep/input/input" class="form-control x-edit"
x bind-ref="accountData.ref('fMoney')" format="0,000.00" placeHolder="0.00"/>
</div>
<div component="$UI/system/components/justep/labelEdit/labelEdit" class="x-label-edit x-label30"
x>
<label class="x-label" x><![CDATA[备注]]></label>
<input component="$UI/system/components/justep/input/input" class="form-control x-edit"
x bind-ref="accountData.ref('fDescription')" placeHolder="请输入备注"/>
</div>
</div>
</div>
</div>

detail.js

define(function(require) {
var $ = require("jquery");
var justep = require("$UI/system/lib/justep");

var Model = function() {
this.callParent();
};

Model.prototype.windowReceiver1Receive = function(event) {
// 对话框接收参数后,新增或编辑
var accountData = this.comp("accountData");
accountData.clear();
this.operator = event.data.operator;
if (this.operator == "new") {
accountData.newData({
"defaultValues" : [ {
"fID" : justep.UUID.createUUID(),
"fCreateTime" : new Date(),
"fDate" : new Date(),
"fType" : "支出",
"fClass" : this.getDefaultClass("支出")
} ]
});
} else if (this.operator == "edit") {
accountData.loadData([ event.data.rowData ]);
accountData.first();
}
};

// 获取指定类型下第一个分类作为默认分类
Model.prototype.getDefaultClass = function(type) {
var classData = this.comp("classData");
var rows = classData.find([ "fType" ], [ type ]);
return rows.length > 0 ? rows[0].val("fClass") : "";
};

Model.prototype.accountDataValueChanged = function(event) {
// 当类型改变时,分类也要同时改变
if (event.col == "fType") {
event.row.val("fClass", this.getDefaultClass(event.value));
}
};

Model.prototype.okBtnClick = function(event) {
// 确定后返回当前行,用于windowDialog的mapping映射
var accountData = this.comp("accountData");
var receiver = this.comp("windowReceiver1");
receiver.windowEnsure(accountData.getCurrentRow());
};

Model.prototype.onClassChanged = function(event) {
this.comp("classData").clear();
this.comp("classData").loadData(event.classData, true, null, null, true);
};

Model.prototype.modelLoad = function(event) {
// 通过Shell的消息总线,挂接分类改变的消息,接收到后加载改变后的分类数据
justep.Shell.on("onClassChanged", this.onClassChanged, this);
};

Model.prototype.modelUnLoad = function(event){
justep.Shell.off("onClassChanged", this.onClassChanged);
};

return Model;
});

detail.css

.x-panel > .x-panel-content {
margin : 10px;
}
classSetting.w
<?xml version="1.0" encoding="utf-8"?>

<div xmlns="http://www.w3.org/1999/xhtml" component="$UI/system/components/justep/window/window" design="device:m;"
x class="window">
<div component="$UI/system/components/justep/model/model" x style="height:auto;left:130px;top:300px;">
<div component="$UI/system/components/justep/data/baasData" autoLoad="true"
x idColumn="fID" onAfterSave="classDataAfterSave" saveAction="saveAccount_class"
queryAction="queryAccount_class" tableName="account_class" url="/justep/account" directDelete="true">
<column label="主键" name="fID" type="String" x/>
<column label="支出\收入" name="fType" type="String" x/>
<column label="分类" name="fClass" type="String" x/>
<data x>[]</data>
</div>
<div component="$UI/system/components/justep/data/data" autoLoad="true"
x idColumn="fType" limit="20">
<column label="fType" name="fType" type="String" x/>
<data x>[{"fType":"收入"},{"fType":"支出"}]</data>
</div>
</div>
<div component="$UI/system/components/justep/panel/panel" class="x-panel x-full"
x>
<div class="x-panel-top" x>
<div component="$UI/system/components/justep/titleBar/titleBar" title="设置分类"
class="x-titlebar">
<div class="x-titlebar-left">
<a component="$UI/system/components/justep/button/button" label=""
class="btn btn-link btn-only-icon" icon="icon-chevron-left" x
onClick="{operation:'window.close'}">
<i class="icon-chevron-left"/>
<span/>
</a>
</div>
<div class="x-titlebar-title">设置分类</div>
<div class="x-titlebar-right reverse">
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="保存" x icon="icon-android-checkmark" onClick="{operation:'classData.save'}">
<i x class="icon-android-checkmark"/>
<span x>保存</span>
</a>
<a component="$UI/system/components/justep/button/button" class="btn btn-link btn-only-icon"
label="新增" x icon="icon-android-add" onClick="newBtnClick">
<i x class="icon-android-add"/>
<span x>新增</span>
</a>
</div>
</div>
</div>
<div class="x-panel-content" x style="bottom: 0px;">
<div component="$UI/system/components/justep/list/list" class="x-list"
x data="classData">
<ul class="x-list-template" x>
<li x>
<div component="$UI/system/components/justep/row/row" class="x-row x-row-center"
x>
<div class="x-col x-col-33" x>
<select component="$UI/system/components/justep/select/select"
class="form-control" x bind-options="$model.typeData"
bind-optionsValue="fType" bind-ref="ref('fType')"/>
</div>
<div class="x-col" x>
<input component="$UI/system/components/justep/input/input" class="form-control"
x bind-ref="ref('fClass')"/>
</div>
<div class="x-col x-col-fixed" x style="width:50px;">
<a component="$UI/system/components/justep/button/button"
class="btn btn-link btn-only-icon" label="删除" x icon="icon-android-close"
onClick="deleteBtnClick">
<i x class="icon-android-close"/>
<span x>删除</span>
</a>
</div>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>

classSetting.js

define(function(require) {
var $ = require("jquery");
var justep = require("$UI/system/lib/justep");

var Model = function() {
this.callParent();
};

Model.prototype.newBtnClick = function(event) {
// 新增分类数据并给出默认值
this.comp("classData").newData({
"defaultValues" : [ {
"fID" : justep.UUID.createUUID(),
"fType" : "支出"
} ]
});
};

Model.prototype.deleteBtnClick = function(event) {
// 行删除
var row = event.bindingContext.$object;
this.comp("classData").deleteData([ row ], {
"async" : true
});
};

Model.prototype.classDataAfterSave = function(event) {
// 通过Shell发出一个消息,通知其他页面分类数据已改变,并且在消息中携带了改变后的分类数据
var classData = this.comp("classData");
justep.Shell.fireEvent("onClassChanged", {
"classData" : classData.toJson()
});
};

return Model;
});

appVersionChecker.js

define(function(require){
var $ = require('jquery');
var versionInfo;
var Browser = require('$UI/system/lib/base/browser');
var MsgDialog = require("$UI/system/components/justep/messageDialog/messageDialog");
require("cordova!cordova-plugin-app-version");
require("cordova!cordova-plugin-inappbrowser");

var parentNode = $('body').find('.window').get(0);

var VersionChecker = function(){
this.env = "browser";
if(Browser.isX5App){
if(Browser.isAndroid){
this.env = "androidApp";
}
if(Browser.isIOS){
this.env = "iosApp";
}
}
//this.env = "androidApp";

this.versionMsg = new MsgDialog({
parentNode:parentNode
});
var $domNode = this.versionMsg.$domNode;
$domNode.find('.Yes').text('更新');
$domNode.find('.No').text('忽略');
this.versionMsg.on('onYes', function(event) {
//下载
this.download();
}, this);
this.versionMsg.on('onNo', function(event) {
//忽略
this.ignore();
}, this);
var self = this;

document.addEventListener("deviceready", function() {
setTimeout(function(){
self.check();
},1000);
});
};

VersionChecker.prototype.check = function(){
var self = this;
if(cordova.getAppVersion){
cordova.getAppVersion.getVersionNumber(function (currentVersion) {
require(['./appVersion_in_server'],function(version_info){
if(version_info){
versionInfo = version_info;
if(versionInfo[self.env] && currentVersion < versionInfo[self.env].version && window.localStorage &&
localStorage.getItem('versionIgnore') !== versionInfo[self.env].version){
self.versionMsg.show({
type : "YesNoCancel",
title : "版本更新",
message : versionInfo[self.env].changeLog
});
}
}
},function(){
console.log('检查版本失败!');
});
});
}else{
console.log('请登录wex5.com下载最新版本体验系统!');
}
};

VersionChecker.prototype.download = function(){
window.open(versionInfo[this.env].downloadUrl,'_system');
};

VersionChecker.prototype.ignore = function(){
if(window.localStorage){
localStorage.setItem('versionIgnore',versionInfo[this.env].version);
}
};

return new VersionChecker();
});

appVersion_in_server.js

define(function(require){
var versionInfo = {
androidApp:{
version:"5.3.18",
changeLog:"请填写版本更新内容",
downloadUrl:"http://wex5.com/apps/account.apk"
},
iosApp:{
version:"5.3.18",
changeLog:"请填写版本更新内容",
downloadUrl:"itms-services:///?action=download-manifest&url=https://x.justep.com/apps/account.plist"
}
};
return versionInfo;
});