工程训练:生意专家:06 店铺设置实现

0. 项目目录

  1. 欢迎页的实现
  2. 程序第一次运行实现
  3. 注册的实现
  4. 登陆的实现
  5. 首页的实现
  6. 店铺设置的实现
  7. 商品分类浏览的实现
  8. 编辑商品分类的实现
  9. 新增商品的实现
  10. 商品管理的实现

目录


# 写于2020.12.18 
# 测试全部成功
# 测试内容包括:店铺名字更改,密码更改,对原始密码验证,关于我们页面跳转等
# 更新不易,望赞鼓励

1. 任务要求

1.1 店铺(系统)设置详细需求
用户场景:为了方便用户的使用,通过店铺(系统)设置页导航到相关的功能。用户在使用软件的过程遇到困难,可以通过店铺(系统)设置页面中的联系客服功能,拨打客服电话。

工程训练:生意专家:06 店铺设置实现
输出/后置条件:点击安全退出时,修改用户登录的状态,把已登录状态改为未登录状态。点击不同的列表项进
入相应的页面。

1.2. 查看店铺信息与修改店铺信息详细需求
用户场景:为了让用户快速注册,注册时填写的店铺信息较少。用户可以通过使用店铺(系统)设置中的查看
店铺信息和修改店铺信息功能,完善店铺的相关信息。
工程训练:生意专家:06 店铺设置实现
1.3 修改密码详细需求
工程训练:生意专家:06 店铺设置实现

2. 工作指导

  • 参考之前的任务,创建店铺(系统)设置组件(含Module和Routing文件)。跟设置功能相关的页面都放在SettingPageModule中。在setting文件夹中分别创建AboutMe、ChangePassword、Shop等页面,最后在shop文件夹下创建edit(ShopEdit)页面。
  • 在setting文件夹下创建SettingService,添加一个属性保存用户和店铺的相关信息,再添加一个属性保存应用程序相关信息。添加load方法,向服务器(本地存储)请求用户和店铺的相关数据,可以使用三点运算符把两个对象合并,并把得到的数据保存在本地存储中,登录成功时调用。
  • 做到这里由于没有服务器,本地存储中保存了许多数据。部分数据代替了服务器数据库中的数据,另外一部分数据是客户端(浏览器端)需要保存的数据。
    工程训练:生意专家:06 店铺设置实现
    为了区分,用于代替服务器数据库存储的数据,Key前面+“T”,例如:TUser、TShop等。

3. 实现店铺(系统)设置页面

3.1 实现店铺(系统)设置的界面

使用3个ion-list。为每个ion-list元素添加inset属性,值设置为true,列表周围就会有边距和圆角。为
ion-item元素添加detail属性,在ion-item元素的右边显示右箭头图标。
src\app\pages\setting\setting.page.html

<ion-header>
  <ion-toolbar>
    <ion-button href='/home'>
      <ion-icon name="arrow-back">返回</ion-icon>
    </ion-button>
    <ion-title>店铺设置</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content color="medium">
  <ion-list inset="true">
    <ion-item detail href="/setting/shop">
      <ion-label>店铺设置</ion-label>
    </ion-item>
    <ion-item detail href="/setting/change-password">
      <ion-label>密码</ion-label>
    </ion-item>
  </ion-list>

  <ion-list inset="true">
    <ion-item detail href="/setting/about-me">
      <ion-label>关于我们</ion-label>
    </ion-item>
    <ion-item>
      <ion-label>联系客服</ion-label>
    
      <a href="tel:这里写你的电话号码">这里写你的电话号码</a>
    </ion-item>
    <ion-item detail href="">
      <ion-label>版本号:1.0.0</ion-label>
      <ion-note slot="end">检测更新</ion-note>
    </ion-item>
  </ion-list>

  <ion-list inset="true">
    <ion-item detail (click)="loginout()">
      <ion-label>安全退出</ion-label>
    </ion-item>
  </ion-list>
  <XXX-copyright [bottom]="'20px'"></XXX-copyright>
</ion-content>

detail属性,在item的右边显示一个向右的箭头图标。
ion-note是一种文本元素,通常用于副标题提供更多的信息。ion-note样式默认显示灰色。

  • 自己的 copyRight替换
  • 自己的电话号码替换一下

3.2 拨打电话联系客服

我用的前面这种方法
先在工程的根目录下找到config.xml文件,添加下面的配置:config.xml

<access origin="tel:*" launch-external="yes"/>
<allow-intent href="tel:*" />

工程训练:生意专家:06 店铺设置实现

第二种方法:
通过click事件绑定调用以下方法
src\app\pages\setting\setting.page.ts

onCall(phoneNumber) {
 window.location.href = 'tel:' + phoneNumber;
}

4 修改密码页面

参考之前的任务根据需求实现修改密码功能。注册功能和修改密码功能都需要验证两个密码要一致,早期任务
实现的方式比较笨拙,而且没有融入到Angular的表单验证的机制中。可以通过自定义指令以及自定义验证器来
实现。
在shared文件夹下创建directives目录,用于存放自定义的指令。执行下面的命令创建ConfirmDirective:

ionic g directive shared/directives/confirm

添加一个函数confirmValidator。
src\app\shared\directives\confirm.directive.ts

import { Directive, Input } from '@angular/core';
import { AbstractControl, NG_VALIDATORS, ValidationErrors, Validator, ValidatorFn } from '@angular/forms';

@Directive({
  selector: '[AAAA]',
  providers: [
    {
      provide: NG_VALIDATORS,
      useExisting: ConfirmDirective,
      multi: true
    }
  ]
})
export class ConfirmDirective implements Validator {
  @Input('AAAA') confirm: string;
  constructor() { }
  validate(control: AbstractControl): ValidationErrors {
    return this.confirm ? confirmValidator(this.confirm)(control) : null;
    // throw new Error('Method not implemented.');
  }
  // registerOnValidatorChange?(fn: () => void): void {
  //   throw new Error('Method not implemented.');
  // }
}


export function confirmValidator(confirm: string): ValidatorFn {
  return (control: AbstractControl): {[key: string]: any} => { // 传入绑定表单的formControl
    if ( !control.value ) { // 如果绑定未输入值,则返回 required错误
     return {required: true };
    }
   // 如果两次输入的值不相同,则返回confirm的错误
    return control.value !== confirm ? {confirm: {value: true}} : null;
   };
}

其中AAAA为这个修改密码函数的名字 换成自己的
在模板文件中添加自定义的属性。
src\app\pages\setting\change-password\change-password.page.html

<ion-header>
  <ion-toolbar>
    <ion-title>修改密码</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <form #passwordForm>
  <ion-list>
    <ion-item lines="none">
      <ion-label position="floating">输入旧密码</ion-label>
      <ion-input name="oldPassword" #oldPassword="ngModel"  [(ngModel)]="viewObject.oldPassword" required type="password">
      </ion-input>
    </ion-item>
    <ion-item *ngIf="oldPassword.invalid && oldPassword.touched" lines="none">
      <ion-text color="danger" *ngIf="oldPassword.errors?.required">
        请输入旧密码
      </ion-text>
    </ion-item>
    <ion-text [hidden]="isRight" padding-start color="danger">您输入的旧密码不正确</ion-text>
  
    <ion-item lines="none">
      <ion-label position="floating">输入新密码</ion-label>
      <ion-input name="newPassword" #newPassword="ngModel"  [(ngModel)]="viewObject.newPassword" required type="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[^]{8,16}$">
      </ion-input>
    </ion-item>
    <ion-item *ngIf="newPassword.invalid && newPassword.touched" lines="none">
      <ion-text color="danger" *ngIf="newPassword.errors?.required">
        请输入新密码
      </ion-text>
      <ion-text color="danger" *ngIf="newPassword.errors?.pattern">
        密码包含大小写字母和数字且长度在8-16位
      </ion-text>
    </ion-item>
    
    <ion-item lines="none">
      <ion-label position="floating">再输入一次新密码</ion-label>
      <ion-input name="confirmPassword" #confirmPassword="ngModel"  [(ngModel)]="viewObject.confirmPassword" [AAAA]="viewObject.newPassword" required type="password">
      </ion-input>
    </ion-item>
    <ion-item *ngIf="confirmPassword.invalid && confirmPassword.touched" lines="none">
      <ion-text color="danger" *ngIf="confirmPassword.errors?.confirm">
        两次密码不一致
      </ion-text>
      <ion-text color="danger" *ngIf="confirmPassword.errors?.required">
        请输入确认密码
      </ion-text>
    </ion-item>
  </ion-list>
  <div class="ion-padding-horizontal">
    <ion-button expand="block" [disabled]="confirmPassword.invalid" (click)="updatePassword()">重置密码</ion-button>
  </div>
</form>
</ion-content>

  • 这个AAAA配合着上面的ts,两者名字要一样
    工程训练:生意专家:06 店铺设置实现
  • 代码显示有些是备注 但实际上全部有用 这里只是没法解析#号

测试通过后,使用自定义验证器修改之前任务中的注册页面。
类似"ng"、“ion”这些前缀,请把默认前缀“app”改成你的专有字符串(姓名拼音首字符)。

5. 关于我们页面

内容包括你的学号、姓名、完成了哪些功能、哪些功能没有完成、通过实训掌握了什么,有什么意见和建议等。
src\app\pages\setting\about-me\about-me.page.html

<ion-header>
  <ion-toolbar>
    <ion-button href='/setting'>
      <ion-icon name="arrow-back"></ion-icon>返回
    </ion-button>
    <ion-title>关于我们</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-card>
    <ion-card-header>工程实训</ion-card-header>
    <ion-card-content>
      <ion-list>
        <ion-item>
          <ion-label><b>学号:</b></ion-label>
          <ion-note slot="end">@@@@@写自己学号</ion-note>
        </ion-item>
        <ion-item>
          <ion-label><b>姓名:</b></ion-label>
          <ion-note slot="end">@@@@@写自己名字</ion-note>
        </ion-item>
        <ion-item>
          <ion-label><b>已完成功能:</b></ion-label>
        </ion-item>
        <ion-item>
          <ion-text>
        	@@@@@写自己完成功能
          </ion-text>
        </ion-item>
        <ion-item>
          <ion-label><b>未完成功能:</b></ion-label>
        </ion-item>
        <ion-item>
          <ion-text>
            <p>@@@@@写自己未完成功能</p>
          </ion-text>
        </ion-item>
        <ion-item>
          <ion-label><b>学习与收获:</b></ion-label>
        </ion-item>
        <ion-item>
          <ion-text>
            @@@@@写自己收获
          </ion-text>
        </ion-item>
        <ion-item>
          <ion-label><b>意见与建议</b></ion-label>
        </ion-item>
        <ion-item>
          <ion-text>
				@@@@@写自己意见和建议
          </ion-text>
        </ion-item>
      </ion-list>

      <ion-card-subtitle>日期</ion-card-subtitle>
      <div>
        <ion-datetime display-format="MM DD, YYYY HH:MM" value="2020-11-12T21:11" disabled="true"></ion-datetime>
      </div>
    </ion-card-content>
  </ion-card>
</ion-content>
  • 补齐@@@@@,写自己东西
  • 2020-11-12T21:11换成自己时间

6. 修改店铺名称

title和property代表参数的名字,property的值是店铺模型中对应属性的名称。routerLink(路由链接)属性是Angular提供的指令。这个指令
把可点击的 HTML元素绑定到某个路由。点击带有 routerLink指令(绑定到字符串或链接参数数组)的元素
时就会触发一次导航。
在店铺修改页中获取店铺信息页传递过来的参数。
src\app\pages\setting\shop\edit\shop-edit.ts

import { ShopService } from './../shop.service';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { SettingService } from '../../setting.service';
import { ToastController } from '@ionic/angular';
import { LocalStorageService } from 'src/app/shared/services/local-storage.service';
import { ShopPage } from '../shop.page';
import { StatusBar } from '@ionic-native/status-bar/ngx';
@Component({
  selector: 'app-shop-edit',
  templateUrl: './shop-edit.page.html',
  styleUrls: ['./shop-edit.page.scss'],
})
export class ShopEditPage implements OnInit {

  title: string;
  property: string;
  value: any; // 用于ngModel,从shop对象的相关属性中获取数据

  constructor(
    private activatedRoute: ActivatedRoute,
    private router: Router,
    private shopService: ShopService,
    private toastCtrl: ToastController,
    private localStorageService :LocalStorageService,
    private statusBar:StatusBar
  ) {
     // 沉浸式并且悬浮透明
     this.statusBar.overlaysWebView(true);
    activatedRoute.queryParams.subscribe(queryParams => {
      this.property = queryParams.property;
      this.title = queryParams.title;
    });
  }

  ngOnInit() {
  }

  async onSave() {
    const user = this.localStorageService.getUser();
    const shop = this.shopService.getShop(user.id);
    shop[this.property] = this.value;
    this.shopService.updateShop(shop);

    this.value = '';
    const toast = await this.toastCtrl.create({
      message: '保存成功',
      duration: 3000
    });
    toast.present();
    this.router.navigateByUrl('/setting/shop');
  }

}

为组件添加onSave方法,使用变量对对象的属性进行访问或者赋值。并通过服务把修改后的店铺数据保存到本地存储中。最后页面跳转回到店铺信息页面。


src\app\pages\setting\shop\edit\shop-edit.html

<ion-header>
  <ion-toolbar>
    <ion-button href='setting/shop'>
      <ion-icon name="arrow-back"></ion-icon>返回
    </ion-button>
    <ion-title>{{title}}</ion-title>
  </ion-toolbar>
</ion-header>


<ion-content>
  <form>
    <ion-list>
      <ion-item>
        <ion-input name="{{property}}" type="text" [(ngModel)]="value" required placeholder="{{title}}"></ion-input>
      </ion-item>
    </ion-list>
    <div padding-horizontal>
      <ion-button expand="block" color="primary" (click)="onSave()">保存</ion-button>
    </div>
  </form>
</ion-content>
上一篇:12.9-新项目克隆到本地-先配置maven的setting文件


下一篇:vscode 自动保存代码