每日一题:会员卡定制 介绍 随着数字化时代的来临,线上平台成为商家与用户之间的重要连接点,线上 VIP 卡定制功能可以满足用户的个性化需求、提升品牌形象和用户体验,并通过数据分析和个性化推荐实现更好的营销效果。这是一个与时俱进的方式,使商家能够与用户建立更紧密的关系,赢得市场竞争的优势。
本题需要你运用所学实现一个线上 VIP 卡的定制功能。
准备 本题已经内置了初始代码,打开实验环境,目录结构如下:
1 2 3 4 5 6 7 8 9 ├── css ├── effect1.gif ├── effect2.gif ├── effect3.gif ├── images ├── index.html └── js ├── index.js └── vue3.global.js
其中:
css 是需要样式文件夹。
effect1.gif ~ effect3.gif 为三个目标的效果图。
images 是图片文件夹。
js/vue3.global.js 是 vue3.x 文件。
js/index.js 是需要补充代码的 js 文件。
index.html 是需要补充代码的主页面。
注意:打开环境后发现缺少项目代码,请手动键入下述命令进行下载:
1 2 cd /home/projectwget https://labfile.oss.aliyuncs.com/courses/5340/vip-card.zip && unzip vip-card.zip && rm vip-card.zip
选中 index.html 右键启动 Web Server 服务(Open with Live Server),让项目运行起来。接着,打开环境右侧的【Web 服务】,就可以在浏览器中看到如下效果:
目标
完善 index.html 中 <label for="cardNumber"> 标签下的 TODO 代码,实现将 Card Number 输入框中输入的卡号以一定规则显示在会员卡最终效果显示区域 的效果。具体需求为:
卡号显示输入值的前 19 位,多出 19 个字符直接忽略不做处理。
卡号显示效果为:使用空格将上面输入值的前 19 位分为 4 组,前 3 组分别由 5 个字符组成,最后 1 组由 4 个字符组成。
其中第一组和最后一组显示具体输入的值,中间两组每组的前 4 位由 号代替,最后一位显示对应的输入值。例如:输入的卡号为 20 位字符串 “12345678901234567890” 显示效果为 “12345 *0 5 6789”。
最终效果可参考文件夹下面的 gif 图,图片名称为 effect1.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
需要注意的是,分组空格的 <div> 标签(.card-item__numberItem)元素需要添加 -active 类,其最终使用的 DOM 结构为:
1 <span > <div class ="card-item__numberItem -active" > </div > </span >
最终渲染在浏览器中的 DOM 结构为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <span > <div class ="card-item__numberItem" > 1</div > </span > <span > <div class ="card-item__numberItem" > 2</div > </span > <span > <div class ="card-item__numberItem" > 3</div > </span > <span > <div class ="card-item__numberItem" > 4</div > </span > <span > <div class ="card-item__numberItem" > 5</div > </span > <span > <div class ="card-item__numberItem -active" > </div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > 0</div > </span > <span > <div class ="card-item__numberItem -active" > </div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > *</div > </span > <span > <div class ="card-item__numberItem" > 5</div > </span > <span > <div class ="card-item__numberItem -active" > </div > </span > <span > <div class ="card-item__numberItem" > 6</div > </span > <span > <div class ="card-item__numberItem" > 7</div > </span > <span > <div class ="card-item__numberItem" > 8</div > </span > <span > <div class ="card-item__numberItem" > 9</div > </span >
完善 index.html 中 <div class="card-item__name"> 标签下的 TODO 代码,实现将输入框 Card Holders 中输入的用户名以一定规则显示在会员卡最终效果显示区域 的效果。具体需求为:完成输入卡片持有者(Card Holders)Full Name 的显示效果。Full Name 的长度不限,若输入值中有 1 到多个连续的空格,则只保留 1 个空格,且英文字母均为大写。例如:输入值为 “T o n ney”(即,字母 T 后面有 3 个空格,o 后面有两个空格,n 后面有一个空格),则显示效果为 “T O N NEY”。其最终 DOM 结构为:
1 2 3 4 5 6 7 8 9 10 <span class ="card-item__nameItem" > T</span > <span class ="card-item__nameItem" > </span > <span class ="card-item__nameItem" > o</span > <span class ="card-item__nameItem" > </span > <span class ="card-item__nameItem" > n</span > <span class ="card-item__nameItem" > </span > <span class ="card-item__nameItem" > n</span > <span class ="card-item__nameItem" > e</span > <span class ="card-item__nameItem" > y</span >
最终效果可参考文件夹下面的 gif 图,图片名称为 effect2.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
补充 js/index.js 中的 TODO 代码,实现 computed 计算属性 minCardMonth 和 watch 监听 cardYear,最终实现本年只能选择当前月份及以后的月份的功能。即,当页面中Expiration Date 日期选择下拉框 中的 Year 下拉框为当前年份 时,minCardMonth 的值只能选择当前月份及其之后的月份 。例如:当前年月为 2023 年 7 月,且 Year 下拉框选中的为 2023(即 minCardYear 值为 “2023”),则 Month 下拉框只能选 7~12月。
最终效果可参考文件夹下面的 gif 图,图片名称为 effect3.gif(提示:可以通过 VS Code 或者浏览器预览 gif 图片)。
规定
请勿修改 index.html 和 js/index.js 文件中 TODO 之外的任何内容。
请严格按照考试步骤操作,切勿修改考试默认提供项目中的文件名称、文件夹路径、class 名、id 名、图片名等,以免造成判题无法通过。
满足题目需求后,保持 Web 服务处于可以正常访问状态,点击「提交检测」系统会自动判分。
判分标准
完成目标 1,得 5 分。
完成目标 2,得 10 分。
完成目标 3,得 5 分。
总通过次数: 23 | 总提交次数: 56 | 通过率: 41.1%
题解: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 req.on ("end" , () => { let { interested = [] } = qs.parse (body); let html = '' if (!interested.length ) { html = `<div class="unselect">你还未选择任何感兴趣的标签!</div>` } else { const hashMap = {} const result = [] if (!Array .isArray (interested)) interested = [interested] for (let i = 0 ; i < interested.length ; i++) { for (let j = 0 ; j < data.length ; j++) { if (interested[i] === data[j]['tag' ] && !hashMap[interested[i]]) { result.push (data[j]) hashMap[interested[i]] = 1 for (let tag of data[j]['relevance' ]) { if (interested.indexOf (tag) === -1 ) { interested.push (tag) } } } } } for (let item of result) html += `<div class="interest"> <div class="tag">${item.tag} </div> <div>${item.content} </div> </div>` } let customized = fs.readFileSync (path.join (__dirname, "../customized.html" ), { encoding : "utf8" , }); customized = customized.replace ('<body></body>' , `<body>${html} </body>` ) res.writeHead (200 , { "Content-Type" : "text/html" }); res.write (customized); res.end (); });
1 2 3 4 5 6 7 8 <!-- 目标 1 TODO :在当前 <label for ="cardNumber" > 标签中补充代码,完成输入卡号的显示效果。--> <span v-for="(n, $index) in otherCardMask" :key="$index"> <transition name="slide-fade-up"> <!-- 目标 1 TODO Start --> <div class="card-item__numberItem" v-if="cardNumber && $index < cardNumber.length && $index > 4 && $index < 15 && n.trim() !== ''">*</div> <div class="card-item__numberItem" v-else-if='cardNumber && $index < cardNumber.length' :class="n.trim() === '' ? '-active' : ''">{{cardNumber[$index]}}</div> <div class="card-item__numberItem" v-else :class="n.trim() === '' ? '-active' : ''">{{n}}</div> <!-- 目标 1 TODO End -->
1 2 3 4 <!-- 目标 2 TODO :在下面补充代码,完成输入卡片持有者(Card Holders )Full Name 的显示效果。--> <!-- 目标 2 TODO Start --> <span class ="card-item__nameItem" v-for ="(item, $index) in cardName.replaceAll(/\s+/g, ' ')" :key ="$index" > {{ item }}</span > <!-- 目标 2 TODO End -->
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 const minCardMonth = computed (() => { console .log (data.cardYear ); console .log (data.minCardYear ); if (data.cardYear === data.minCardYear ) { data.cardMonth = '' return new Date ().getMonth () + 1 } return 1 ; }) watch ( () => { if (data.cardMonth < minCardMonth.value ) { data.cardMonth = '' } return data.cardYear .value ; }, () => { console .log ("data.cardYear 发生了变化" ); }, { immediate : true , } );