Skip to content
This repository was archived by the owner on Feb 20, 2024. It is now read-only.

Commit 993a171

Browse files
authored
Merge pull request #6 from AOFStudentCheckSystem/dev
Latest release
2 parents 1fcea5c + 418fb9d commit 993a171

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2364
-499
lines changed

app/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@
1010
"dependencies": {
1111
"@pokusew/pcsclite": "^0.4.17",
1212
"axios": "^0.16.1",
13+
"font-awesome": "^4.7.0",
1314
"framework7": "^1.6.0",
1415
"framework7-icons": "^0.8.9",
1516
"framework7-vue": "^0.9.0",
1617
"hexify": "^1.0.1",
1718
"moment": "^2.18.1",
1819
"vue": "^2.1.10",
1920
"vue-electron": "^1.0.6",
21+
"vue-virtual-scroller": "^0.6.1",
2022
"vuex": "^2.1.1"
2123
},
2224
"devDependencies": {},

app/src/main/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@ function createWindow () {
1212
* Initial window options
1313
*/
1414
mainWindow = new BrowserWindow({
15-
height: 600,
16-
width: 800,
15+
// height: 600,
16+
// width: 800,
1717
webPreferences: {
1818
scrollBounce: true
1919
},
2020
frame: false,
21-
title: 'Spectacle'
21+
title: 'Spectacle',
22+
fullscreen: process.env.NODE_ENV !== 'development'
2223
})
2324

2425
mainWindow.loadURL(winURL)

app/src/renderer/App.vue

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div id="app">
3-
<f7-statusbar></f7-statusbar>
3+
<!--<f7-statusbar></f7-statusbar>-->
44
<layout></layout>
55
<authentication-panel id="login-screen"></authentication-panel>
66
</div>
@@ -9,20 +9,27 @@
99
<script>
1010
import AuthenticationPanel from './components/Authentication/AuthenticationPanel.vue'
1111
import Layout from './components/Master/Layout.vue'
12+
1213
export default {
1314
components: {AuthenticationPanel, Layout}
1415
}
1516
</script>
1617

1718
<style>
19+
#app {
20+
font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', '微软雅黑', Arial, sans-serif;
21+
/*-webkit-font-smoothing: antialiased;*/
22+
/*-moz-osx-font-smoothing: grayscale;*/
23+
}
1824
body {
1925
-webkit-user-select: none;
2026
-webkit-app-region: no-drag;
2127
}
28+
.webkit-draggable {
29+
-webkit-app-region: drag;
30+
}
2231
</style>
2332

2433
<style scoped>
25-
.nav-bar {
26-
-webkit-app-region: drag;
27-
}
34+
2835
</style>

app/src/renderer/api/check.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export default {
1515
recordsToUpload: records.map((recordObj) => {
1616
return {
1717
studentId: recordObj.student.idNumber,
18-
timestamp: recordObj.timestamp
18+
timestamp: recordObj.checkInTime
1919
}
2020
})
2121
})).data

app/src/renderer/api/student.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ export default {
1919
studentId: student.idNumber
2020
})).data)
2121
},
22-
async bindCardWithStudent (student) {
22+
async bindCardWithStudent (student, cardSecret) {
2323
return new ActionResult((await http.post('student/edit/bind-card', {
2424
studentId: student.idNumber,
25-
cardSecret: student.cardSecret
25+
cardSecret: cardSecret
2626
})).data)
2727
},
2828
async pullStudent (id) {

app/src/renderer/components/Authentication/AuthenticationPanel.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
}).then(() => {
5151
self.$f7.hideIndicator()
5252
self.close()
53+
self.secret = ''
5354
}).catch((e) => {
5455
self.$f7.hideIndicator()
5556
self.$f7.alert(e, 'Error', () => {

app/src/renderer/components/Event/CheckPage.vue

Lines changed: 260 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,273 @@
22
* Created by dummy on 4/14/17.
33
*/
44
<style scoped>
5+
.remove-top-margin {
6+
margin-top: 0 !important;
7+
}
58
9+
.remove-all-margin {
10+
margin: 0 !important;
11+
}
612
</style>
713

814
<template>
9-
<f7-page name="event-check">
10-
<f7-navbar title="title" back-link="Back" sliding></f7-navbar>
11-
nothing here
15+
<f7-page name="event-check" @page:init="setPageActive(true)"
16+
@page:reinit="setPageActive(true)" @page:beforeremove="setPageActive(false)">
17+
<f7-navbar :title="computedTitle" back-link="Back" sliding>
18+
<f7-nav-right>
19+
<f7-link @click="stupidKidForgotHisCard">
20+
<f7-icon v-if="remove" f7="delete_round"></f7-icon>
21+
<f7-icon v-else f7="add_round"></f7-icon>
22+
</f7-link>
23+
</f7-nav-right>
24+
</f7-navbar>
25+
26+
<search-bar v-model="filter" @input="$refs['virtualscroller'].updateVisibleItems()" @overlayActive="overlayActive = $event"></search-bar>
27+
<search-bar-overlay :active="overlayActive"></search-bar-overlay>
28+
29+
<f7-block>
30+
<f7-grid>
31+
<f7-col :width="75 + !displayPhoto * 25">
32+
<f7-list no-hairlines no-hairlines-between inset class="remove-all-margin">
33+
<f7-list-item :title="'Records: ' + amountRecords"></f7-list-item>
34+
<f7-list-item :title="'Add: ' + amountAdd"></f7-list-item>
35+
<f7-list-item :title="'Remove: ' + amountRemove"></f7-list-item>
36+
<li class="media-item">
37+
<div class="item-content">
38+
<div class="item-inner">
39+
<div class="item-title-row">
40+
<div class="item-title">Scan To Remove</div>
41+
<div class="item-after">
42+
<f7-input type="switch" @input="setRemoveValue" :value="remove"></f7-input>
43+
</div>
44+
</div>
45+
</div>
46+
</div>
47+
</li>
48+
</f7-list>
49+
</f7-col>
50+
<f7-col v-if="displayPhoto" :width="25">
51+
<f7-block inset class="remove-all-margin">Reserved</f7-block>
52+
</f7-col>
53+
</f7-grid>
54+
</f7-block>
55+
56+
<virtual-scroller ref="virtualscroller" v-show="filteredCurrentEventRecords.length > 0" id="check-list" containerTag="ul" mainTag="div"
57+
:class="['list-block', 'media-list', 'check-searchbar-found', 'tablet-inset']"
58+
:items="filteredCurrentEventRecords" :itemHeight="63" keyField="id">
59+
<template scope="props">
60+
<li class="swipeout"
61+
:key="props.itemKey">
62+
<div class="swipeout-content">
63+
<div class="item-content">
64+
<div class="item-inner">
65+
<div class="item-title-row">
66+
<div class="item-title">{{props.item.student.lastName + ', ' + props.item.student.firstName}}</div>
67+
<div class="item-after"><span class="badge"
68+
:class="props.item.checkInTime >= 0 ? 'color-blue' : 'color-red'">{{props.item.checkInTime >= 0 ? 'Checked' : 'Removed'}}</span>
69+
</div>
70+
</div>
71+
<div class="item-subtitle">{{props.item.student.preferredName || props.item.student.firstName}}</div>
72+
</div>
73+
</div>
74+
</div>
75+
<!--<div class="swipeout-actions-left" v-if="props.item.checkInTime < 0">-->
76+
<!--<a class="swipeout-close swipeout-overswipe bg-blue" href="#">Add</a>-->
77+
<!--</div>-->
78+
<!--<div class="swipeout-actions-right" v-if="props.item.checkInTime >= 0">-->
79+
<!--<a class="swipeout-close swipeout-overswipe bg-red" href="#">Remove</a>-->
80+
<!--</div>-->
81+
<f7-swipeout-actions right v-if="props.item.checkInTime >= 0">
82+
<f7-swipeout-button close overswipe color="red" @click="removeSwiped(props.item.student)">Remove
83+
</f7-swipeout-button>
84+
</f7-swipeout-actions>
85+
<f7-swipeout-actions left v-if="props.item.checkInTime < 0">
86+
<f7-swipeout-button close overswipe color="blue" @click="addSwiped(props.item.student)">Add
87+
</f7-swipeout-button>
88+
</f7-swipeout-actions>
89+
</li>
90+
</template>
91+
</virtual-scroller>
92+
1293
</f7-page>
1394
</template>
1495

1596
<script>
16-
export default {}
97+
import {mapGetters} from 'vuex'
98+
import {SmartCardController} from 'smartcard'
99+
import {ActivityEventRecord} from '../../models/event'
100+
import {EventBusMixin} from '../../mixins/event-bus'
101+
import SearchBar from '../Master/SearchBar.vue'
102+
import SearchBarOverlay from '../Master/SearchBarOverlay.vue'
103+
104+
export default {
105+
mixins: [EventBusMixin],
106+
components: {SearchBar, SearchBarOverlay},
107+
data () {
108+
return {
109+
smart: null,
110+
errorCallbackUnsubscriber: null,
111+
connectCallbackUnsubscriber: null,
112+
pageActive: false,
113+
subscription: null,
114+
displayPhoto: false,
115+
filter: '',
116+
overlayActive: false,
117+
remove: false
118+
}
119+
},
120+
computed: {
121+
...mapGetters([
122+
'currentEvent',
123+
'sortedCurrentEventRecords',
124+
'cardSecretStudentMap'
125+
]),
126+
computedTitle () {
127+
return this.currentEvent ? this.currentEvent.name : ''
128+
},
129+
checkable () {
130+
return this.currentEvent ? this.currentEvent.status < 2 : false
131+
},
132+
amountRecords () {
133+
return this.sortedCurrentEventRecords.length
134+
},
135+
amountAdd () {
136+
return this.sortedCurrentEventRecords.reduce((acc, val) => {
137+
return val.checkInTime >= 0 ? ++acc : acc
138+
}, 0)
139+
},
140+
amountRemove () {
141+
return this.sortedCurrentEventRecords.reduce((acc, val) => {
142+
return val.checkInTime < 0 ? ++acc : acc
143+
}, 0)
144+
},
145+
filteredCurrentEventRecords () {
146+
const filter = this.filter
147+
return this.filter === '' ? this.sortedCurrentEventRecords : this.sortedCurrentEventRecords.filter((record) => {
148+
const student = record.student
149+
const fullName = (student.firstName + ' ' + student.lastName + ' ' + student.preferredName).toLowerCase()
150+
return fullName.includes(filter)
151+
})
152+
}
153+
},
154+
methods: {
155+
setRemoveValue (event) {
156+
this.remove = event
157+
},
158+
setPageActive (active) {
159+
this.pageActive = active
160+
},
161+
removeSwiped (student) {
162+
if (this.checkable) {
163+
this.$store.dispatch('addEventRecord', {
164+
record: new ActivityEventRecord({
165+
student: student,
166+
signUpTime: -1,
167+
checkInTime: -(new Date().getTime())
168+
})
169+
})
170+
this.$forceUpdate()
171+
}
172+
},
173+
addSwiped (student) {
174+
if (this.checkable) {
175+
this.$store.dispatch('addEventRecord', {
176+
record: new ActivityEventRecord({
177+
student: student,
178+
signUpTime: -1,
179+
checkInTime: new Date().getTime()
180+
})
181+
})
182+
this.$forceUpdate()
183+
}
184+
},
185+
addRecord (cardSecret) {
186+
if (this.checkable) {
187+
const toRemove = this.remove ? -1 : 1
188+
const cardSecretStudentMap = this.cardSecretStudentMap
189+
const foundStudent = cardSecretStudentMap[cardSecret.toLowerCase()] ||
190+
cardSecretStudentMap[cardSecret.toUpperCase()]
191+
if (foundStudent && this.currentEvent) {
192+
this.$store.dispatch('addEventRecord', {
193+
record: new ActivityEventRecord({
194+
student: foundStudent,
195+
signUpTime: -1,
196+
checkInTime: toRemove * new Date().getTime()
197+
})
198+
})
199+
this.$forceUpdate()
200+
} else {
201+
if (!this.subscription) {
202+
this.$publish(this.$channels.SELECT_STUDENT_POPUP)
203+
const self = this
204+
this.subscription = this.$subscribe(this.$channels.SELECTED_STUDENT, ({student}) => {
205+
self.$unsubscribe(self.subscription)
206+
self.subscription = null
207+
if (student) {
208+
self.$store.dispatch('addEventRecord', {
209+
record: new ActivityEventRecord({
210+
student: student,
211+
signUpTime: -1,
212+
checkInTime: toRemove * new Date().getTime()
213+
})
214+
})
215+
self.$store.dispatch('patchStudentCardSecret', {
216+
student, cardSecret
217+
})
218+
self.$forceUpdate()
219+
}
220+
})
221+
}
222+
}
223+
}
224+
},
225+
stupidKidForgotHisCard () {
226+
if (this.checkable) {
227+
if (!this.subscription) {
228+
const toRemove = this.remove ? -1 : 1
229+
this.$publish(this.$channels.SELECT_STUDENT_POPUP)
230+
const self = this
231+
this.subscription = this.$subscribe(this.$channels.SELECTED_STUDENT, ({student}) => {
232+
self.$unsubscribe(self.subscription)
233+
self.subscription = null
234+
if (student) {
235+
self.$store.dispatch('addEventRecord', {
236+
record: new ActivityEventRecord({
237+
student: student,
238+
signUpTime: -1,
239+
checkInTime: toRemove * new Date().getTime()
240+
})
241+
})
242+
self.$forceUpdate()
243+
}
244+
})
245+
}
246+
}
247+
}
248+
},
249+
created () {
250+
const self = this
251+
this.smart = new SmartCardController()
252+
this.errorCallbackUnsubscriber = this.smart.onError((error) => {
253+
console.log(error)
254+
})
255+
this.connectCallbackUnsubscriber = this.smart.onConnect((reader) => {
256+
console.log(self.currentEvent)
257+
reader.onInsert((card) => {
258+
if (self.pageActive && self.currentEvent) {
259+
self.addRecord(card.atr)
260+
}
261+
})
262+
reader.onError((error) => {
263+
console.log(error)
264+
})
265+
})
266+
},
267+
beforeDestroy () {
268+
this.smart ? this.smart.close() : undefined
269+
this.errorCallbackUnsubscriber ? this.errorCallbackUnsubscriber() : undefined
270+
this.connectCallbackUnsubscriber ? this.connectCallbackUnsubscriber() : undefined
271+
}
272+
}
17273
</script>
18274

0 commit comments

Comments
 (0)