f0ab4214 by 杨炀

no message

1 parent 4c57b42c
Showing 65 changed files with 795 additions and 2856 deletions
...@@ -493,6 +493,36 @@ function getMergePaymentInfo(mergeId) { ...@@ -493,6 +493,36 @@ function getMergePaymentInfo(mergeId) {
493 } 493 }
494 }) 494 })
495 } 495 }
496 // 一键下发
497 function submitCert(data) {
498 return request({
499 url: `/exam/payment/submitCerts/nesting`,
500 method: 'put',
501 params: data
502 })
503 }
504 function getCertsLList(query) {
505 return request({
506 url: '/exam/payment/certsList',
507 method: 'get',
508 params: query
509 })
510 }
511 function getExamListByPayId(params) {
512 return request({
513 url: `/exam/payment/examList/${params.payId}`,
514 method: 'get',
515 params: params
516 })
517 }
518 function certStudentList(query) {
519 return request({
520 url: '/exam/person/cert/studentList',
521 method: 'get',
522 params: query
523 })
524 }
525
496 526
497 export { 527 export {
498 getMessage, 528 getMessage,
...@@ -539,5 +569,7 @@ export { ...@@ -539,5 +569,7 @@ export {
539 groupCommitPaymentVoucher,getFeeBillById, 569 groupCommitPaymentVoucher,getFeeBillById,
540 personalCommit, 570 personalCommit,
541 delPayment,editYear,addPersonPaymentGroup, 571 delPayment,editYear,addPersonPaymentGroup,
542 commitRenew,getVerityMergeList,doMergeFlows,getMergePaymentInfo 572 commitRenew,getVerityMergeList,doMergeFlows,getMergePaymentInfo,
573 submitCert,getCertsLList,getExamListByPayId,
574 certStudentList
543 } 575 }
...\ No newline at end of file ...\ No newline at end of file
......
...@@ -148,6 +148,15 @@ color: #7D8592;} ...@@ -148,6 +148,15 @@ color: #7D8592;}
148 } 148 }
149 .mt30{margin-top: 30rpx;} 149 .mt30{margin-top: 30rpx;}
150 .userlist { 150 .userlist {
151 .func{display: flex;justify-content: flex-end;
152 border-top: 1px dashed #e5e5e5;padding-top: 20rpx;
153 button{border: 1px solid #AD181F;
154 border-radius: 30rpx;height: 60rpx;line-height: 60rpx;
155 font-size: 30rpx;color: #AD181F;background: #fff;
156 margin: 0 0 0 30rpx;padding: 0 60rpx;
157 }
158 text{font-size: 30rpx;padding:30rpx 0 0;}
159 }
151 .colorful { 160 .colorful {
152 width: 100rpx; 161 width: 100rpx;
153 margin-right: 14rpx; 162 margin-right: 14rpx;
......
1 <template>
2 <view class="content">
3 <swiper class="swiper"
4 :autoplay="autoplay"
5 :duration="duration">
6 <swiper-item>
7 <view class="swiper-item">
8 <view class="swiper-item-img"><image src="../../static/guide/title_01.png" mode="aspectFit"></image></view>
9 <view class="swiper-item-img"><image src="../../static/guide/icon_01.png" mode="aspectFit"></image></view>
10 </view>
11 <view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
12 </swiper-item>
13 <swiper-item>
14 <view class="swiper-item">
15 <view class="swiper-item-img"><image src="../../static/guide/title_02.png" mode="aspectFit"></image></view>
16 <view class="swiper-item-img"><image src="../../static/guide/icon_02.png" mode="aspectFit"></image></view>
17 </view>
18 <view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
19 </swiper-item>
20 <swiper-item>
21 <view class="swiper-item">
22 <view class="swiper-item-img"><image src="../../static/guide/title_03.png" mode="aspectFit"></image></view>
23 <view class="swiper-item-img"><image src="../../static/guide/icon_03.png" mode="aspectFit"></image></view>
24 </view>
25 <view class="jump-over" @tap="launchFlag()">{{jumpover}}</view>
26 </swiper-item>
27 <swiper-item>
28 <view class="swiper-item">
29 <view class="swiper-item-img"><image src="../../static/guide/title_04.png" mode="aspectFit"></image></view>
30 <view class="swiper-item-img"><image src="../../static/guide/icon_04.png" mode="aspectFit"></image></view>
31 </view>
32 <view class="experience" @tap="launchFlag()">{{experience}}</view>
33 </swiper-item>
34 </swiper>
35 <view class="uniapp-img"><image src="../../static/guide/uniapp4@2x.png" mode="aspectFit"></image></view>
36 </view>
37 </template>
38
39 <script>
40 export default {
41 data() {
42 return {
43 background: ['color1', 'color2', 'color3'],
44 autoplay: false,
45 duration: 500,
46 jumpover: '跳过',
47 experience: '立即体验'
48 }
49 },
50 methods: {
51 launchFlag: function(){
52 /**
53 * 向本地存储中设置launchFlag的值,即启动标识;
54 */
55 uni.setStorage({
56 key: 'launchFlag',
57 data: true,
58 });
59 uni.switchTab({
60 url: '/pages/tabBar/component/component'
61 });
62
63 }
64 }
65 }
66 </script>
67 <style>
68 page,
69 .content{
70 width: 100%;
71 height: 100%;
72 background-size: 100% auto ;
73 padding: 0;
74 }
75 .swiper{
76 width: 100%;
77 height: 80%;
78 background: #FFFFFF;
79 }
80 .swiper-item {
81 width: 100%;
82 height: 100%;
83 text-align: center;
84 position: relative;
85 display: flex;
86 /* justify-content: center; */
87 align-items:flex-end;
88 flex-direction:column-reverse
89 }
90 .swiper-item-img{
91 width: 100%;
92 height: auto;
93 margin: 0 auto;
94 }
95 .swiper-item-img image{
96 width: 80%;
97 }
98 .uniapp-img{
99 height: 20%;
100 background: #FFFFFF;
101 display: flex;
102 justify-content: center;
103 align-items:center;
104 overflow: hidden;
105 }
106 .uniapp-img image{
107 width: 40%;
108 }
109
110 .jump-over,.experience{
111 position: absolute;
112 height: 60upx;
113 line-height: 60upx;
114 padding: 0 40upx;
115 border-radius: 30upx;
116 font-size: 32upx;
117 color: #454343;
118 border: 1px solid #454343;
119 z-index: 999;
120 }
121 .jump-over{
122 right: 45upx;
123 top: 125upx;
124 }
125 .experience{
126 right: 50%;
127 margin-right: -105upx;
128 bottom: 0;
129 }
130 </style>
1 # 引导页
2
3 ### 基于uni-app框架的swiper组件打开的时候启动。
4
5 > 首次启动展示引导页,之后启动不再展示。那么就意味着,我们需要一个标识来确定,App是否已经启动过。
6
7 > 我们可以在本地存储一个key来做为已经启动过App的标识。那么,我们在入口这里,就可以读取这个key,来决定是否展示引导页。
8
9 > 因工作繁忙目前该程序金对安卓做了适配,IOS可根据环境自己适配。谢谢
10
11 ## 目录结构
12 * /pages/index/index.vue //入口页
13 ### 存储key
14 * 向本地存储中设置launchFlag的值,即启动标识;
15 ### 获取key
16 * 向本地存储中设置launchFlag的值,即启动标识;
17 * 获取本地存储中launchFlag的值
18 * 若存在,说明不是首次启动,直接进入首页;
19 * 若不存在,说明是首次启动,进入引导页;
20
21 ```html
22 <view class="main">
23 <code-elf-guide v-if="guidePages"></code-elf-guide>
24 </view>
25
26 ```
27
28 ```javascript
29 import codeElfGuide from '@/components/code-elf-guide/code-elf-guide.vue'
30 export default {
31 components: {
32 codeElfGuide
33 },
34 data() {
35 return {
36 guidePages:true
37 }
38 },
39 onLoad(){
40 this.loadExecution()
41 },
42 methods: {
43 loadExecution: function(){
44 /**
45 * 获取本地存储中launchFlag的值
46 * 若存在,说明不是首次启动,直接进入首页;
47 * 若不存在,说明是首次启动,进入引导页;
48 */
49 try {
50 // 获取本地存储中launchFlag标识
51 const value = uni.getStorageSync('launchFlag');
52 if (value) {
53 // launchFlag=true直接跳转到首页
54 uni.switchTab({
55 url: '/pages/tabBar/component/component'
56 });
57 } else {
58 // launchFlag!=true显示引导页
59 this.guidePages = true
60 }
61 } catch(e) {
62 // error
63 uni.setStorage({
64 key: 'launchFlag',
65 data: true,
66 success: function () {
67 console.log('error时存储launchFlag');
68 }
69 });
70 this.guidePages = true
71 }
72 }
73 }
74 }
75 ```
76 ```css
77 page,.main{
78 width: 100%;
79 height: 100%;
80 }
81
82 ```
83
84 ### 首页清除key,进行测试
85 * 清除本地存储中设置launchFlag的值,即启动标识;
86 * 两秒后重启APP,进行测试
87 ```javascript
88 uni.showModal({
89 title: '清除launchFlag值',
90 content: '确定要清除launchFlag值,进行重启测试?',
91 success: function (res) {
92 if (res.confirm) {
93 console.log('用户点击确定');
94 // 清除缓存
95 uni.clearStorage();
96 uni.showToast({
97 icon: 'none',
98 duration:3000,
99 title: '清除成功2秒后重启'
100 });
101 // 两秒后重启
102 setTimeout(function() {
103 uni.hideToast();
104 plus.runtime.restart();
105 }, 2000);
106 } else if (res.cancel) {
107 console.log('用户点击取消');
108 }
109 }
110 });
111 ```
...\ No newline at end of file ...\ No newline at end of file
1 # 日历组件 lx-calendar可选择周与月支持左右滑动切换
2
3
4 ```
5 <template>
6 <view class="content">
7
8 <lxCalendar @change="change"></lxCalendar>
9 </view>
10 </template>
11
12 <script>
13 import lxCalendar from '../../components/lx-calendar/lx-calendar.vue'
14 export default {
15 components:{
16 lxCalendar,
17 },
18 data() {
19 return {
20 title: 'Hello'
21 }
22 },
23
24 onLoad() {
25
26 },
27 methods: {
28 change(e){
29 console.log(e);
30 }
31
32 }
33 }
34 </script>
35 ```
36
37
38 事件 | 说明
39 ---|---
40 change | 日期改变时执行
41
42 参数 | 类型 | 说明
43 ---|---|---
44 value | 字符串 | 选中的日期
45 dot_lists | 数组 | 显示点的日期
46
47
48
49
50
1 <template>
2 <view class="date">
3 <view class="head" hidden>
4 <view class="icon" @click="switch_month_week('prev',true)"><text class="iconfont icon-fanhui" /></view>
5 <view class="title">{{nowYear+'年'+nowMonth+'月'}}</view>
6 <view class="icon" @click="switch_month_week('next',true)"><text class="iconfont next icon-fanhui" /></view>
7 </view>
8 <view class="date_dl">
9 <view class="dd" v-for="(item,index) in week" :key="index">{{item}}</view>
10 </view>
11 <view class="bigMonthInBottom">{{nowMonth+'月'}}</view>
12 <swiper :style="{height:(retract ? 2 * 60 : (week_list.length + 1) * 60 ) + 'rpx'}" :current="current" circular
13 @change="change_date">
14 <swiper-item>
15 <view class="date_dl" v-show="!retract || index == to_prev_week_index"
16 v-for="(item,index) in week_list_prev_co" :key="index">
17 <view class="dd" @click="item_click(vo,index,key)" v-for="(vo,key) in item" :key="key">
18 <view class="num"
19 :class="[vo.today ? 'today' : '',vo.cantOrder?'cantOrder':'',vo.type == 'month' ? 'month' : (retract ? '' : 'disabled')]">
20 {{vo.day}}
21 </view>
22 <view v-show="vo.dot && (vo.type == 'month' || retract)" class="dot"></view>
23 </view>
24 </view>
25 <view @click="open" class="retract icon"><text class="iconfont next icon-fanhui"
26 :class="[retract ? '' : 'retract_icon']" /></view>
27 </swiper-item>
28 <swiper-item>
29
30 <view class="date_dl" v-show="!retract || index == to_week_index" v-for="(item,index) in week_list"
31 :key="index">
32 <view class="dd" @click="item_click(vo,index,key)" v-for="(vo,key) in item" :key="key">
33 <view class="num"
34 :class="[vo.today ? 'today' : '',vo.cantOrder?'cantOrder':'',vo.type == 'month' ? 'month' : (retract ? '' : 'disabled')]">
35 {{vo.day}}
36 </view>
37 <view v-show="vo.dot && (vo.type == 'month' || retract)" class="dot"></view>
38 </view>
39 </view>
40 <view @click="open" class="retract icon"><text class="iconfont next icon-fanhui"
41 :class="[retract ? '' : 'retract_icon']" /></view>
42 </swiper-item>
43 <swiper-item>
44
45 <view class="date_dl" v-show="!retract || index == to_next_week_index"
46 v-for="(item,index) in week_list_next_co" :key="index">
47 <view class="dd" @click="item_click(vo,index,key)" v-for="(vo,key) in item" :key="key">
48 <view class="num"
49 :class="[vo.today ? 'today' : '',vo.cantOrder?'cantOrder':'',vo.type == 'month' ? 'month' : (retract ? '' : 'disabled')]">
50 {{vo.day}}
51 </view>
52 <view v-show="vo.dot && (vo.type == 'month' || retract)" class="dot"></view>
53 </view>
54 </view>
55 <view @click="open" class="retract icon"><text class="iconfont next icon-fanhui"
56 :class="[retract ? '' : 'retract_icon']" /></view>
57 </swiper-item>
58 </swiper>
59 </view>
60 </template>
61
62 <script>
63 import dayjs from 'dayjs';
64 export default {
65 props: {
66 value: {
67 type: [String, Number],
68 default: ''
69 },
70 dot_lists: {
71 type: Array,
72 default: () => {
73 return [];
74 }
75 },
76 startTime: {
77 type: Number,
78 default: 0
79 },
80 endTime: {
81 type: Number,
82 default: 0
83 }
84 },
85 data() {
86 return {
87 debug: false,
88 week: ['日', '一', '二', '三', '四', '五', '六'],
89 week_list: [],
90 week_list_prev: [],
91 week_list_prev_week: [],
92 week_list_next: [],
93 week_list_next_week: [],
94 now_date: '',
95 start_date: '',
96 end_date: '',
97 prev_date: '',
98 next_date: '',
99 nowYear: '',
100 nowMonth: '',
101 nowDay: '',
102 retract: true,
103 to_week_index: 0,
104 to_prev_week_index: 0,
105 to_next_week_index: 0,
106 nowTime: 0,
107 dot_list: [],
108 current: 1,
109 date: '',
110 cantOrder: false
111 }
112 },
113 watch: {
114 value(value) {
115 this.get_date(this.date_parse(value));
116 },
117
118
119 dot_lists: {
120 immediate: true,
121 handler(value) {
122
123 this.dot_list = value;
124 this.set_doc_lists_update()
125 }
126 },
127 endTime:{
128 handler(value) {
129 this.doc_list_update()
130 }
131 }
132
133 },
134 computed: {
135 week_list_prev_co() {
136 return this.retract ? this.week_list_prev_week : this.week_list_prev
137 },
138 week_list_next_co() {
139 return this.retract ? this.week_list_next_week : this.week_list_next
140 }
141 },
142 created() {
143 this.init();
144 },
145 mounted() {
146 // this.doc_list_update();
147 },
148 methods: {
149 change() {
150 let value = {
151 fulldate: this.date.replace(/-(\d)(?!\d)/g, '-0$1')
152 };
153 this.$emit('change', value)
154 },
155 init() {
156 if (this.value) {
157 this.get_date(this.date_parse(this.value));
158 } else {
159 this.get_date();
160 }
161 this.update_month();
162 },
163 open() {
164 this.retract = !this.retract;
165 this.get_date(this.nowTime);
166 this.set_to_day('week_list_prev')
167 this.set_to_day('week_list_next')
168
169 this.change_week();
170
171 if (this.retract) {
172 this.update_swiper_item('week')
173 } else {
174 this.update_swiper_item('month')
175 }
176 this.set_doc_lists_update();
177 },
178 change_week() {
179 if (this.to_week_index < this.week_list.length - 1) {
180 this.to_next_week_index = this.to_week_index + 1;
181 this.week_list_next_week = this.week_list;
182 } else {
183 this.to_next_week_index = 0;
184 this.week_list_next_week = this.week_list_next;
185 }
186
187 if (this.to_week_index == 0) {
188
189 this.update_month();
190
191 // if(){
192 let next_day = this.week_list_prev[this.week_list_prev.length - 1][6].day;
193
194 // }
195 this.to_prev_week_index = this.week_list_prev.length - 1 - Math.ceil(next_day / 7);
196
197 this.week_list_prev_week = JSON.parse(JSON.stringify(this.week_list_prev));
198
199
200
201
202
203 } else {
204 this.to_prev_week_index = this.to_week_index - 1;
205 this.week_list_prev_week = this.week_list;
206 }
207
208 // if(this.current == 1){
209
210 // }
211 // let to_week_index = this.to_week_index;
212 // if(this.current == 2){
213 // this.to_next_week_index = this.to_week_index;
214 // this.to_week_index = this.to_week_index - 1;
215 // this.to_prev_week_index = this.to_next_week_index + 1;
216 // }else if(this.current == 0){
217 // this.to_next_week_index = this.to_week_index;
218 // this.to_week_index = this.to_week_index - 1;
219 // this.to_prev_week_index = this.to_next_week_index + 1;
220 // }
221
222
223
224
225
226
227 },
228 change_date_week(type) {
229 let week_list = this.week_list;
230 let to_week_index = this.to_week_index;
231 if (type == 'prev') {
232 this.to_week_index = this.to_prev_week_index;
233 this.to_prev_week_index = this.to_next_week_index
234 this.to_next_week_index = to_week_index;
235
236 this.week_list = this.week_list_prev_week
237 this.week_list_prev_week = this.week_list_next_week;
238 this.week_list_next_week = week_list;
239
240
241
242 } else if (type == 'next') {
243 this.to_week_index = this.to_next_week_index;
244 this.to_next_week_index = this.to_prev_week_index
245 this.to_prev_week_index = to_week_index;
246
247 this.week_list = this.week_list_next_week
248 this.week_list_next_week = this.week_list_prev_week;
249 this.week_list_prev_week = week_list;
250
251
252 }
253
254 this.set_to_day_all();
255 },
256 change_date_month(type) {
257 let week_list = this.week_list;
258 if (type == 'prev') {
259 this.week_list = this.week_list_prev
260 this.week_list_prev = this.week_list_next;
261 this.week_list_next = week_list;
262 } else if (type == 'next') {
263 this.week_list = this.week_list_next
264 this.week_list_next = this.week_list_prev;
265 this.week_list_prev = week_list;
266 }
267 },
268 change_date(e) {
269 if (this.current == e.detail.current) {
270 this.change()
271 return
272 }
273
274
275
276 let primary_current = this.current
277 let current = e.detail.current;
278
279 this.current = current;
280
281
282 if (primary_current - current == -1 || primary_current - current == 2) {
283
284 if (this.retract) {
285 this.switch_month_week('next')
286 this.change_week()
287 if (primary_current - current == -1 && current != 1) {
288 this.change_date_week('prev')
289 } else if (primary_current - current == 2) {
290 this.change_date_week('next')
291 }
292 } else {
293 this.get_date(this.get_month('next'));
294 this.update_month();
295 if (primary_current - current == -1 && current != 1) {
296 this.change_date_month('prev')
297 } else if (primary_current - current == 2) {
298 this.change_date_month('next')
299 }
300 }
301 } else {
302 if (this.retract) {
303 this.switch_month_week('prev')
304 this.change_week()
305 if (primary_current - current == 1 && current != 1) {
306 this.change_date_week('next')
307 } else if (primary_current - current == -2) {
308 this.change_date_week('prev')
309 }
310
311
312 } else {
313 this.get_date(this.get_month('prev'));
314 this.update_month();
315 if (primary_current - current == 1 && current != 1) {
316 this.change_date_month('next')
317 } else if (primary_current - current == -2) {
318 this.change_date_month('prev')
319 }
320 }
321 }
322
323 this.set_to_day_all();
324 this.set_doc_lists_update();
325 this.change()
326 },
327 update_month() {
328 this.get_date(this.get_month('prev'), 'prev');
329 this.get_date(this.get_month('next'), 'next');
330 },
331 set_doc_lists_update() {
332 this.doc_list_update('week_list');
333 this.doc_list_update('week_list_prev');
334 this.doc_list_update('week_list_next');
335 this.doc_list_update('week_list_prev_week')
336 this.doc_list_update('week_list_next_week')
337 },
338 doc_list_update(week_list = 'week_list') {
339 let list = [],
340 dayTime;
341 this[week_list].map((item, index) => {
342 list.push(item.map((vo, key) => {
343 if (this.dot_list.indexOf(vo.date) > -1 || this.dot_list.indexOf(vo.date
344 .replace(/-(\d)(?!\d)/g, '-0$1')) > -1) {
345 vo.dot = true;
346
347 } else {
348 vo.dot = false;
349 }
350
351
352 dayTime = dayjs(vo.date).valueOf()
353 if (dayTime < this.startTime || (this.endTime != 0 && dayTime >= this
354 .endTime)) {
355 vo.cantOrder = true
356 } else {
357 vo.cantOrder = false
358 }
359
360 return {
361 ...vo
362 }
363 }))
364 })
365 this[week_list] = list;
366 },
367 set_to_day(type) {
368 let list = [];
369
370 this[type].map((item, index) => {
371 list.push(item.map((vo, key) => {
372 if (vo.date == `${this.date}`) {
373 vo.today = true;
374 } else {
375 vo.today = false;
376 }
377 return {
378 ...vo
379 };
380 }))
381 })
382 this[type] = list;
383 },
384 item_click(item, item_index = -1) {
385 if (item.date == this.date) {
386 return
387 }
388
389 // if(item.cantOrder){
390 // // 不能预订的
391 // return
392 // }
393
394 if (!this.retract && item.type !== 'month') {
395 return false;
396 }
397 this.date = item.date;;
398 if (item.type == 'month') {
399 this.nowDay = item.day;
400 if (item_index >= 0) this.to_week_index = item_index;
401
402 } else if (this.retract) {
403 this.nowDay = item.day;
404 }
405
406 let now_arr = item.date.split('-')
407 this.nowYear = now_arr[0];
408 this.nowMonth = now_arr[1];
409 this.nowDay = now_arr[2];
410
411
412 this.set_to_day_all(item_index);
413
414 this.nowTime = this.date_parse(`${item.date}`);
415
416 this.change()
417 this.set_doc_lists_update();
418
419 },
420 set_to_day_all(item_index) {
421 this.set_to_day('week_list')
422 this.set_to_day('week_list_prev')
423 this.set_to_day('week_list_next')
424 this.set_to_day('week_list_prev_week')
425 this.set_to_day('week_list_next_week')
426
427 },
428 get_month(type) {
429 let nowMonth = this.nowMonth;
430 let nowYear = this.nowYear;
431 let nowDay = this.nowDay;
432
433 if (type == 'prev') {
434 if (nowMonth == 1) {
435 nowMonth = 12;
436 nowYear = nowYear - 1;
437 } else {
438 nowMonth--;
439 }
440 } else if (type == 'next') {
441 if (nowMonth == 12) {
442 nowMonth = 1;
443 nowYear = nowYear + 1;
444 } else {
445 nowMonth++;
446 }
447 }
448
449 let days = this.get_month_days(nowMonth, nowYear);
450 if (nowDay > days) {
451 nowDay = days;
452 }
453
454 return this.date_parse(`${nowYear}-${nowMonth}-${nowDay}`);
455 },
456
457 date_parse(str) {
458 return Date.parse(str.replace(/-(\d)(?!\d)/g, '-0$1'));
459 },
460 switch_month_week(type = 'next', update_week = false) {
461 if (this.retract) {
462 if (type == 'prev') {
463 this.get_date(this.nowTime - 86400 * 7 * 1000);
464 } else if (type == 'next') {
465 this.get_date(this.nowTime + 86401 * 7 * 1000);
466 }
467 if (update_week) {
468 this.update_swiper_item('week');
469 this.set_doc_lists_update();
470 }
471 } else {
472 this.get_date(this.get_month(type))
473 this.update_swiper_item('month');
474 }
475 this.set_doc_lists_update();
476
477 this.set_to_day_all();
478
479 if (update_week) {
480 this.change()
481 }
482
483 },
484 update_swiper_item(type = 'month') {
485 if (type == 'month') {
486 if (this.current == 0) {
487 this.change_date_month('next')
488 } else if (this.current == 2) {
489 this.change_date_month('prev')
490 }
491 } else if (type == 'week') {
492
493 if (this.current == 0) {
494 this.change_date_week('next')
495 } else if (this.current == 2) {
496 this.change_date_week('prev')
497 }
498 }
499 },
500 next() {
501 this.get_date(this.next_date)
502 },
503 get_date(value = '', type = 'same') {
504 let date = new Date();
505 if (value) {
506 date = new Date(value);
507 }
508 let nowMonth = date.getMonth() + 1,
509 nowYear = date.getFullYear(),
510 nowDay = date.getDate(),
511 nowTime = date.getTime(),
512 nowWeek = date.getDay();
513
514
515 let days = this.get_month_days(nowMonth, nowYear);
516 let start_date = new Date(nowYear, nowMonth - 1, 1);
517 let end_date = new Date(nowYear, nowMonth - 1, days);
518 let prev_date = new Date(start_date.getTime() - 1);
519 let prev_date_days = prev_date.getDate();
520 let next_date = new Date(end_date.getTime() + 86401 * 1000);
521 let next_date_days = next_date.getDate();
522 let start_week = start_date.getDay();
523 let date_arrs = [];
524
525 let week_list = [];
526 let count_days = 35;
527
528 for (let i = prev_date_days - start_week + 1; i <= prev_date_days; i++) {
529 date_arrs.push({
530 day: i,
531 type: 'prev',
532 date: `${prev_date.getFullYear()}-${prev_date.getMonth()+1}-${i}`
533 })
534 }
535
536 for (let i = 1; i <= days; i++) {
537 date_arrs.push({
538 day: i,
539 type: 'month',
540 today: i == nowDay ? true : false,
541 date: `${nowYear}-${nowMonth}-${i}`
542 })
543
544 if (i == nowDay && type == 'same') {
545 this.date = `${nowYear}-${nowMonth}-${i}`;
546 }
547
548 }
549 if (this.debug) console.log(value, date, this.date,
550 `${next_date.getFullYear()}-${next_date.getMonth()+1}-${next_date.getDate()}`)
551 let date_arrs_length = date_arrs.length;
552
553 // if(date_arrs_length > 35){
554 count_days = 42;
555 // }
556 for (let i = 1; i <= count_days - date_arrs_length; i++) {
557 date_arrs.push({
558 day: i,
559 type: 'next',
560 date: `${next_date.getFullYear()}-${next_date.getMonth()+1}-${i}`
561 })
562 }
563
564 for (let i = 0; i < date_arrs.length / 7; i++) {
565 let arr = [];
566 for (let j = 0; j < 7; j++) {
567
568 if (date_arrs[i * 7 + j].today) {
569 if (type == 'same') {
570 this.to_week_index = i
571 }
572 }
573 arr.push(date_arrs[i * 7 + j]);
574 }
575 week_list.push(arr);
576 }
577
578 if (type == 'same') {
579 this.week_list = week_list;
580 this.nowYear = nowYear;
581 this.nowMonth = nowMonth;
582 this.nowDay = nowDay;
583 this.nowTime = nowTime;
584 this.start_date = start_date;
585 this.end_date = end_date;
586 this.prev_date = prev_date;
587 this.next_date = next_date;
588
589 } else if (type == 'prev') {
590 this.week_list_prev = week_list;
591 } else if (type == 'next') {
592 this.week_list_next = week_list;
593 }
594
595 },
596 get_month_days(nowMonth, nowYear) {
597 let month_arr = [1, 3, 5, 7, 8, 10, 12];
598 let days = 0;
599 if (nowMonth == 2) {
600 if (nowYear % 4 == 0) {
601 days = 29;
602 } else {
603 days = 28;
604 }
605 } else if (month_arr.indexOf(nowMonth) >= 0) {
606 days = 31;
607 } else {
608 days = 30;
609 }
610 return days;
611 }
612 }
613 }
614 </script>
615
616 <style lang="less">
617 @import (less) '../../static/lx-calendar/fonts/iconfont.css';
618
619 @color: #1EC886;
620 @color_disabled: #f1f1f1;
621 @color_cantOrder: #999;
622 @color_standard: #333;
623 @color_border: #f5f5f5;
624
625 .date {
626 position: relative;
627 overflow: hidden;
628 border-radius: 20rpx 20rpx 0px 0px;
629 width: 750rpx;
630 background: #F7F8FA;
631 }
632
633 .head {
634 display: flex;
635 align-items: center;
636 height: 100rpx;
637 justify-content: center;
638 border-bottom: 1rpx solid @color_border;
639 color: @color_standard;
640
641 .title {
642 width: 200rpx;
643 font-size: 30rpx;
644 text-align: center;
645 }
646
647 .icon {
648 display: block;
649
650 .next {
651 transform: rotate(180deg);
652 display: block;
653 }
654 }
655 }
656
657 .retract {
658 display: flex;
659 justify-content: center;
660 align-items: center;
661 height: 80rpx;
662 ;
663
664 .iconfont {
665 transform: rotate(270deg);
666
667 &.retract_icon {
668 transform: rotate(90deg);
669 }
670 }
671 }
672
673 .date_dl {
674 display: flex;
675 width: 100%;
676
677 .dd {
678 flex: 1;
679 text-align: center;
680 height: 60rpx;
681 font-size: 24rpx;
682 color: #666666;
683 display: flex;
684 flex-direction: column;
685 align-items: center;
686 justify-content: center;
687 position: relative;
688
689 .num {
690 font-size: 28rpx;
691 width: 60rpx;
692 height: 60rpx;
693 border-radius: 50%;
694 line-height: 60rpx;
695 &.month {
696 color: @color_standard;
697 }
698 &.cantOrder {
699 color: @color_cantOrder;
700 }
701 &.today {
702 background: @color;
703 color: #fff;
704 }
705 &.disabled {
706 color: @color_disabled;
707 }
708 }
709
710 .dot {
711 width: 8rpx;
712 height: 8rpx;
713 border-radius: 50%;
714 background: @color;
715 position: absolute;
716 bottom: 0;
717 left: 50%;
718 transform: translateX(-50%);
719 }
720 }
721 }
722
723 .bigMonthInBottom {
724 font-size: 160rpx;
725 color: #c7e0de;
726 position: absolute;
727 left: 0;
728 right: 0;
729 text-align: center;
730 top: 140rpx;
731 }
732 </style>
1 # slider-range
2 uni-app 滑块区间选择组件
3
4 可根据具体需求,修改、自定义其他内容。
5
6 ## 属性说明
7
8 |属性名|类型|默认值|说明|
9 | -- | -- | --|--|
10 | value | Array<Number, Number> | [0,100] |滑块已选中区间的值|
11 | min | Number| 0 | 滑块区间最小值 |
12 | max | Number | 100 | 滑块区间最大值 |
13 | step | Number | 1 | 拖动时的步长 |
14 | disabled | Boolean | false | 是否为禁用状态 |
15 | height | Number | 50 | 滑块容器高度 |
16 | barHeight | Number | 5 | 滑块进度条高度 |
17 | backgroundColor | String | #e9e9e9| 滑块进度条背景色|
18 | activeColor | String | #1aad19 | 已选中区间进度条颜色|
19 | blockSize | Number | 20 | 滑块大小 |
20 | blockColor | String | #fff | 滑块颜色 |
21 | decorationVisible | Boolean | false | 是否显示滑块内装饰元素|
22 | tipVisible | Boolean | true | 是否显示滑块值提示文本 |
23 | fomat| Function | | 滑块值提示文本格式化函数,**注意**:小程序中此属性必传,否则会报错,如果无需格式化,可以简单返回原始值: `format(val) { return val }`;H5中可以不传。|
24
25
26 ## 使用示例
27
28 ```html
29
30 <slider-range
31 :value="rangeValue"
32 :min="rangeMin"
33 :max="rangMax"
34 :step="5"
35 :bar-height="3"
36 :block-size="26"
37 background-color="#EEEEF6"
38 active-color="#FF6B00"
39 :format="format"
40 :decorationVisible="true"
41 @change="handleRangeChange"
42 ></slider-range>
43
44
45 ```
46
47 ```javascript
48
49 import SliderRange from '../components/slider-range/index.vue'
50 export default {
51 components: {
52 SliderRange
53 },
54 data() {
55 return {
56 rangeMin: 5,
57 rangMax: 200,
58 rangeValue: [10, 50]
59 }
60 },
61 methods: {
62 format(val) {
63 return val + '%'
64 },
65 handleRangeChange(e) {
66 this.rangeValue = e
67 }
68 }
69 }
70 ```
71
72 效果图
73
74 ![](http://images.alisali.cn/img_20190715175325.png)
1 <template>
2 <view
3 class="slider-range"
4 :class="{ disabled: disabled }"
5 :style="{ paddingLeft: blockSize / 2 + 'px', paddingRight: blockSize / 2 + 'px' }"
6 >
7 <view class="slider-range-inner" :style="{ height: height + 'px' }">
8 <view
9 class="slider-bar"
10 :style="{
11 height: barHeight + 'px',
12 }"
13 >
14 <!-- 背景条 -->
15 <view
16 class="slider-bar-bg"
17 :style="{
18 backgroundColor: backgroundColor,
19 }"
20 ></view>
21
22 <!-- 滑块实际区间 -->
23 <view
24 class="slider-bar-inner"
25 :style="{
26 width: ((values[1] - values[0]) / (max - min)) * 100 + '%',
27 left: lowerHandlePosition + '%',
28 backgroundColor: activeColor,
29 }"
30 ></view>
31 </view>
32
33 <!-- 滑动块-左 -->
34 <view
35 class="slider-handle-block"
36 :class="{ decoration: decorationVisible }"
37 :style="{
38 backgroundColor: blockColor,
39 width: blockSize + 'px',
40 height: blockSize + 'px',
41 left: lowerHandlePosition + '%',
42 }"
43 @touchstart="_onTouchStart"
44 @touchmove="_onBlockTouchMove"
45 @touchend="_onBlockTouchEnd"
46 data-tag="lowerBlock"
47 ></view>
48
49 <!-- 滑动块-右 -->
50 <view
51 class="slider-handle-block"
52 :class="{ decoration: decorationVisible }"
53 :style="{
54 backgroundColor: blockColor,
55 width: blockSize + 'px',
56 height: blockSize + 'px',
57 left: higherHandlePosition + '%',
58 }"
59 @touchstart="_onTouchStart"
60 @touchmove="_onBlockTouchMove"
61 @touchend="_onBlockTouchEnd"
62 data-tag="higherBlock"
63 ></view>
64
65 <!-- 滑块值提示 -->
66 <view v-if="tipVisible" class="range-tip" :style="lowerTipStyle">{{ format(values[0]) }}</view>
67 <view v-if="tipVisible" class="range-tip" :style="higherTipStyle">{{ format(values[1]) }}</view>
68 </view>
69 </view>
70 </template>
71 <script>
72 export default {
73 components: {},
74 props: {
75 //滑块区间当前取值
76 value: {
77 type: Array,
78 default: function() {
79 return [0, 100]
80 },
81 },
82 //最小值
83 min: {
84 type: Number,
85 default: 0,
86 },
87 //最大值
88 max: {
89 type: Number,
90 default: 100,
91 },
92 step: {
93 type: Number,
94 default: 1,
95 },
96 format: {
97 type: Function,
98 default: function(val) {
99 return val
100 },
101 },
102 disabled: {
103 type: Boolean,
104 default: false,
105 },
106 //滑块容器高度
107 height: {
108 height: Number,
109 default: 50,
110 },
111 //区间进度条高度
112 barHeight: {
113 type: Number,
114 default: 5,
115 },
116 //背景条颜色
117 backgroundColor: {
118 type: String,
119 default: '#e9e9e9',
120 },
121 //已选择的颜色
122 activeColor: {
123 type: String,
124 default: '#1aad19',
125 },
126 //滑块大小
127 blockSize: {
128 type: Number,
129 default: 20,
130 },
131 blockColor: {
132 type: String,
133 default: '#fff',
134 },
135 tipVisible: {
136 type: Boolean,
137 default: true,
138 },
139 decorationVisible: {
140 type: Boolean,
141 default: false,
142 },
143 },
144 data() {
145 return {
146 values: [this.min, this.max],
147 startDragPos: 0, // 开始拖动时的坐标位置
148 startVal: 0, //开始拖动时较小点的值
149 }
150 },
151 computed: {
152 // 较小点滑块的坐标
153 lowerHandlePosition() {
154 return ((this.values[0] - this.min) / (this.max - this.min)) * 100
155 },
156 // 较大点滑块的坐标
157 higherHandlePosition() {
158 return ((this.values[1] - this.min) / (this.max - this.min)) * 100
159 },
160 lowerTipStyle() {
161 if (this.lowerHandlePosition < 90) {
162 return `left: ${this.lowerHandlePosition}%;`
163 }
164 return `right: ${100 - this.lowerHandlePosition}%;transform: translate(50%, -100%);`
165 },
166 higherTipStyle() {
167 if (this.higherHandlePosition < 90) {
168 return `left: ${this.higherHandlePosition}%;`
169 }
170 return `right: ${100 - this.higherHandlePosition}%;transform: translate(50%, -100%);`
171 },
172 },
173 created: function() {},
174 onLoad: function(option) {},
175 watch: {
176 //滑块当前值
177 value: {
178 immediate: true,
179 handler(newVal, oldVal) {
180 if (this._isValuesValid(newVal) && (newVal[0] !== this.values[0] || newVal[1] !== this.values[1])) {
181 this._updateValue(newVal)
182 }
183 },
184 },
185 },
186 methods: {
187 _updateValue(newVal) {
188 // 步长大于区间差,或者区间最大值和最小值相等情况
189 if (this.step >= this.max - this.min) {
190 throw new RangeError('Invalid slider step or slider range')
191 }
192
193 let newValues = []
194 if (Array.isArray(newVal)) {
195 newValues = [newVal[0], newVal[1]]
196 }
197 if (typeof newValues[0] !== 'number') {
198 newValues[0] = this.values[0]
199 } else {
200 newValues[0] = Math.round((newValues[0] - this.min) / this.step) * this.step + this.min
201 }
202 if (typeof newValues[1] !== 'number') {
203 newValues[1] = this.values[1]
204 } else {
205 newValues[1] = Math.round((newValues[1] - this.min) / this.step) * this.step + this.min
206 }
207
208 // 新值与原值相等,不做处理
209 if (this.values[0] === newValues[0] && this.values[1] === newValues[1]) {
210 return
211 }
212 // 左侧滑块值小于最小值时,设置为最小值
213 if (newValues[0] < this.min) {
214 newValues[0] = this.min
215 }
216 // 右侧滑块值大于最大值时,设置为最大值
217 if (newValues[1] > this.max) {
218 newValues[1] = this.max
219 }
220 // 两个滑块重叠或左右交错,使两个滑块保持最小步长的间距
221 if (newValues[0] >= newValues[1]) {
222 // 左侧未动,右侧滑块滑到左侧滑块之左
223 if (newValues[0] === this.values[0]) {
224 newValues[1] = newValues[0] + this.step
225 } else {
226 // 右侧未动, 左侧滑块滑到右侧之右
227 newValues[0] = newValues[1] - this.step
228 }
229 }
230
231 this.values = newValues
232 this.$emit('change', this.values)
233 },
234 _onTouchStart: function(event) {
235 if (this.disabled) {
236 return
237 }
238
239 this.isDragging = true
240 let tag = event.target.dataset.tag
241
242 //兼容h5平台及某版本微信
243 let e = event.changedTouches ? event.changedTouches[0] : event
244 this.startDragPos = e.pageX
245
246 this.startVal = tag === 'lowerBlock' ? this.values[0] : this.values[1]
247 },
248 _onBlockTouchMove: function(e) {
249 if (this.disabled) {
250 return
251 }
252 this._onDrag(e)
253 },
254 _onBlockTouchEnd: function(e) {
255 if (this.disabled) {
256 return
257 }
258 this.isDragging = false
259 this._onDrag(e)
260 },
261 _onDrag(event) {
262 if (!this.isDragging) {
263 return
264 }
265 let view = uni
266 .createSelectorQuery()
267 .in(this)
268 .select('.slider-range-inner')
269
270 view
271 .boundingClientRect(data => {
272 let sliderWidth = data.width
273 const tag = event.target.dataset.tag
274 let e = event.changedTouches ? event.changedTouches[0] : event
275 let diff = ((e.pageX - this.startDragPos) / sliderWidth) * (this.max - this.min)
276 let nextVal = this.startVal + diff
277
278 if (tag === 'lowerBlock') {
279 this._updateValue([nextVal, null])
280 } else {
281 this._updateValue([null, nextVal])
282 }
283 })
284 .exec()
285 },
286 _isValuesValid: function(values) {
287 return Array.isArray(values) && values.length == 2
288 },
289 },
290 }
291 </script>
292
293 <style scoped>
294 .slider-range {
295 position: relative;
296 padding-top: 40rpx;
297 }
298
299 .slider-range-inner {
300 position: relative;
301 width: 100%;
302 }
303
304 .slider-range.disabled .slider-bar-inner {
305 opacity: 0.35;
306 }
307
308 .slider-range.disabled .slider-handle-block {
309 cursor: not-allowed;
310 }
311
312 .slider-bar {
313 position: absolute;
314 top: 50%;
315 left: 0;
316 right: 0;
317 transform: translateY(-50%);
318 }
319
320 .slider-bar-bg {
321 position: absolute;
322 width: 100%;
323 height: 100%;
324 border-radius: 10000px;
325 z-index: 10;
326 }
327
328 .slider-bar-inner {
329 position: absolute;
330 width: 100%;
331 height: 100%;
332 border-radius: 10000px;
333 z-index: 11;
334 }
335
336 .slider-handle-block {
337 position: absolute;
338 top: 50%;
339 transform: translate(-50%, -50%);
340 border-radius: 50%;
341 box-shadow: 0 0 3px 2px rgba(227, 229, 241, 0.5);
342 z-index: 12;
343 }
344
345 .slider-handle-block.decoration::before {
346 position: absolute;
347 content: '';
348 width: 6upx;
349 height: 24upx;
350 top: 50%;
351 left: 29%;
352 transform: translateY(-50%);
353 background: #eeedf2;
354 border-radius: 3upx;
355 z-index: 13;
356 }
357
358 .slider-handle-block.decoration::after {
359 position: absolute;
360 content: '';
361 width: 6upx;
362 height: 24upx;
363 top: 50%;
364 right: 29%;
365 transform: translateY(-50%);
366 background: #eeedf2;
367 border-radius: 3upx;
368 z-index: 13;
369 }
370
371 .range-tip {
372 position: absolute;
373 top: 0;
374 font-size: 24upx;
375 color: #666;
376 transform: translate(-50%, -100%);
377 }
378 </style>
1 <template>
2 <view class="demo-slider-range">
3 <view class="section-title">普通用法</view>
4 <view class="slider-item">
5 <slider-range
6 :value="slider1.rangeValue"
7 :min="slider1.min"
8 :max="slider1.max"
9 :step="slider1.step"
10 :bar-height="barHeight"
11 :block-size="blockSize"
12 :background-color="backgroundColor"
13 :format="format1"
14 @change="handleRangeChange"
15 ></slider-range>
16 </view>
17 <view class="section-title">自定义</view>
18 <view class="slider-item">
19 <slider-range
20 :value="slider2.rangeValue"
21 :min="slider2.min"
22 :max="slider2.max"
23 :step="slider2.step"
24 :bar-height="barHeight"
25 :block-size="blockSize"
26 :background-color="backgroundColor"
27 :active-color="slider2.activeColor"
28 :format="format2"
29 :decorationVisible="slider2.decorationVisible"
30 @change="handleRangeChange"
31 ></slider-range>
32 </view>
33 </view>
34 </template>
35
36 <script>
37 import SliderRange from '../../components/slider-range/index.vue'
38 export default {
39 components: {
40 SliderRange,
41 },
42 data() {
43 return {
44 barHeight: 3,
45 blockSize: 26,
46 backgroundColor: '#EEEEF6',
47 slider1: {
48 min: 50,
49 max: 200,
50 step: 10,
51 rangeValue: [50, 150],
52 },
53 slider2: {
54 rangeMin: 0,
55 rangMax: 100,
56 rangeValue: [8, 80],
57 step: 1,
58 activeColor: '#FF6B00',
59 decorationVisible: true,
60 },
61 }
62 },
63 methods: {
64 format1(val) {
65 return val
66 },
67 format2(val) {
68 return `${val}%`
69 },
70 handleRangeChange(e) {
71 this.rangeValue = e
72 },
73 },
74 }
75 </script>
76 <style>
77 .demo-slider-range {
78 background-color: #fff;
79 padding: 100rpx 40rpx 0;
80 }
81
82 .section-title {
83 padding: 0 0 20rpx;
84 color: #666;
85 }
86
87 .slider-item:not(:last-child) {
88 margin-bottom: 100rpx;
89 }
90 </style>
1 <template>
2 <view class="box">
3 <view class="box1">
4 <view class="title">
5 <view class="title-left">{{ porps.title }}</view>
6 <view class="title-icon" @click="changFN">
7 <uni-icons type="top" color="#95a1a6" v-if="show"></uni-icons>
8 <uni-icons type="bottom" color="#95a1a6" v-else></uni-icons>
9 </view>
10 </view>
11 <view class="conter-liner-cost">
12 <view class="liner-left">{{ porps.text }}&nbsp;&nbsp; 合计:</view>
13 <view class="liner-right">{{ porps.cost }}</view>
14 </view>
15 </view>
16 <view class="box2" v-show="show"><slot></slot></view>
17 </view>
18 </template>
19
20 <script setup>
21 import { ref } from 'vue';
22 const porps = defineProps({
23 title: String,
24 text: String,
25 cost: String
26 });
27 const show = ref(false);
28
29 function changFN() {
30 show.value = !show.value;
31 }
32 </script>
33
34 <style lang="scss" scoped>
35 .box {
36 margin: 0;
37 padding: 0 25rpx;
38 .box1 {
39 margin-bottom: 23rpx;
40 margin-top: 35rpx;
41 .title {
42 display: flex;
43 justify-content: space-between;
44 margin-bottom: 10rpx;
45
46 .title-left {
47 font-size: 30rpx;
48 font-family: PingFang SC;
49 font-weight: 500;
50 color: #2b3133;
51 }
52 }
53 .conter-liner-cost {
54 display: flex;
55 .liner-left {
56 font-size: 28rpx;
57 font-family: PingFang SC;
58 font-weight: 400;
59 color: #7b7f83;
60 }
61 .liner-right {
62 font-size: 28rpx;
63 font-family: PingFang SC;
64 font-weight: 400;
65 color: #ff8124;
66 }
67 }
68 }
69 .box2 {
70 border-top: 1rpx solid #e6e6e6;
71 }
72 }
73 </style>
1 <template>
2 <view class="box">
3 <view class="box-title">
4 <view class="title-left">是否住宿</view>
5 <view class="title-right ">
6 <radio-group name="radio" @change="radio">
7 <label>
8 <radio value="1" :checked="flag" />
9 <text></text>
10 </label>
11 <label>
12 <radio value="0" :checked="!flag" />
13 <text></text>
14 </label>
15 </radio-group>
16 </view>
17 </view>
18
19 <!-- 酒店信息 -->
20 <view class="box-conter" v-if="flag">
21 <checkbox-group @change="change">
22 <view class="conter-conter" v-for="item in range" :key="item.id">
23 <view class="bgcColor">
24 <view class="conter-top">
25 <view class="text">{{ item.name }}</view>
26 <checkbox :value="item.hotelFlag" @click="checkedFN(item)" :disabled="disabled" />
27 </view>
28 <view class="box-dress">
29 <uni-icons custom-prefix="iconfont" type="icon-31dingwei" color="#95A1A6"></uni-icons>
30 {{ item.address }}
31 </view>
32 <view class="conter-text">
33 <view class="conter-liner">
34 <view class="liner-left">房型:</view>
35 <view class="liner-right">{{ item.houseType }}</view>
36 </view>
37
38 <view class="conter-liner">
39 <view class="liner-left">价格:</view>
40 <view class="liner-right">{{ item.spend }}</view>
41 </view>
42
43 <view class="conter-liner">
44 <view class="liner-left">餐食:</view>
45 <view class="liner-right">{{ item.haveDinner == 1 ? '含早' : '不含早参' }}</view>
46 </view>
47
48 <view class="conter-liner">
49 <view class="liner-left">入住时间:</view>
50 <view class="liner-right liner-move">
51 <view class="liner-right-hotl" v-for="val in item.move" :key="val.id">
52 <uni-datetime-picker
53 :start="val.moveIntoTime"
54 :end="val.leaveTime"
55 type="daterange"
56 v-model="val.move"
57 return-type="yyyy/MM/dd"
58 @change="maskClick(val)"
59 />
60 <uni-icons
61 class="liner-del"
62 @click="delHot(item, val)"
63 v-if="item.move.length > 1"
64 custom-prefix="custom-icon"
65 type="trash"
66 size="20"
67 />
68 </view>
69 <uni-icons
70 @click="addHot(item)"
71 custom-prefix="custom-icon"
72 type="plusempty"
73 size="20"
74 />
75 </view>
76 </view>
77 </view>
78 </view>
79 </view>
80 </checkbox-group>
81 <view class="remark" v-if="hotelList">
82 <view class="liner-left">备注:</view>
83 <input class="uni-input" v-model="remark" placeholder="请输入你的内容" />
84 </view>
85 </view>
86 <view class="foot ">
87 <view class="button1" @click="upFN">上一步</view>
88 <view class="button" @click="nextFN">下一步</view>
89 </view>
90 </view>
91 </template>
92
93 <script setup>
94 import * as train from '@/common/train.js';
95 import {
96 onLoad,
97 onReady,
98 onShareAppMessage,
99 onShareTimeline,
100 onPullDownRefresh,
101 onReachBottom,
102 onShow
103 } from '@dcloudio/uni-app';
104 import { ref, getCurrentInstance, reactive, watch, toRefs } from 'vue';
105
106 const emit = defineEmits(['nextFN']);
107 const props = defineProps({
108 projectIdsArray: {},
109 id: {},
110 signId: {},
111 examIdsArry: {}
112 });
113 const moveList = ref([
114 {
115 id: 1,
116 move: null
117 }
118 ]);
119 const hotShow = ref(true);
120 const popup = ref();
121 const hotlList = ref();
122 const omve = ref();
123 const arr = ref([]);
124 const range = ref();
125 const id = ref(props.id);
126 const hotelIdsArray = ref();
127 const state = ref(); //是否住宿
128 const remark = ref();
129 const flag = ref(true);
130 const disabled = ref(false);
131 const costID = ref();
132 const code = ref();
133 const status = ref();
134 const signId = ref();
135 const data = reactive({
136 addForm: {}
137 });
138 const { addForm } = toRefs(data);
139
140 onShow(() => {
141 status.value = 3;
142 });
143 getList();
144 async function getList() {
145 addForm.value.id = id.value;
146 let res = await train.trainParticulars(addForm.value);
147 status.value = res.data.signStatus;
148 range.value = res.data.hotelList;
149 range.value.forEach(item => {
150 let tId = uuid();
151 item.move = [
152 {
153 moveIntoTime: item.moveIntoTime.replace(/-/g, '/'),
154 leaveTime: item.leaveTime.replace(/-/g, '/'),
155 id: tId,
156 hotlId: item.id,
157 move: [item.moveIntoTime.replace(/-/g, '/'), item.leaveTime.replace(/-/g, '/')]
158 }
159 ];
160 });
161 // 数据加工
162
163 if (res.data.signId) signId.value = res.data.signId;
164 console.log(range.value);
165 }
166
167 function uuid() {
168 var s = [];
169 var hexDigits = '0123456789abcdef';
170 for (var i = 0; i < 36; i++) {
171 s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
172 }
173 s[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010
174 s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
175 s[8] = s[13] = s[18] = s[23] = '-';
176 var uuid = s.join('');
177 return uuid;
178 }
179
180 // 是否住宿
181 function changeRadio(e) {
182 console.log(e);
183 if (e.target.value == 0) {
184 hotShow.value = false;
185 } else {
186 hotShow.value = true;
187 }
188 }
189
190 // 获取用酒店信息
191 function change(e) {
192 hotelIdsArray.value = e.target;
193 }
194
195 // 封装数据处理
196 function changeKey(arr) {
197 let newArr = [];
198 arr.forEach(item => {
199 newArr.push({
200 text: item.moveIntoTimeStr,
201 value: item.id
202 });
203 });
204 return newArr;
205 }
206
207 // 下一步
208 async function nextFN() {
209 await initData();
210 }
211
212 // 上一步
213 function upFN() {
214 console.log(111);
215 emit('nextFN', 1);
216 }
217
218 // 是否住宿
219 function radio(e) {
220 console.log(e);
221 e.target.value == 1 ? (flag.value = true) : (flag.value = false);
222 console.log(flag.value);
223 }
224
225 // 页面跳转
226 async function goRenew() {
227 let path = `/pages/train/costBreakdown/costBreakdown?id=` + id.value;
228 await wx.navigateTo({
229 url: path
230 });
231 }
232
233 function checkedFN(item) {
234 item.hotelFlag = !item.hotelFlag;
235 }
236
237 // 日期确定时处发
238 // function maskClick(item) {
239 // item.move.forEach(val => {
240 // val = val.replace(/-/g, '/');
241 // });
242 // console.log(item.move);
243 // console.log(item);
244 // }
245
246 // 添加住宿
247 function addHot(item) {
248 let tId = uuid;
249 item.move.push({
250 moveIntoTime: item.moveIntoTime.replace(/-/g, '/'),
251 leaveTime: item.leaveTime.replace(/-/g, '/'),
252 id: tId,
253 move: [item.moveIntoTime.replace(/-/g, '/'), item.leaveTime.replace(/-/g, '/')],
254 hotlId: item.id
255 });
256 }
257
258 function delHot(item, val) {
259 item.move = item.move.filter(obj => {
260 return obj.id != val.id;
261 });
262 }
263
264 // 提交
265 async function initData() {
266 let list = null;
267 list = JSON.parse(JSON.stringify(range.value));
268 // 1.过滤没有选中的酒店
269 list = list.filter(item => {
270 return item.hotelFlag == true;
271 });
272 // 2.过滤没有选择日期的
273 let arr = [];
274 list.forEach((item, index) => {
275 arr[index] = item;
276 arr[index].move = item.move.filter(val => {
277 return val.move.length != 0;
278 });
279 });
280
281 // 3.过滤酒店日期相同
282 let arr1 = [];
283 arr.forEach((item, index) => {
284 item.move.forEach(val => {
285 arr1.push(val);
286 });
287 });
288 let arr2 = [];
289 arr1.forEach(item => {
290 item.move = item.move.join();
291 arr2.push({
292 hotlId: item.hotlId,
293 move: item.move
294 });
295 });
296 // // 去重
297 // for (var i = 0; i < arr2.length - 1; i++) {
298 // for (var j = i + 1; j < arr2.length; j++) {
299 // if (arr2[i].move == arr2[j].move) {
300 // arr2.splice(j, 1);
301 // j--;
302 // }
303 // }
304 // }
305
306 if (flag.value) {
307 if (arr2.length == 0) {
308 uni.showToast({
309 title: '请选择入住酒店!',
310 duration: 2000,
311 icon: 'error'
312 });
313 return false;
314 }
315 addForm.value.hotelIdsArray = arr2;
316 } else {
317 addForm.value.hotelIdsArray = [];
318 }
319 addForm.value.projectIdsArray = props.projectIdsArray;
320 addForm.value.examIdsArray = props.examIdsArry;
321 addForm.value.trainId = id.value;
322 addForm.value.remark = remark.value;
323 let res = null;
324 // if (status.value == null || status.value == 4) {
325 // 添加
326 // addForm.value.id = null
327 addForm.value.id = signId.value;
328 res = await train.trainNext(addForm.value);
329 signId.value = res.data;
330 // } else {
331 // // 修改
332 // addForm.value.id = signId.value
333 // res = await train.trainUpdata(addForm.value);
334 // }
335 costID.value = res.data;
336 // 报名成功才跳转
337 if (res.code == 200) {
338 // 酒店是否已住满
339
340 goRenew();
341 }
342 }
343 </script>
344
345 <style scoped lang="scss">
346 .box {
347 margin-top: 5rpx;
348 padding: 25rpx;
349
350 .bgcColor {
351 background-color: #fff;
352 border-radius: 15rpx;
353 padding: 25rpx;
354 }
355
356 .box-title {
357 padding: 25rpx;
358 display: flex;
359 justify-content: space-between;
360 margin-bottom: 30rpx;
361 background-color: #fff;
362 border-radius: 15rpx;
363 }
364
365 .title-left {
366 text {
367 font-size: 30rpx;
368 font-family: PingFang SC;
369 font-weight: 400;
370 color: #000000;
371 }
372 }
373
374 .box-conter {
375 padding: 25rpx 0;
376 display: block;
377
378 .conter-conter {
379 margin-bottom: 20rpx;
380
381 .conter-top {
382 display: flex;
383 justify-content: space-between;
384 margin-bottom: 10rpx;
385
386 .text {
387 font-size: 33rpx;
388 font-family: PingFang SC;
389 font-weight: 500;
390 color: #2b3133;
391 }
392
393 .checkbox {
394 }
395 }
396
397 .box-dress {
398 font-family: PingFang SC;
399 font-weight: 400;
400 color: #2b3133;
401 font-size: 24rpx;
402 border-bottom: 1px solid #e6e6e6;
403 padding-bottom: 32rpx;
404 }
405
406 .conter-text {
407 .conter-liner {
408 display: flex;
409 justify-content: space-between;
410 margin-top: 20rpx;
411 padding: 0 10rpx;
412
413 .liner-left {
414 font-size: 28rpx;
415 font-family: PingFang SC;
416 font-weight: 400;
417 color: #7b7f83;
418 padding-top: 10rpx;
419 }
420
421 .liner-right {
422 font-size: 28rpx;
423 font-family: PingFang SC;
424 font-weight: 400;
425 color: #2b3133;
426 width: 80%;
427 text-align: right;
428 }
429 }
430 }
431 }
432 }
433
434 .remark {
435 margin-top: 35rpx;
436 display: flex;
437 justify-content: space-between;
438 margin-bottom: 120rpx;
439 background-color: #fff;
440 border-radius: 15rpx;
441 padding: 10rpx 25rpx;
442
443 .liner-left {
444 font-size: 28rpx;
445 font-family: PingFang SC;
446 font-weight: 400;
447 color: #7b7f83;
448 padding-top: 18rpx;
449 }
450 }
451
452 .foot {
453 background-color: #ffffff;
454 padding: 20rpx 0;
455 position: absolute;
456 left: 0;
457 bottom: 0;
458 width: 100%;
459 display: flex;
460
461 .button {
462 margin: 0 auto;
463 height: 80rpx;
464 width: 300rpx;
465 text-align: center;
466 font-size: 32rpx;
467 font-family: PingFang SC;
468 font-weight: 500;
469 color: #ffffff;
470 line-height: 80rpx;
471 background: linear-gradient(270deg, #54e1b9, #00caa6);
472 border-radius: 40rpx;
473 }
474
475 .button1 {
476 margin: 0 auto;
477 height: 80rpx;
478 width: 300rpx;
479 text-align: center;
480 font-size: 32rpx;
481 font-family: PingFang SC;
482 font-weight: 500;
483 line-height: 80rpx;
484 background: #fff;
485 border-radius: 40rpx;
486 border: 1px solid #2ed981;
487 color: #2ed981;
488 }
489 }
490
491 .select {
492 width: 300rpx;
493 }
494 }
495
496 .uni-date {
497 flex: 0;
498 width: 65%;
499 }
500
501 .popup-center {
502 display: flex;
503 justify-content: space-between;
504 }
505
506 .popup-title {
507 display: flex;
508 justify-content: space-between;
509 border-bottom: 1px solid #e6e6e6;
510 padding: 30rpx 50rpx;
511 }
512
513 .popup-title-left {
514 font-size: 30rpx;
515 font-weight: 400;
516 color: 000;
517 font-family: PingFangSC-Medium;
518 }
519
520 .popup-body {
521 border-bottom: 1px solid #e6e6e6;
522 padding: 15rpx 50rpx;
523 color: #4c5359;
524 font-size: 30rpx;
525 }
526
527 .popup-box {
528 height: 500rpx;
529 overflow-y: scroll;
530 }
531
532 .liner-right-hotl {
533 display: flex;
534 }
535
536 .liner-del {
537 margin-top: 19rpx;
538 }
539 </style>
1 <template>
2 <view class=" conter-box">
3 <view class="box" v-if="props.trainProjectsList.length != 0">
4 <view class="text">培训科目</view>
5 <view class="box2">
6 <checkbox-group>
7 <view class="box-check" v-for="item in props.trainProjectsList" :key="item.id">
8 <view class="">
9 <view class="title">{{ item.projectName }}</view>
10 <view class="content">
11 {{ item.isNecessary == 1 ? '必选' : '非必选' }}&nbsp;&nbsp;合计:
12 <view class="span">{{ item.cost }}</view>
13 </view>
14 </view>
15 <view class="checkbox">
16 <checkbox
17 :disabled="item.isNecessary == 1"
18 :value="item.id"
19 @click="checkTrain(item)"
20 :checked="item.check"
21 />
22 </view>
23 </view>
24 </checkbox-group>
25 </view>
26 </view>
27 <view class="box" v-if="props.examProjectsList.length != 0">
28 <view class="text">考试科目</view>
29 <view class="box2">
30 <checkbox-group>
31 <view class="box-check" v-for="item in props.examProjectsList" :key="item.id">
32 <view class="">
33 <view class="title">{{ item.projectName }}</view>
34 <view class="content">
35 {{ item.isNecessary == 1 ? '必选' : '非必选' }}&nbsp;&nbsp;合计:
36 <view class="span">{{ item.cost }}</view>
37 </view>
38 </view>
39 <view class="checkbox">
40 <checkbox
41 :disabled="item.isNecessary == 1"
42 :value="item.id"
43 @click="checkTrain(item)"
44 :checked="item.check"
45 />
46 </view>
47 </view>
48 </checkbox-group>
49 </view>
50 </view>
51 </view>
52 <view class="foot">
53 <view class="button1" @click="upFN">上一步</view>
54 <view class="button" @click="nextFN">下一步</view>
55 </view>
56 <view class="nodata " v-if="props.examProjectsList.length == 0 && props.trainProjectsList.length == 0">
57 没有培训科目
58 </view>
59 </template>
60
61 <script setup>
62 import { forEach } from 'lodash';
63 import { ref, getCurrentInstance, reactive, toRefs } from 'vue';
64 const props = defineProps({
65 trainProjectsList: {},
66 examProjectsList: {},
67 hotelList: {},
68 id: {}
69 });
70 const data = reactive({
71 projectIdsArray: []
72 });
73
74 const examIdsArry = ref([]);
75 const { projectIdsArray } = toRefs(data);
76 const emit = defineEmits(['nextFN']);
77 const checkbox1 = ref([0]);
78
79 function checkTrain(item) {
80 if (item.isNecessary == 1) {
81 item.check = true;
82 } else {
83 item.check = !item.check;
84 }
85 }
86
87 // 上一步
88 function upFN() {
89 emit('nextFN', 0);
90 }
91
92 // 下一步
93 function nextFN() {
94 let falg = true;
95 let arr1 = [];
96 let arr2 = [];
97 props.examProjectsList.forEach(item => {
98 if (item.check) {
99 arr1.push(item.id);
100 }
101 });
102 props.trainProjectsList.forEach(item => {
103 if (item.check) {
104 arr2.push(item.id);
105 }
106 });
107 let examList = JSON.parse(JSON.stringify(props.examProjectsList));
108 let trainList = JSON.parse(JSON.stringify(props.trainProjectsList));
109 examList.concat(trainList).forEach(item => {
110 if (item.isNecessary == 1 && item.check == false) {
111 falg = false;
112 }
113 });
114
115 if (falg) {
116 examIdsArry.value = arr1;
117 projectIdsArray.value = arr2;
118 if (props.hotelList.length == 0) {
119 // 没有酒店直接报名
120 // 页面跳转
121 let path = `/pages/train/costBreakdown/costBreakdown?id=` + props.id;
122 wx.navigateTo({
123 url: path
124 });
125 } else {
126 emit('nextFN', 2, projectIdsArray.value, examIdsArry.value);
127 }
128 } else {
129 uni.showToast({
130 title: '请选择必选科目!',
131 duration: 2000,
132 icon: 'error'
133 });
134 return false;
135 }
136 }
137 </script>
138
139 <style scoped lang="scss">
140 .nodata {
141 background: url(/static/nodata.png) no-repeat;
142 background-size: 100%;
143 width: 100%;
144 height: 835rpx;
145 color: #aaa59f;
146 font-size: 50rpx;
147 }
148
149 .conter-box {
150 padding-bottom: 100rpx;
151 }
152
153 .box {
154 padding: 34rpx 25rpx;
155 background-color: #f4f6fa;
156 padding-bottom: 0;
157
158 .box2 {
159 background-color: #fff;
160 border-radius: 15rpx;
161 margin-top: 20rpx;
162 }
163
164 .text {
165 height: 29px;
166 font-size: 30rpx;
167 font-family: PingFang SC;
168 font-weight: 500;
169 color: #000000;
170 line-height: 62rpx;
171 }
172
173 .box-check {
174 padding: 40rpx;
175 display: flex;
176 justify-content: space-between;
177 border-bottom: 1rpx solid #e6e6e6;
178 padding-bottom: 20rpx;
179
180 :deep(.checkbox__inner) {
181 background-color: #d9d9d9 !important;
182 border-color: #d9d9d9 !important;
183 border-radius: 50% !important;
184 width: 45rpx !important;
185 height: 45rpx !important;
186 line-height: 40rpx;
187 }
188
189 .text {
190 font-size: 12px;
191 color: #666;
192 margin-top: 5px;
193 }
194
195 .title {
196 font-size: 30rpx;
197 font-family: PingFang SC;
198 font-weight: 400;
199 color: #2b3133;
200 margin-bottom: 10rpx;
201 }
202
203 .content {
204 display: flex;
205 font-size: 30rpx;
206 font-family: PingFang SC;
207 font-weight: 400;
208 color: #2b3133;
209
210 .span {
211 color: #ff8124;
212 font-size: 28rpx;
213 font-family: PingFang SC;
214 font-weight: 400;
215 }
216 }
217 }
218
219 :deep(.checkbox__inner-icon) {
220 position: absolute !important;
221 top: 4px !important;
222 left: 7px !important;
223 color: #000 !important;
224 }
225
226 :deep(.uni-data-checklist .checklist-group .checklist-box) {
227 margin-right: 0;
228 }
229 }
230
231 .conter-button {
232 position: absolute;
233 left: 0;
234 bottom: 10rpx;
235 width: 100%;
236 display: flex;
237 justify-content: center;
238
239 .button {
240 height: 80rpx;
241 width: 500rpx;
242 text-align: center;
243 font-size: 32rpx;
244 font-family: PingFang SC;
245 font-weight: 500;
246 color: #ffffff;
247 line-height: 80rpx;
248 background: linear-gradient(270deg, #54e1b9, #00caa6);
249 border-radius: 40rpx;
250 }
251 }
252
253 .foot {
254 display: flex;
255 background-color: #ffffff;
256 padding: 20rpx 0;
257 position: absolute;
258 left: 0;
259 bottom: 0;
260 width: 100%;
261
262 .button {
263 margin: 0 auto;
264 height: 80rpx;
265 width: 300rpx;
266 text-align: center;
267 font-size: 32rpx;
268 font-family: PingFang SC;
269 font-weight: 500;
270 color: #ffffff;
271 line-height: 80rpx;
272 background: linear-gradient(270deg, #54e1b9, #00caa6);
273 border-radius: 40rpx;
274 }
275
276 .button1 {
277 margin: 0 auto;
278 height: 80rpx;
279 width: 300rpx;
280 text-align: center;
281 font-size: 32rpx;
282 font-family: PingFang SC;
283 font-weight: 500;
284 line-height: 80rpx;
285 background: #fff;
286 border-radius: 40rpx;
287 border: 1px solid #2ed981;
288 color: #2ed981;
289 }
290 }
291 </style>
1 <template>
2 <view class="box">
3 <view class="liner" v-for="item in props.scheduleList" :key="item.id">
4 <view class="timer">
5 <uni-icons custom-prefix="iconfont" type="icon-ai253" color="#1ec886" size="20"></uni-icons>
6 &nbsp; {{ item.dayStr }} 10:00-12:00
7 </view>
8 <view class="conetr">{{ item.event }}</view>
9 <view class="data">
10 <uni-icons custom-prefix="iconfont" type="icon-loufangfangzi"></uni-icons>
11 {{ item.place }}
12 </view>
13 </view>
14 <view class="nodata" v-if="props?.scheduleList?.length == 0">你还没有日程安排</view>
15 </view>
16 </template>
17
18 <script setup>
19 import { ref, getCurrentInstance, reactive, toRefs } from 'vue';
20 const props = defineProps({
21 scheduleList: {}
22 });
23 </script>
24
25 <style scoped lang="scss">
26 .nodata {
27 background: url(/static/nodata.png) no-repeat;
28 background-size: 100%;
29 width: 100%;
30 height: 835rpx;
31 color: #aaa59f;
32 font-size: 50rpx;
33 }
34
35 .box {
36 padding-top: 25rpx;
37
38 .liner {
39 margin-bottom: 20rpx;
40 background-color: #fff;
41 border-radius: 15rpx;
42 padding: 20rpx;
43 }
44
45 .timer {
46 display: flex;
47 font-size: 28rpx;
48 font-family: PingFang SC;
49 font-weight: 400;
50 color: #1ec886;
51 }
52
53 .conetr {
54 font-size: 30rpx;
55 font-family: PingFang SC;
56 font-weight: 400;
57 color: #2b3133;
58 margin: 25rpx 0;
59 }
60
61 .data {
62 font-size: 28rpx;
63 font-family: PingFang SC;
64 font-weight: 400;
65 color: #7b7f83;
66 }
67 }
68 </style>
1 <template>
2 <view class="big-box">
3 <view class="list-box">
4 <view class="image">
5 <image class="img" referrer="no-referrer|origin|unsafe-url" :src="porps.pic" mode="aspectFill"></image>
6 </view>
7 <view class="text">
8 <view class="text-title">{{ porps.title }}</view>
9 <view class="text-card color" v-if="porps.card == '报名中'">{{ porps.card }}</view>
10 <view class="text-card color1" v-if="porps.card == '进行中'">{{ porps.card }}</view>
11 <view class="text-card color2" v-if="porps.card == '即将开始'">{{ porps.card }}</view>
12 <view class="text-card color3" v-if="porps.card == '已结束'">{{ porps.card }}</view>
13 <view class="text-card color4" v-if="porps.card == '培训未开始'">{{ porps.card }}</view>
14 <view class="text-card color4" v-if="porps.card == '报名未开始'">{{ porps.card }}</view>
15 <view class="text-timer ">报名截止:{{ porps.timer }}</view>
16 </view>
17 </view>
18 <view class="hr"></view>
19 </view>
20 </template>
21
22 <script setup>
23 const porps = defineProps({
24 pic: {
25 type: String
26 },
27 title: {
28 type: String
29 },
30 card: {
31 type: String
32 },
33 timer: {
34 type: String
35 }
36 });
37 </script>
38
39 <style lang="scss">
40 .big-box {
41 width: 100%;
42 padding: 25rpx 0;
43
44 .hr {
45 width: 100%;
46 border-bottom: 1rpx solid #e5e5e5;
47 padding-top: 25rpx;
48 }
49
50 .list-box {
51 width: 100%;
52 height: 180rpx;
53 display: flex;
54
55 .image {
56 width: 270rpx;
57 height: 180rpx;
58 padding-right: 25rpx;
59
60 .img {
61 width: 270rpx;
62 height: 180rpx;
63 border-radius: 15rpx;
64 }
65 }
66
67 .text {
68 margin-left: 20rpx;
69
70 .text-title {
71 text-align: left;
72 font-size: 30rpx;
73 font-family: PingFang SC;
74 font-weight: 400;
75 color: #000000;
76 }
77
78 .text-card {
79 font-size: 20rpx;
80 width: 110rpx;
81 height: 32rpx;
82 margin-top: 57rpx;
83 text-align: center;
84 font-family: PingFang SC;
85 font-weight: 400;
86 color: #ffffff;
87 border-radius: 16px 16px 16px 0px;
88 }
89
90 .color {
91 background: linear-gradient(270deg, #54e1b9, #00caa6);
92 }
93
94 .color1 {
95 background: linear-gradient(270deg, #be8efb, #a76df4);
96 }
97
98 .color2 {
99 background: linear-gradient(270deg, #fea449, #ffb95f);
100 }
101
102 .color3 {
103 background: linear-gradient(270deg, #d9d9d9, #bcbcbc);
104 }
105
106 .color4 {
107 background: linear-gradient(270deg, #40d8ee, #53a7f6);
108 }
109
110 .text-timer {
111 margin-top: 20rpx;
112 height: 23rpx;
113 font-size: 24rpx;
114 font-family: PingFang SC;
115 font-weight: 400;
116 color: #7b7f83;
117 }
118 }
119 }
120 }
121 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="big-box">
3 <view class="list-box">
4 <view class="image">
5 <image
6 class="img"
7 referrer="no-referrer|origin|unsafe-url"
8 :src="porps.item.cover"
9 mode="aspectFill"
10 ></image>
11 </view>
12 <view class="text">
13 <view class="text-title">{{ porps.item.trainName }}</view>
14 <view class="text-card color1" v-if="porps.item.statusStr == '审核通过'">
15 {{ porps.item.statusStr }}
16 </view>
17 <view class="text-card color2" v-if="porps.item.statusStr == '待审核'">
18 {{
19 porps.item.status == '0' && porps.item.payStatus == '0'
20 ? porps.item.payStatusStr
21 : porps.item.statusStr
22 }}
23 </view>
24 <view class="text-card color3" v-if="porps.item.statusStr == '报名失败'">
25 {{ porps.item.statusStr }}
26 </view>
27 <view class="text-card color3" v-if="porps.item.statusStr == '审核拒绝'">
28 {{ porps.item.statusStr }}
29 </view>
30 <view class="text-card color4" v-if="porps.item.statusStr == '待支付'">{{ porps.item.statusStr }}</view>
31 <view class="text-card color4" v-if="porps.item.statusStr == '待提交'">{{ porps.item.statusStr }}</view>
32 <view class="text-card color5" v-if="porps.item.statusStr == '已取消'">{{ porps.item.statusStr }}</view>
33 </view>
34 </view>
35 <view class="hr"></view>
36 </view>
37 </template>
38
39 <script setup>
40 const porps = defineProps({
41 pic: {
42 type: String
43 },
44 title: {
45 type: String
46 },
47 card: {
48 type: String
49 },
50 timer: {
51 type: String
52 },
53 item: {}
54 });
55 </script>
56
57 <style lang="scss">
58 .big-box {
59 width: 100%;
60 padding: 25rpx 0;
61
62 .hr {
63 width: 100%;
64 border-bottom: 1rpx solid #e5e5e5;
65 padding-top: 25rpx;
66 }
67
68 .list-box {
69 width: 100%;
70 height: 180rpx;
71 display: flex;
72
73 .image {
74 width: 270rpx;
75 height: 180rpx;
76 padding-right: 25rpx;
77
78 .img {
79 width: 270rpx;
80 height: 180rpx;
81 border-radius: 15rpx;
82 }
83 }
84
85 .text {
86 margin-left: 20rpx;
87
88 .text-title {
89 text-align: left;
90 font-size: 30rpx;
91 font-family: PingFang SC;
92 font-weight: 400;
93 color: #000000;
94 }
95
96 .text-card {
97 font-size: 20rpx;
98 width: 94rpx;
99 height: 32rpx;
100 margin-top: 57rpx;
101 text-align: center;
102 font-family: PingFang SC;
103 font-weight: 400;
104 color: #ffffff;
105 border-radius: 16px 16px 16px 0px;
106 }
107
108 .color1 {
109 background: linear-gradient(270deg, #54e1b9, #00caa6);
110 }
111
112 .color2 {
113 background: linear-gradient(270deg, #be8efb, #a76df4);
114 }
115
116 .color3 {
117 background: linear-gradient(90deg, #f83841, #f76d74);
118 }
119
120 .color4 {
121 background: linear-gradient(90deg, #fea449, #ffb95f);
122 }
123
124 .color5 {
125 background: linear-gradient(270deg, #d9d9d9, #bcbcbc);
126 }
127 }
128 }
129 }
130 </style>
...@@ -181,6 +181,20 @@ ...@@ -181,6 +181,20 @@
181 } 181 }
182 182
183 }, { 183 }, {
184 "path": "pages/level/ztx/approval",
185 "style": {
186 "navigationBarTitleText": "级位考试审批",
187 "enablePullDownRefresh": false
188 }
189
190 }, {
191 "path": "pages/level/ztx/cert",
192 "style": {
193 "navigationBarTitleText": "级位证书发布",
194 "enablePullDownRefresh": false
195 }
196
197 }, {
184 "path": "pages/rank/approval", 198 "path": "pages/rank/approval",
185 "style": { 199 "style": {
186 "navigationBarTitleText": "段位考试审批", 200 "navigationBarTitleText": "段位考试审批",
...@@ -422,6 +436,24 @@ ...@@ -422,6 +436,24 @@
422 "enablePullDownRefresh": false 436 "enablePullDownRefresh": false
423 } 437 }
424 } 438 }
439 ,{
440 "path" : "pages/level/ztx/examList",
441 "style" :
442 {
443 "navigationBarTitleText": "级位考试详情",
444 "enablePullDownRefresh": false
445 }
446
447 }
448 ,{
449 "path" : "pages/level/ztx/studentList",
450 "style" :
451 {
452 "navigationBarTitleText": "考生列表",
453 "enablePullDownRefresh": false
454 }
455
456 }
425 ], 457 ],
426 "globalStyle": { 458 "globalStyle": {
427 "navigationStyle": "custom", 459 "navigationStyle": "custom",
......
...@@ -4,6 +4,12 @@ ...@@ -4,6 +4,12 @@
4 <uni-segmented-control class="whitebg" :current="current" :values="navs" @clickItem="onClickItem" 4 <uni-segmented-control class="whitebg" :current="current" :values="navs" @clickItem="onClickItem"
5 styleType="text" activeColor="#AD181F"></uni-segmented-control> 5 styleType="text" activeColor="#AD181F"></uni-segmented-control>
6 <view class="appList"> 6 <view class="appList">
7 <view class="vipData" v-if="userType == '1'" v-show="totalCost>0">
8 <view>费用合计:
9 <text>¥{{ totalCost.toFixed(2) }}</text>
10 </view>
11 </view>
12
7 <view class="appItem" v-for="item in list"> 13 <view class="appItem" v-for="item in list">
8 <view class="status" @click="goDetail(item)"> 14 <view class="status" @click="goDetail(item)">
9 <text v-if="item.auditStatus == 0" class="text-primary">审核中</text> 15 <text v-if="item.auditStatus == 0" class="text-primary">审核中</text>
...@@ -36,25 +42,22 @@ ...@@ -36,25 +42,22 @@
36 <view>{{item.content.renewYear}}</view> 42 <view>{{item.content.renewYear}}</view>
37 </view> 43 </view>
38 <view v-if="deptType == 1"> 44 <view v-if="deptType == 1">
39 团体会员/新会员 45 会员合计/新会员
40 <view>{{item.content.allCount}}/{{item.content.newCount}}</view> 46 <view>{{item.content.allCount}}/<text class="text-danger">{{item.content.newCount}}</text></view>
41 </view> 47 </view>
42 <view v-if="deptType == 1"> 48 <view v-if="deptType == 1">
43 费用合计 49 费用合计
44 <view> {{ (item?.content?.allFee*1).toFixed(2) }}</view> 50 <view> ¥{{ (item?.content?.allFee*1).toFixed(2) }}</view>
45 </view> 51 </view>
46 </view> 52 </view>
47 <view class="func" v-if="(userType == '3'||userType == '2') && item.auditStatus == 0"> 53 <view class="func" v-if="(userType == '3'||userType == '2') && item.auditStatus == 0">
48 <button @click="audit(item.recordId,'0')">拒绝</button> 54 <button @click="audit(item.recordId,'0')">拒绝</button>
49 <button @click="audit(item.recordId,'1')">同意</button> 55 <button @click="audit(item.recordId,'1')">同意</button>
50 </view> 56 </view>
51 <view class="func" v-if="(deptType == 1&&item.ztxRes == 0)||((deptType == 2 || deptType == 3)&&item.shenRes == 0)"> 57 <view class="func" v-if="(userType == '1'&&item.auditStatus == 0)">
52 <button @click="audit(item.recordId,'0')">拒绝</button> 58 <button @click="audit(item.recordId,'0')">拒绝</button>
53 <button @click="audit(item.recordId,'1')">同意</button> 59 <button @click="audit(item.recordId,'1')">同意</button>
54 </view> 60 </view>
55 <view class="func" v-if="(deptType == 6&&(item.status == 0 || item.status == 2))">
56 <button>提交审核</button>
57 </view>
58 </view> 61 </view>
59 </view> 62 </view>
60 63
...@@ -90,6 +93,7 @@ ...@@ -90,6 +93,7 @@
90 const total = ref(0) 93 const total = ref(0)
91 const deptType = ref('') 94 const deptType = ref('')
92 const userType = ref('') 95 const userType = ref('')
96 const totalCost = ref(0)
93 onLoad(() => { 97 onLoad(() => {
94 if (app.globalData.isLogin) { 98 if (app.globalData.isLogin) {
95 init() 99 init()
...@@ -126,12 +130,14 @@ ...@@ -126,12 +130,14 @@
126 }else if( deptType.value==4||deptType.value==5){ 130 }else if( deptType.value==4||deptType.value==5){
127 queryParams.value.noEmpty=1 131 queryParams.value.noEmpty=1
128 } 132 }
133 totalCost.value = 0
129 api.getGroupList(queryParams.value).then(res => { 134 api.getGroupList(queryParams.value).then(res => {
130 uni.hideLoading() 135 uni.hideLoading()
131 list.value = res.rows 136 list.value = res.rows
132 list.value.forEach(item => { 137 list.value.forEach(item => {
133 item.content = JSON.parse(item.content) 138 item.content = JSON.parse(item.content)
134 // item.doc = JSON.parse(item.doc) 139 // item.doc = JSON.parse(item.doc)
140 totalCost.value = totalCost.value + (item.content.allFee * 1)
135 }) 141 })
136 total.value = res.total 142 total.value = res.total
137 }) 143 })
...@@ -194,7 +200,7 @@ ...@@ -194,7 +200,7 @@
194 200
195 if(userType.value=='1'){ 201 if(userType.value=='1'){
196 // 查看 202 // 查看
197 let path = `/pages/group/apply/applyDetail?rangeId=${item.id}&auditLog=${auditLog}&form=${form}` 203 let path = `/pages/group/apply/mergeUpDetail?form=${form}`
198 uni.navigateTo({ 204 uni.navigateTo({
199 url: path 205 url: path
200 }); 206 });
......
...@@ -40,21 +40,35 @@ ...@@ -40,21 +40,35 @@
40 </view> 40 </view>
41 <view class="flexbox"> 41 <view class="flexbox">
42 <view> 42 <view>
43 单价 43 <view>
44 <text>¥{{n.unitPrice}}</text> 44 原有效期
45 <text>{{n.validityTime?.slice(0,10)}}</text>
46 </view>
47 <view>
48 提交日期
49 <text>{{n.commitTime?.slice(0,10)}}</text>
50 </view>
45 </view> 51 </view>
46 <view> 52 <view>
47 年限 53 年限
48 <text>{{n.renewYear}}</text> 54 <text>{{n.renewYear}}</text>
55 <view v-if="deptType==1">
56 会员证
57 <text v-if="form.content.sendJiaoFeiFlag==1" class="text-success">已下发</text>
58 <text v-else class="text-warning">未下发</text>
59 </view>
49 </view> 60 </view>
50 <view> 61 <view>
51 总价 62 单价
63 <text>¥{{n.unitPrice}}</text>
64 <view>总价
52 <text>¥{{n.allFee}}</text> 65 <text>¥{{n.allFee}}</text>
53 </view> 66 </view>
54 </view> 67 </view>
55 </view> 68 </view>
56 </view> 69 </view>
57 </view> 70 </view>
71 </view>
58 72
59 </view> 73 </view>
60 74
...@@ -80,15 +94,15 @@ ...@@ -80,15 +94,15 @@
80 </view> 94 </view>
81 </view> 95 </view>
82 96
83 <view class="fixedBottom" v-if="(deptType == 1)&&form.ztxRes == 0"> 97 <!-- <view class="fixedBottom" v-if="(deptType == 1)&&form.auditStatus == 0">
84 <button class="btn-red-kx" @click="audit(form.id,'2')">拒绝</button> 98 <button class="btn-red-kx" @click="audit(form.id,'2')">拒绝</button>
85 <button class="btn-red" @click="audit(form.id,'1')">同意</button> 99 <button class="btn-red" @click="audit(form.id,'1')">同意</button>
86 </view> 100 </view>
87 101
88 <view class="fixedBottom" v-if="(deptType == 2 || deptType == 3)&&form.shenRes == 0"> 102 <view class="fixedBottom" v-if="(deptType == 2 || deptType == 3)&&form.auditStatus == 0">
89 <button class="btn-red-kx" @click="audit(form.id,'2')">拒绝</button> 103 <button class="btn-red-kx" @click="audit(form.id,'2')">拒绝</button>
90 <button class="btn-red" @click="audit(form.id,'1')">同意</button> 104 <button class="btn-red" @click="audit(form.id,'1')">同意</button>
91 </view> 105 </view> -->
92 106
93 </view> 107 </view>
94 </template> 108 </template>
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
15 <view class="item" v-for="n in list"> 15 <view class="item" v-for="n in list">
16 <view class="w100"> 16 <view class="w100">
17 <view class="name">{{n.certName}}</view> 17 <view class="name">{{n.certName}}</view>
18 <view class="date" v-if="n.validityTime">{{n.validityTime?.silce(0,10)}}</view> 18 <view class="date" v-if="n.validityTime">{{n.validityTime?.slice(0,10)}}</view>
19 <view class="flexbox"> 19 <view class="flexbox">
20 <view>单价 20 <view>单价
21 <text>¥{{ (n.unitPrice*1).toFixed(2) }}</text> 21 <text>¥{{ (n.unitPrice*1).toFixed(2) }}</text>
......
1 <template> 1 <template>
2 <view class="page"> 2 <view class="page">
3 <view class="bgbg"> 3 <view class="bgbg">
4 <view class="loginOutIcon" @click="loginOut">
5 <image src="@/static/switch.png"></image>
6 </view>
4 <view class="welcome">您好! 7 <view class="welcome">您好!
5 {{memberInfo.name}} 8 {{memberInfo.name}}
6 <br />欢迎使用中跆协会员管理系统 9 <br />欢迎使用中跆协会员管理系统
...@@ -42,7 +45,7 @@ ...@@ -42,7 +45,7 @@
42 <view v-if="userType=='4'" @click="goPath('/pages/level/apply')"> 45 <view v-if="userType=='4'" @click="goPath('/pages/level/apply')">
43 <image />级位考试申请 46 <image />级位考试申请
44 </view> 47 </view>
45 <view v-if="userType!='4'" @click="goPath('/pages/level/approval')"> 48 <view v-if="userType!='4'&&userType!='1'" @click="goPath('/pages/level/approval')">
46 <image />级位考试审核 49 <image />级位考试审核
47 </view> 50 </view>
48 <view v-if="userType=='2'" @click="goPath('/pages/level/apply')"> 51 <view v-if="userType=='2'" @click="goPath('/pages/level/apply')">
...@@ -52,6 +55,12 @@ ...@@ -52,6 +55,12 @@
52 55
53 </view> 56 </view>
54 <view v-if="userType=='1'" class="girdBox"> 57 <view v-if="userType=='1'" class="girdBox">
58 <view @click="goPath('/pages/level/ztx/approval')">
59 <image />级位考试审核
60 </view>
61 <view @click="goPath('/pages/level/ztx/cert')">
62 <image />级位证书发布
63 </view>
55 <view @click="goPath('/pages/rank/approval')"> 64 <view @click="goPath('/pages/rank/approval')">
56 <image />段位考试审核 65 <image />段位考试审核
57 </view> 66 </view>
...@@ -132,7 +141,9 @@ ...@@ -132,7 +141,9 @@
132 proId = option.proId; 141 proId = option.proId;
133 } 142 }
134 }); 143 });
144 function loginOut(){
135 145
146 }
136 function goPath(path) { 147 function goPath(path) {
137 uni.navigateTo({ 148 uni.navigateTo({
138 url: path 149 url: path
...@@ -282,6 +293,9 @@ ...@@ -282,6 +293,9 @@
282 } 293 }
283 </script> 294 </script>
284 <style scope lang="scss"> 295 <style scope lang="scss">
296 .loginOutIcon{
297 image{}
298 }
285 .welcome { 299 .welcome {
286 padding: 55rpx; 300 padding: 55rpx;
287 line-height: 55rpx; 301 line-height: 55rpx;
......
...@@ -42,6 +42,9 @@ ...@@ -42,6 +42,9 @@
42 <image mode="aspectFit" src="/static/nodata.png"></image> 42 <image mode="aspectFit" src="/static/nodata.png"></image>
43 <text>暂无数据</text> 43 <text>暂无数据</text>
44 </view> 44 </view>
45 <view v-if="userType=='2'" class="block-btn-box">
46 <button @click="goMerge" class="btn-red-kx">前往合并 > </button>
47 </view>
45 </view> 48 </view>
46 </template> 49 </template>
47 50
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
40 40
41 <view class="nodata" v-if="infoList.length==0"> 41 <view class="nodata" v-if="infoList.length==0">
42 <image mode="aspectFit" src="/static/nodata.png"></image> 42 <image mode="aspectFit" src="/static/nodata.png"></image>
43 <text>暂无数据</text> 43 <button class="btn-red" @click="gohome">回到首页</button>
44 </view> 44 </view>
45 </view> 45 </view>
46 </template> 46 </template>
...@@ -161,6 +161,12 @@ ...@@ -161,6 +161,12 @@
161 }); 161 });
162 162
163 } 163 }
164 function gohome(){
165 let path = `/pages/index/index`
166 uni.reLaunch({
167 url: path
168 });
169 }
164 </script> 170 </script>
165 171
166 <style scoped> 172 <style scoped>
......
1 <template>
2 <view>
3 <uni-segmented-control class="whitebg" :current="current" :values="navs" @clickItem="onClickItem"
4 styleType="text" activeColor="#AD181F"></uni-segmented-control>
5 <view v-show="totalCost>0" class="vipData">
6 <view>费用合计:
7 <text>{{ totalCost.toFixed(2) }}</text>
8 </view>
9 </view>
10
11 <view class="appList">
12 <view class="appItem" v-for="item in infoList">
13 <view class="status" :class="{
14 'text-primary':item.status=='0',
15 'text-success':item.status=='1',
16 'text-danger':item.status=='2',
17 'text-warning':item.status=='3'
18 }" @click="goDetail(item)">
19 {{ item.statusStr }}
20 </view>
21
22 <view class="date" v-if="item.status!='0'&&item.submitTime">提交时间:{{item.submitTime}}</view>
23 <view class="name mt0" @click="goDetail(item)">{{item.mergeName}}</view>
24 <view class="pp esp">上报单位:{{item.memName}}</view>
25 <view class="flexbox" @click="goDetail(item)">
26 <view>
27 考试人数
28 <view>{{item.totalNum}}</view>
29 </view>
30
31 <view>
32 缴费状态
33 <view>
34 <text :class="{
35 'text-success':item.examPayStatusStr=='已上传凭证',
36 'text-danger':item.examPayStatusStr=='未上传凭证',
37 'text-warning':item.examPayStatusStr=='已结算'
38 }">{{ item.examPayStatusStr||'--' }}</text>
39 </view>
40 </view>
41 <view>
42 总金额
43 <view>¥{{item.totalAmount}}</view>
44 </view>
45 </view>
46 <view class="func" v-if="item.status=='0'">
47 <button @click="audit(item,'2')">拒绝</button>
48 <button @click="audit(item,'1')">同意</button>
49 </view>
50 </view>
51 </view>
52
53 <view class="nodata" v-if="infoList.length==0">
54 <image mode="aspectFit" src="/static/nodata.png"></image>
55 <text>暂无数据</text>
56 </view>
57 </view>
58 </template>
59
60 <script setup>
61 import * as api from '@/common/api.js'
62 import config from '@/config.js'
63 import _ from 'lodash'
64 import {
65 onMounted,
66 ref
67 } from 'vue'
68 import {
69 onLoad,
70 onShow
71 } from '@dcloudio/uni-app'
72 const app = getApp();
73 const queryParams = ref({
74 // pageNum: 1,
75 // pageSize: 10
76 status: '0',
77 type: '1'
78 })
79 const navs = ref(['审核中', '审核通过', '审核拒绝', '审批撤回'])
80 const statusArr = ['审批中', '审批通过', '审批拒绝', '审批撤回']
81 const current = ref()
82 const infoList = ref([])
83 const total = ref(0)
84 const totalCost = ref(0)
85 const deptType = ref('')
86 const userType = ref('')
87 onLoad(() => {
88
89 })
90 onShow(() => {
91 if (app.globalData.isLogin) {
92 init()
93 } else {
94
95 app.firstLoadCallback = () => {
96 init()
97 };
98 }
99 })
100
101 function init() {
102 deptType.value = app.globalData.deptType
103 userType.value = app.globalData.userType
104 getList()
105 }
106
107
108 function getList() {
109 uni.showLoading({
110 title: '加载中'
111 })
112 totalCost.value = 0
113 api.getVerityMergeList(queryParams.value).then(response => {
114 uni.hideLoading()
115 const list = []
116 _.each(response.rows, r => {
117 const item = JSON.parse(r.remark)
118 item.recordId = r.recordId
119 item.status = r.auditStatus
120 item.statusStr = statusArr[r.auditStatus]
121 item.isView = r.isView
122 item.payStatus = r.payStatus
123 item.examPayStatusStr = r.examPayStatusStr
124 item.sourceData = r
125 item.auditProcess = r.auditProcess
126 list.push(item)
127
128 totalCost.value += (item.totalAmount * 1)
129 })
130 infoList.value = list
131 total.value = response.total
132 })
133 }
134
135 function onClickItem(e) {
136 console.log(e)
137 uni.showLoading({
138 title: '加载中'
139 })
140 queryParams.value.status = e.currentIndex
141 getList()
142 }
143
144 function goDetail(item) {
145 const form = encodeURIComponent(JSON.stringify(item))
146 // 查看
147 let path = `/pages/level/mergeUpDetail?form=${form}&type=1`
148 uni.navigateTo({
149 url: path
150 });
151
152 }
153
154 function audit(item, flag) {
155 var obj = {
156 flag: flag,
157 reason: null,
158 id: item.recordId
159 }
160
161 if (flag == '2') {
162 // 拒绝
163 // 弹出框填写理由
164 uni.showModal({
165 title: '请输入拒绝理由',
166 editable: true,
167 success: function(res) {
168 if (res.confirm) {
169 if (!res.content) {
170 uni.showToast({
171 title: '请输入拒绝理由',
172 icon: 'none'
173 })
174 } else {
175 obj.reason = res.content
176 doApproval(obj)
177 }
178 }
179 }
180 })
181 } else if (flag == '1') {
182 // 二次确认
183 uni.showModal({
184 title: '提示',
185 content: `确定审批通过吗`,
186 success: function(res) {
187 if (res.confirm) {
188 doApproval(obj)
189 }
190 }
191 })
192 }
193 }
194
195 function doApproval(obj) {
196 console.log(obj)
197 api.doMergeFlows(obj).then((res) => {
198 uni.showToast({
199 title: '操作成功',
200 icon: 'none'
201 })
202 getList()
203 })
204 }
205 </script>
206
207
208 <style scoped lang="scss">
209 .mt0 {
210 margin-top: 0 !important;
211 }
212
213 .appList .appItem .name {
214 width: 80%;
215 word-break: break-all;
216 }
217 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view>
3 <!-- 级位证书发布 -->
4 <view class="appList">
5 <view class="appItem" v-for="item in infoList">
6 <view class="status" @click="goDetail(item)">
7 <text :class="{
8 'text-warning':item.certStatus=='0',
9 'text-success':item.certStatus=='1'
10 }">{{ item.certStatusStr }}</text>
11 </view>
12
13 <view class="date">提交日期:{{item.submitTimeStr}}</view>
14 <view class="name mt0" @click="goDetail(item)">{{item.name}}</view>
15 <view class="pp esp" v-if="item.certTime">证书发送时间:{{item.certTimeStr}}</view>
16 <view class="flexbox" @click="goDetail(item)">
17 <view>
18 申请单位
19 <view>{{item.memberName}}</view>
20 </view>
21 <view>
22 已发证书
23 <view>{{item.hasCerts}}</view>
24 </view>
25 <view>
26 待发证书
27 <view>{{item.noCerts}}</view>
28 </view>
29 </view>
30 <view class="func" v-if="item.certStatus != '2'">
31 <button @click="send(item)">一键生成</button>
32 </view>
33 </view>
34 </view>
35
36 <view class="nodata" v-if="infoList.length==0">
37 <image mode="aspectFit" src="/static/nodata.png"></image>
38 <text>暂无数据</text>
39 </view>
40 </view>
41 </template>
42
43 <script setup>
44 import * as api from '@/common/api.js'
45 import config from '@/config.js'
46 import _ from 'lodash'
47 import {
48 onMounted,
49 ref
50 } from 'vue'
51 import {
52 onLoad,
53 onShow
54 } from '@dcloudio/uni-app'
55 const app = getApp();
56 const queryParams = ref({
57 // pageNum: 1,
58 // pageSize: 10
59 status: '0',
60 type: '1'
61 })
62 const statusArr = ['审批中', '审批通过', '审批拒绝', '审批撤回']
63 const current = ref()
64 const infoList = ref([])
65 const total = ref(0)
66 const deptType = ref('')
67 const userType = ref('')
68 onLoad((option) => {
69
70 })
71 onShow(() => {
72 if (app.globalData.isLogin) {
73 init()
74 } else {
75
76 app.firstLoadCallback = () => {
77 init()
78 };
79 }
80 })
81
82 function init() {
83 deptType.value = app.globalData.deptType
84 userType.value = app.globalData.userType
85 getList()
86 }
87
88
89 function getList() {
90 uni.showLoading({
91 title: '加载中'
92 })
93 api.getCertsLList(queryParams.value).then(res => {
94 infoList.value = res.rows
95 uni.hideLoading()
96 })
97 }
98
99 function goDetail(item) {
100 // const form = encodeURIComponent(JSON.stringify(item))
101 let path = `/pages/level/ztx/examList?type=1&payId=${item.payId}`
102 uni.navigateTo({
103 url: path
104 });
105 }
106
107 function send(row) {
108 uni.showModal({
109 title: '提示',
110 content: `确定生成 ${row.name} 的证书吗`,
111 success: function(res) {
112 if (res.confirm) {
113 api.submitCert([{
114 id: row.payId
115 }]).then(res => {
116 uni.showToast({
117 title: `下发成功`
118 })
119 getList()
120 })
121 }
122 }
123 })
124 }
125 </script>
126
127
128 <style scoped lang="scss">
129 .mt0 {
130 margin-top: 0 !important;
131 }
132
133 .appList .appItem .name {
134 width: 80%;
135 word-break: break-all;
136 }
137 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view>
3 <!-- 级位证书发布 -->
4 <view class="appList">
5 <view class="appItem" v-for="item in infoList">
6 <view class="status" @click="goDetail(item)">
7 <text :class="{
8 'text-warning':item.isCert=='0',
9 'text-primary':item.isCert=='1',
10 'text-success':item.isCert=='2'
11 }">{{ statusArr[item.isCert]}}</text>
12 </view>
13
14 <view class="date">申请日期: {{item.applyTime?.slice(0,10)}}</view>
15 <view class="name mt0" @click="goDetail(item)">{{item.name}}</view>
16 <view class="pp esp">考级考官:{{item.examinerNames}}</view>
17 <view class="flexbox" @click="goDetail(item)">
18 <view>
19 申请单位
20 <view>{{item.memberName}}</view>
21 </view>
22 <view>
23 已发/待发证书
24 <view>{{item.hasCerts}}/<text class="text-danger">{{item.noCerts}}</text></view>
25 </view>
26 <view>
27 考生数/通过数
28 <view>{{item.totalNum}}/<text class="text-danger">{{item.pass}}</text></view>
29 </view>
30 </view>
31 <view class="func" v-if="item.certStatus != '2'">
32 <button @click="send(item)">一键生成</button>
33 </view>
34 </view>
35 </view>
36
37 <view class="nodata" v-if="infoList.length==0">
38 <image mode="aspectFit" src="/static/nodata.png"></image>
39 <text>暂无数据</text>
40 </view>
41 </view>
42 </template>
43
44 <script setup>
45 import * as api from '@/common/api.js'
46 import config from '@/config.js'
47 import _ from 'lodash'
48 import {
49 onMounted,
50 ref
51 } from 'vue'
52 import {
53 onLoad,
54 onShow
55 } from '@dcloudio/uni-app'
56 const app = getApp();
57 const queryParams = ref({
58 // pageNum: 1,
59 // pageSize: 10
60 })
61 const statusArr = ['未发放', '部分发放', '已发放']
62 const current = ref()
63 const infoList = ref([])
64 const total = ref(0)
65 const deptType = ref('')
66 const userType = ref('')
67 onLoad((option) => {
68 queryParams.value.payId = option.payId
69 queryParams.value.type = option.type
70 })
71 onShow(() => {
72 if (app.globalData.isLogin) {
73 init()
74 } else {
75
76 app.firstLoadCallback = () => {
77 init()
78 };
79 }
80 })
81
82 function init() {
83 deptType.value = app.globalData.deptType
84 userType.value = app.globalData.userType
85 getList()
86 }
87
88
89 function getList() {
90 uni.showLoading({
91 title: '加载中'
92 })
93 api.getExamListByPayId(queryParams.value).then(res => {
94 infoList.value = res.rows
95 uni.hideLoading()
96 })
97 }
98
99 function goDetail(item) {
100 // const form = encodeURIComponent(JSON.stringify(item))
101 let path = `/pages/level/ztx/studentList?type=${queryParams.value.type}&examId=${item.examId}&payId=${queryParams.value.payId}`
102 uni.navigateTo({
103 url: path
104 });
105 }
106
107 function send(row) {
108 uni.showModal({
109 title: '提示',
110 content: `确定生成 ${row.name} 的证书吗`,
111 success: function(res) {
112 if (res.confirm) {
113 api.submitCert([{
114 id: row.payId
115 }]).then(res => {
116 uni.showToast({
117 title: `下发成功`
118 })
119 getList()
120 })
121 }
122 }
123 })
124 }
125 </script>
126
127
128 <style scoped lang="scss">
129 .mt0 {
130 margin-top: 0 !important;
131 }
132
133 .appList .appItem .name {
134 width: 80%;
135 word-break: break-all;
136 }
137 </style>
...\ No newline at end of file ...\ No newline at end of file
1 <template>
2 <view class="hasfixedbottom">
3 <view class="searchbar">
4 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search"
5 v-model="queryParams.name" placeholder="搜索姓名" @blur="getList()" @clear="getList()">
6 </uni-easyinput>
7 </view>
8 <view class="indexboxre">
9 <view class="userlist">
10 <view class="item" v-for="n in list">
11 <view class="w100">
12 <view class="status">
13 <text class="text-success" v-if="n.isCert == '1' ">已发送</text>
14 <text class="text-warning" v-else>未发送</text>
15 </view>
16 <view class="name">{{n.realName}}</view>
17
18
19 <view class="flexbox mtb30">
20 <view>所属团体
21 <text>{{n.memName}}</text>
22 </view>
23 <view>会员有效期
24 <text>{{n.vaildityDate?.slice(0,10)}}</text>
25 </view>
26 <view>级位
27 <text>
28 {{ szToHz(n.levelNew) }}
29 </text>
30 </view>
31 </view>
32
33 <div class="func">
34 <button @click="sendCert(n)">{{ ['发送证书','更新证书'][n.isCert] }}</button>
35 </div>
36 </view>
37 </view>
38 </view>
39
40 </view>
41
42 </view>
43 </template>
44
45 <script setup>
46 import * as api from '@/common/api.js'
47 import config from '@/config.js'
48 import {
49 ref,
50 getCurrentInstance
51 } from 'vue'
52 import {
53 onLoad
54 } from '@dcloudio/uni-app'
55 const {
56 proxy
57 } = getCurrentInstance()
58 const app = getApp();
59 const queryParams = ref({})
60 const list = ref([])
61 const total = ref(0)
62 const userType = ref('')
63 onLoad((option) => {
64 queryParams.value.examId = option.examId
65 queryParams.value.payId = option.payId
66 queryParams.value.type = option.type
67 getList()
68 })
69
70 function getList() {
71 uni.showLoading({
72 title: '加载中'
73 })
74 api.certStudentList(queryParams.value).then(res => {
75 list.value = res.rows
76 uni.hideLoading()
77 })
78 }
79
80 function szToHz(num) {
81 const hzArr = ['〇', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十']
82 return hzArr[parseInt(num)]
83 }
84
85
86 function sendCert(row) {
87 uni.showModal({
88 title: '提示',
89 content: `确定下发 ${row.realName} 的证书吗`,
90 success: function(res) {
91 if (res.confirm) {
92 const params = [{
93 id: queryParams.value.payId,
94 children: [{
95 id: queryParams.value.examId,
96 children: [row.id]
97 }]
98 }]
99
100 api.submitCert(params).then(res => {
101 uni.showToast({
102 title: `下发成功`
103 })
104 getList()
105 })
106 }
107 }
108 })
109 }
110
111
112 function handleImport() {
113 var arr = []
114 for (var n of list.value) {
115 if (n.checked) {
116 arr.push(n.perId)
117 }
118 }
119 if (arr.length == 0) {
120 uni.showToast({
121 title: "请选择会员",
122 icon: "none"
123 })
124 return
125 }
126 api.addPersonPaymentGroup({
127 rangeId: queryParams.value.paymentRangeId,
128 personIdArray: arr.join(',')
129 }).then(res => {
130 let path = `/pages/personalVip/renew?rangeId=${res.data.rangeId}`
131 uni.redirectTo({
132 url: path
133 });
134 })
135 }
136 </script>
137
138 <style scoped lang="scss">
139 .indexboxre {
140 padding: 0 30rpx;
141
142 .tt {
143 font-size: 30rpx;
144 margin: 0 0 30rpx;
145 color: #4C5359;
146 }
147
148 position: relative;
149 height: calc(100vh - 280rpx);
150 overflow: auto;
151 }
152
153 .searchbar {
154 display: flex;
155 align-items: center;
156 padding: 25rpx;
157 box-sizing: border-box;
158
159 :deep(.uni-easyinput .uni-easyinput__content) {
160 border-radius: 35rpx;
161 border: none;
162 height: 70rpx;
163 }
164
165 :deep(.uni-easyinput__content-input) {
166 font-size: 26rpx;
167 }
168 }
169 </style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
2 <view class="hasfixedbottom"> 2 <view class="hasfixedbottom">
3 <view class="searchbar"> 3 <view class="searchbar">
4 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search" 4 <uni-easyinput placeholderStyle="font-size:30rpx" :input-border="false" prefixIcon="search"
5 v-model="queryParams.name" placeholder="搜索姓名或证件号码" @blur="getList()" @clear="getList()"> 5 v-model="queryParams.name" placeholder="搜索姓名" @blur="getList()" @clear="getList()">
6 </uni-easyinput> 6 </uni-easyinput>
7 </view> 7 </view>
8 <view class="indexboxre"> 8 <view class="indexboxre">
......
1 @font-face {font-family: "iconfont";
2 src: url('iconfont.eot?t=1587304858380'); /* IE9 */
3 src: url('iconfont.eot?t=1587304858380#iefix') format('embedded-opentype'), /* IE6-IE8 */
4 url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAKYAAsAAAAABkQAAAJOAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCCcApQZAE2AiQDCAsGAAQgBYRtBzAbigXIrrApw69IkQJyuEPQxl76g4HoIYL6/dje+w8TiUTRZBoiHqpVEmRaIRRCYrpn8t//uczdiITNQB7LUyNSaIv5v7/lNAN0rMlIMv6eHwo3dzBnwGQPk3M8ZxtLDRi4CKu4hFtT9xqbz3M5vQl0IPMDneNqDtrDFk3qBXQvDqQA98IosjJJvGHsApfwmECtQTWVzdXtPRiWWasCcWu0A8O5tCyzWrVQWXMwixcVqtNTegeew+/Hn04Mk1QUrJaD8xUf5j/ZxeKxhE/IENDxChSYBzJxUlve0ycY16e23G8U7Ksx+FSWfkjs1S/YX2fV14N+qN6T5uq3WktwWxN1AL2jriQ6LvSLqs8PXI9IP2WWb82rj+Ho6f7KTwh8/vG/+MEqQLlFX3EFFQR3W5dz1tTif3VdBh/nNUyWm/WLguq9RIK/ofUcyLphBVNWtVpz0nGWtlq1KAnHW/2N9XSc2hyqR0SrDKQoVBsnMzuPCnUWUKnaCmrNWTtepw3rE7kGs64BQrNXJI3eUGjWIzP7iwqd/lGpOfpQ6yzaLqwzGWZ0g8kR8tE9ReNlqXLCMho17pA+jB3OGiF/QFyaHLYbrWJtjVLiObaUR7ojolBxluAqeI7iOMOcs5A8aQQiebfZVHVvanhZAqM2MOIQxIdcp5DhyaSUP1qMlj6/g2iHYg5u6aspDxBWMtOjtoZWD3LNkfbqu5dXSke0DiEUpLBMAq2CeSQWy6C8fl6IeERDMKKY62raw1RfR2N9V/J1x6CW5U1hzypUnjtpcGgAAA==') format('woff2'),
5 url('iconfont.woff?t=1587304858380') format('woff'),
6 url('iconfont.ttf?t=1587304858380') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
7 url('iconfont.svg?t=1587304858380#iconfont') format('svg'); /* iOS 4.1- */
8 }
9
10 .iconfont {
11 font-family: "iconfont" !important;
12 font-size: 16px;
13 font-style: normal;
14 -webkit-font-smoothing: antialiased;
15 -moz-osx-font-smoothing: grayscale;
16 }
17
18 .icon-fanhui:before {
19 content: "\e65c";
20 }
21
No preview for this file type
1 <?xml version="1.0" standalone="no"?>
2 <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
3 <!--
4 2013-9-30: Created.
5 -->
6 <svg>
7 <metadata>
8 Created by iconfont
9 </metadata>
10 <defs>
11
12 <font id="iconfont" horiz-adv-x="1024" >
13 <font-face
14 font-family="iconfont"
15 font-weight="500"
16 font-stretch="normal"
17 units-per-em="1024"
18 ascent="896"
19 descent="-128"
20 />
21 <missing-glyph />
22
23 <glyph glyph-name="fanhui" unicode="&#58972;" d="M349.184 382.976l435.2 432.64c13.824 13.824 13.824 39.424 0 53.76l-13.824 13.824c-13.824 13.824-39.424 13.824-53.76 0L239.616 410.624c-13.824-13.824-13.824-39.424 0-53.76l474.624-472.576c13.824-13.824 39.424-13.824 53.76 0l13.824 13.824c13.824 13.824 13.824 39.424 0 53.76l-432.64 431.104z" horiz-adv-x="1024" />
24
25
26
27
28 </font>
29 </defs></svg>
No preview for this file type
No preview for this file type
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!