!3474 【Sample】橘子购物sample添加动效代码

Merge pull request !3474 from haoxiaohui/master
This commit is contained in:
openharmony_ci 2023-09-27 14:16:43 +00:00 committed by Gitee
commit 303fcdc279
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
47 changed files with 1587 additions and 729 deletions

View File

@ -15,13 +15,17 @@
{
"app": {
"compileSdkVersion": 10,
"compatibleSdkVersion": 10,
"products": [
{
"name": "default",
"signingConfig": "default"
"signingConfig": "default",
"compileSdkVersion": 10,
"compatibleSdkVersion": 10,
"targetSdkVersion": 10,
"runtimeOS": "OpenHarmony"
}
],
"signingConfigs": [
]
},
"modules": [

View File

@ -14,12 +14,12 @@
*/
import AbilityStage from '@ohos.app.ability.AbilityStage';
import { logger } from '@ohos/details-page-component'
import { logger } from '@ohos/details-page-component';
const TAG: string = 'MyAbilityStage'
const TAG: string = 'MyAbilityStage';
export default class MyAbilityStage extends AbilityStage {
onCreate() {
logger.info(TAG, 'onCreate')
logger.info(TAG, 'onCreate');
}
}

View File

@ -13,27 +13,28 @@
* limitations under the License.
*/
import UIAbility from '@ohos.app.ability.UIAbility'
import { logger } from '@ohos/details-page-component'
import { notificationUtil } from '@ohos/notification'
import { QRCodeScanConst } from '@ohos/scan-component'
import abilityAccessCtrl from '@ohos.abilityAccessCtrl'
import UIAbility from '@ohos.app.ability.UIAbility';
import { logger } from '@ohos/details-page-component';
import { notificationUtil } from '@ohos/notification';
import { QRCodeScanConst } from '@ohos/scan-component';
import abilityAccessCtrl from '@ohos.abilityAccessCtrl';
import Want from '@ohos.app.ability.Want';
const TAG: string = 'MainAbility'
const TAG: string = 'MainAbility';
export default class MainAbility extends UIAbility {
onCreate(want, launchParam) {
logger.info(TAG, 'onCreate')
const that = this
onCreate(want: Want): void {
logger.info(TAG, 'onCreate');
const that = this;
this.context.eventHub.on("getAbilityData", (data) => {
data.context = that.context
data.launchWant = want
data.context = that.context;
data.launchWant = want;
})
this.requestPermission()
AppStorage.SetOrCreate('context', this.context)
this.requestPermission();
AppStorage.setOrCreate('context', this.context);
}
requestPermission = async () => {
async requestPermission(): Promise<void> {
let permissionRequestResult = await abilityAccessCtrl.createAtManager().requestPermissionsFromUser(this.context,
[
'ohos.permission.CAMERA',
@ -46,36 +47,35 @@ export default class MainAbility extends UIAbility {
// 如果权限列表中有-1说明用户拒绝了授权
if (permissionRequestResult.authResults[0] === 0) {
// 控制相机是否打开
AppStorage.SetOrCreate(QRCodeScanConst.HAS_CAMERA_PERMISSION, true)
logger.info('MainAbility permissionRequestResult success')
AppStorage.setOrCreate(QRCodeScanConst.HAS_CAMERA_PERMISSION, true);
logger.info('MainAbility permissionRequestResult success');
}
await notificationUtil.enableNotification()
await notificationUtil.enableNotification();
}
onDestroy() {
logger.info(TAG, 'onDestroy')
onDestroy(): void {
logger.info(TAG, 'onDestroy');
}
onWindowStageCreate(windowStage) {
onWindowStageCreate(windowStage): void {
// Main window is created, set main page for this ability
logger.info(TAG, 'onWindowStageCreate')
windowStage.setUIContent(this.context, 'pages/Index', null)
logger.info(TAG, 'onWindowStageCreate');
windowStage.setUIContent(this.context, 'pages/Index', null);
}
onWindowStageDestroy() {
onWindowStageDestroy(): void {
// Main window is destroyed, release UI related resources
logger.info(TAG, 'onWindowStageDestroy')
logger.info(TAG, 'onWindowStageDestroy');
}
onForeground() {
onForeground(): void {
// Ability has brought to foreground
logger.info(TAG, 'MainAbility onForeground')
AppStorage.SetOrCreate('cameraStatus', !AppStorage.Get('cameraStatus'))
logger.info(TAG, 'MainAbility onForeground');
AppStorage.setOrCreate('cameraStatus',!AppStorage.Get('cameraStatus'));
}
onBackground() {
onBackground(): void {
// Ability has back to background
logger.info(TAG, 'onBackground')
logger.info(TAG, 'onBackground');
}
}

View File

@ -13,35 +13,36 @@
* limitations under the License.
*/
import WorkSchedulerExtensionAbility from '@ohos.WorkSchedulerExtensionAbility'
import { notificationUtil, notificationContentUtil, notificationRequestUtil, wantAgentUtil } from '@ohos/notification'
import { logger } from '@ohos/details-page-component'
import WorkSchedulerExtensionAbility from '@ohos.WorkSchedulerExtensionAbility';
import { notificationUtil, notificationContentUtil, notificationRequestUtil, wantAgentUtil } from '@ohos/notification';
import { logger } from '@ohos/details-page-component';
import workScheduler from '@ohos.resourceschedule.workScheduler';
const TAG: string = 'WorkAbility'
const BUNDLE_NAME = 'ohos.samples.orangeshopping'
const ABILITY_NAME = 'MainAbility'
const NOTIFICATION_ID = 1 // 定义发送通知的id,默认1
const TAG: string = 'WorkAbility';
const BUNDLE_NAME: string = 'ohos.samples.orangeshopping';
const ABILITY_NAME: string = 'MainAbility';
const NOTIFICATION_ID: number = 1 // 定义发送通知的id,默认1
export default class WorkAbility extends WorkSchedulerExtensionAbility {
onWorkStart(workInfo) {
logger.info(TAG, `onWorkStart ${JSON.stringify(workInfo)}`)
onWorkStart(workInfo: workScheduler.WorkInfo) {
logger.info(TAG, `onWorkStart ${JSON.stringify(workInfo)}`);
if (workInfo.parameters) {
this.publishNotification(workInfo.parameters)
this.publishNotification(workInfo.parameters);
}
}
onWorkStop(workInfo) {
logger.info(TAG, `onWorkStop ${JSON.stringify(workInfo)}`)
notificationUtil.cancelNotificationById(1)
logger.info(TAG, `onWorkStop ${JSON.stringify(workInfo)}`);
notificationUtil.cancelNotificationById(1);
}
publishNotification = async (parameters: any) => {
let parametersObject = JSON.parse(parameters)
logger.info(TAG, `publishNotification parametersObject= ${parametersObject}`)
async publishNotification(parameters: any): Promise<void> {
let parametersObject = JSON.parse(parameters);
logger.info(TAG, `publishNotification parametersObject= ${parametersObject}`);
let basicContent = {
title: parametersObject.title,
text: ''
}
};
let actionButtons = [
{
title: parametersObject.firstButton,
@ -51,13 +52,13 @@ export default class WorkAbility extends WorkSchedulerExtensionAbility {
title: parametersObject.secondButton,
wantAgent: await wantAgentUtil.createWantAgentForStartAbility(BUNDLE_NAME, ABILITY_NAME)
}
]
];
try {
let notificationContent = notificationContentUtil.initBasicNotificationContent(basicContent)
let notificationRequest = notificationRequestUtil.initButtonNotificationRequest(notificationContent, actionButtons)
notificationUtil.publishNotification(notificationRequest, NOTIFICATION_ID)
let notificationContent = notificationContentUtil.initBasicNotificationContent(basicContent);
let notificationRequest = notificationRequestUtil.initButtonNotificationRequest(notificationContent, actionButtons);
notificationUtil.publishNotification(notificationRequest, NOTIFICATION_ID);
} catch (error) {
logger.info(TAG, `publish notification error ${JSON.stringify(error)}`)
logger.info(TAG, `publish notification error ${JSON.stringify(error)}`);
}
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { DetailPage } from '@ohos/details-page-component'
import { DetailPage } from '@ohos/details-page-component';
@Entry
@Component
struct Detail {
build() {
Column() {
DetailPage()
DetailPage();
}
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { FullPage } from '@ohos/video-component'
import { FullPage } from '@ohos/video-component';
@Entry
@Component
struct Detail {
build() {
Column() {
FullPage()
FullPage();
}
}
}

View File

@ -13,30 +13,28 @@
* limitations under the License.
*/
import mediaquery from '@ohos.mediaquery'
import window from '@ohos.window'
import { NavigationHomePage } from '@ohos/navigation-component'
import { UpdateDialog } from '@ohos/updatedialog'
import { EventsDialog } from '@ohos/details-page-component'
import { EmitterClass } from '@ohos/emitter'
import mediaQuery from '@ohos.mediaquery';
import window from '@ohos.window';
import { NavigationHomePage } from '@ohos/navigation-component';
import { UpdateDialog } from '@ohos/updatedialog';
import { EventsDialog } from '@ohos/details-page-component';
import { EmitterClass } from '@ohos/emitter';
@Entry
@Component
struct HomePage {
@State url: string = ''
@State option: object = undefined
@State curBp: string = 'md' // curBp指当前窗口断点sm代表小屏md代表中屏lg代表大屏
private smListener: any
private mdListener: any
private lgListener: any
@StorageLink('shoppingCartGoodsList') shoppingCartGoodsList: { data: { id: number } }[] = []
private emitterClass: EmitterClass = new EmitterClass()
@State url: string = '';
@State option: object = undefined;
@State curBp: string = 'md'; // curBp指当前窗口断点sm代表小屏md代表中屏lg代表大屏
private smListener: mediaQuery.MediaQueryListener;
private mdListener: mediaQuery.MediaQueryListener;
private lgListener: mediaQuery.MediaQueryListener;
@StorageLink('shoppingCartGoodsList') shoppingCartGoodsList: { data: { id: number } }[] = [];
private emitterClass: EmitterClass = new EmitterClass();
EventsDialogController: CustomDialogController = new CustomDialogController({
builder: EventsDialog(),
customStyle: true
})
UpdateDialogController: CustomDialogController = new CustomDialogController({
builder: UpdateDialog(),
customStyle: true
@ -44,35 +42,35 @@ struct HomePage {
build() {
Column() {
NavigationHomePage({ url: this.url })
NavigationHomePage({ url: this.url });
}
}
aboutToAppear() {
if(AppStorage.Get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0){
aboutToAppear(): void {
if (AppStorage.get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0) {
this.UpdateDialogController.open()
}
this.emitterClass.showEventsDialog(()=>{
if(AppStorage.Get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0){
this.emitterClass.showEventsDialog(() => {
if (AppStorage.get('nowIndex') === undefined || AppStorage.Get('nowIndex') === 0) {
this.EventsDialogController.open()
}
})
this.emitterClass.setShoppingCartGoodsList((eventData)=>{
this.emitterClass.setShoppingCartGoodsList((eventData) => {
this.shoppingCartGoodsList.push(eventData.data.id)
AppStorage.SetOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList)
AppStorage.setOrCreate('shoppingCartGoodsList', this.shoppingCartGoodsList)
})
this.smListener = mediaquery.matchMediaSync('(320vp<=width<520vp)')
this.smListener = mediaQuery.matchMediaSync('(320vp<=width<520vp)')
this.smListener.on('change', this.isBreakpointSM)
this.mdListener = mediaquery.matchMediaSync('(520vp<=width<840vp)')
this.mdListener = mediaQuery.matchMediaSync('(520vp<=width<840vp)')
this.mdListener.on('change', this.isBreakpointMD)
this.lgListener = mediaquery.matchMediaSync('(840vp<=width)')
this.lgListener = mediaQuery.matchMediaSync('(840vp<=width)')
this.lgListener.on('change', this.isBreakpointLG)
window.getTopWindow({ stageMode: true }).then(result => {
window.getLastWindow({ stageMode: true }).then(result => {
result.setFullScreen(false)
})
}
aboutToDisappear() {
aboutToDisappear(): void {
this.smListener.off('change', this.isBreakpointSM)
this.mdListener.off('change', this.isBreakpointMD)
this.lgListener.off('change', this.isBreakpointLG)
@ -81,19 +79,19 @@ struct HomePage {
isBreakpointSM = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'sm'
AppStorage.SetOrCreate('curBp', this.curBp)
AppStorage.setOrCreate('curBp', this.curBp)
}
}
isBreakpointMD = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'md'
AppStorage.SetOrCreate('curBp', this.curBp)
AppStorage.setOrCreate('curBp', this.curBp)
}
}
isBreakpointLG = (mediaQueryResult) => {
if (mediaQueryResult.matches) {
this.curBp = 'lg'
AppStorage.SetOrCreate('curBp', this.curBp)
AppStorage.setOrCreate('curBp', this.curBp)
}
}
}

View File

@ -13,8 +13,8 @@
* limitations under the License.
*/
import routerUtil from '../utils/RouterUtil'
import { TransitionsAnimation } from '@ohos/enter-animation'
import routerUtil from '../utils/RouterUtil';
import { TransitionsAnimation } from '@ohos/enter-animation';
@Entry
@Component
@ -23,9 +23,9 @@ struct Index {
Column() {
TransitionsAnimation({
gotoNav: () => {
routerUtil.gotoHome()
routerUtil.gotoHome();
}
})
});
}
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { LivePage } from '@ohos/video-component'
import { LivePage } from '@ohos/video-component';
@Entry
@Component
struct Live {
build() {
Column() {
LivePage()
LivePage();
}
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { QRCodeScanComponent } from "@ohos/scan-component"
import { QRCodeScanComponent } from "@ohos/scan-component";
@Entry
@Component
struct Scan {
build() {
Column() {
QRCodeScanComponent()
QRCodeScanComponent();
}
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { setting } from '@ohos/http'
import { setting } from '@ohos/http';
@Entry
@Component
struct Index {
build() {
Column() {
setting()
setting();
}
}
}

View File

@ -13,21 +13,21 @@
* limitations under the License.
*/
import router from '@ohos.router'
import router from '@ohos.router';
export default class RouterUtil {
static gotoHome() {
router.replace({
router.replaceUrl({
url: 'pages/Home'
})
});
}
static gotoDetail() {
router.push({
router.pushUrl({
url: 'pages/Detail',
params: {
id: 10
}
})
});
}
}

View File

@ -15,10 +15,11 @@
@Component
export struct AddressService {
@Link isPanel: boolean
@Link currentLocation: string
@Link isPanel: boolean;
@Link currentLocation: string;
@Builder Server(text: Resource, marginTop: number) {
@Builder
Server(text: Resource, marginTop: number) {
Row() {
Image($r('app.media.service'))
.objectFit(ImageFit.Contain)
@ -78,7 +79,7 @@ export struct AddressService {
.alignItems(VerticalAlign.Top)
.width('100%')
.onClick(() => {
this.isPanel = !this.isPanel
this.isPanel = !this.isPanel;
})
Row() {

View File

@ -13,16 +13,21 @@
* limitations under the License.
*/
import router from '@ohos.router'
import prompt from '@ohos.prompt'
import { EmitterClass } from '@ohos/emitter'
import { ProductDataModel } from '../model/DetailMode'
import router from '@ohos.router';
import { EmitterClass } from '@ohos/emitter';
import { ProductDataModel } from '../model/DetailMode';
import curves from '@ohos.curves';
@Component
export struct BottomNavigation {
@StorageProp('curBp') curBp: string = 'md'
@Link goodItemData: ProductDataModel
private emitterClass: EmitterClass = new EmitterClass()
@StorageProp('curBp') curBp: string = 'md';
@Link goodItemData: ProductDataModel;
private emitterClass: EmitterClass = new EmitterClass();
@Link animateAppear: boolean; // 动画开始标识
@Link animateScale: boolean; // 开始缩小动画标识
@Link animatePath: boolean; // 开始路径动画标识
@State animateSpring: boolean = false; // 开始弹簧动画标识
@State productCount: number = 1;
build() {
Row() {
@ -39,16 +44,30 @@ export struct BottomNavigation {
}
.width(74)
.onClick(() => {
AppStorage.SetOrCreate('nowIndex',0)
router.push({
AppStorage.SetOrCreate('nowIndex', 0)
router.pushUrl({
url: 'pages/Home'
})
});
})
Column() {
Image($r('app.media.cart'))
.width(22)
.height(22)
Stack({ alignContent: Alignment.TopEnd }) {
Image($r('app.media.cart'))
.width(22)
.height(22)
.rotate(this.animateSpring ? { angle: 10 } : { angle: 0 })
Text(`${this.productCount}`)
.borderRadius(10)
.width(15)
.height(15)
.backgroundColor("#ea6055")
.fontSize(10)
.textAlign(TextAlign.Center)
.fontColor(Color.White)
.margin({ top: -10, right: -10 })
}
Text($r('app.string.shopping_cart'))
.fontColor($r('app.color.blank'))
.fontSize(10)
@ -57,10 +76,10 @@ export struct BottomNavigation {
}
.width(74)
.onClick(() => {
AppStorage.SetOrCreate('nowIndex',2)
router.push({
AppStorage.setOrCreate('nowIndex', 2)
router.pushUrl({
url: 'pages/Home'
})
});
})
}
.justifyContent(this.curBp === 'sm' ? FlexAlign.SpaceEvenly : FlexAlign.Start)
@ -74,8 +93,44 @@ export struct BottomNavigation {
}
.alignItems(VerticalAlign.Center)
.padding({ left: 20, right: 20 })
.onClick(()=>{
this.emitterClass.addGoods(this.goodItemData.id)
.onClick(() => {
// 添加商品到购物车
this.emitterClass.addGoods(this.goodItemData.id);
// this.emitterClass.shoppingCartGoodsList
// 准备显示动画
this.animateAppear = !this.animateAppear;
// 用0.5秒实现动画缩小曲线使用EaseOut特点是开始快结束慢
animateTo({ duration: 500, curve: Curve.EaseOut,
onFinish: () => {
// 用1秒实现动画曲线曲线使用EaseIn特点是开始慢结束快
animateTo({ duration: 1000, curve: Curve.EaseIn,
onFinish: () => {
// 动画结束,将参数复原,及时移除动画视图
this.animateAppear = !this.animateAppear;
this.animatePath = !this.animatePath;
this.animateScale = !this.animateScale;
// 设置弹簧动画初始速度100质量1刚度225阻尼10
// 建议从初始速度0质量1刚度225阻尼30开始调参这是临届阻尼的参数
// 如果觉得曲线一开始太慢了,可以把初速度加大
this.animateSpring = !this.animateSpring;
// interpolatingSpring的参数需要调试通过调试找到自己想要的效果
animateTo({ duration: 1, curve: curves.interpolatingSpring(100, 1, 225, 10), iterations: 1 }, () => {
// 开始弹簧动画
this.animateSpring = !this.animateSpring;
// 更改数字
this.productCount = this.productCount + 1;
})
} }, () => {
// 开始路径动画
this.animatePath = !this.animatePath;
})
} }, () => {
// 开始缩小动画
this.animateScale = !this.animateScale;
})
})
Row() {
@ -97,4 +152,5 @@ export struct BottomNavigation {
.height(56)
.backgroundColor($r('app.color.divider'))
}
}
}

View File

@ -24,7 +24,6 @@ export struct EventsDialog {
.objectFit(ImageFit.Contain)
.height(300)
.aspectRatio(1.5)
Column() {
Text($r('app.string.shopping'))
.fontSize(24)
@ -50,7 +49,7 @@ export struct EventsDialog {
.backgroundColor('rgba(0,0,0,0.3)')
.borderRadius('18vp')
.onClick(() => {
this.customDialogController.close()
this.customDialogController.close();
})
}
.backgroundColor('#F1F3F5')

View File

@ -13,31 +13,31 @@
* limitations under the License.
*/
import router from '@ohos.router'
import prompt from '@ohos.promptAction'
import workScheduler from '@ohos.resourceschedule.workScheduler'
import { logger } from '../utils/Logger'
import { ButtonDialogBuilder } from '@ohos/sharecomponent'
import router from '@ohos.router';
import prompt from '@ohos.promptAction';
import workScheduler from '@ohos.resourceschedule.workScheduler';
import { logger } from '../utils/Logger';
import { ButtonDialogBuilder } from '@ohos/sharecomponent';
const SRC_IMG = 'https://res5.vmallres.com/pimages/uomcdn/CN/pms/202207/gbom/6941487270880/428_428_1142FAB7EA4DCBDD8C64BF54486A7D4Bmp.png'
const TAG: string = 'Information'
const SRC_IMG: string = 'https://res5.vmallres.com/pimages/uomcdn/CN/pms/202207/gbom/6941487270880/428_428_1142FAB7EA4DCBDD8C64BF54486A7D4Bmp.png';
const TAG: string = 'Information';
@Component
export struct Information {
@State collected: boolean = false
private data: any[] = router.getParams()['goodItem']
@State recommend: string = ''
@State commodity: string = ''
@State collected: boolean = false;
private data: any[] = router.getParams()['goodItem'];
@State recommend: string = '';
@State commodity: string = '';
aboutToAppear() {
let context: Context = getContext(this)
this.recommend = context.resourceManager.getStringSync($r('app.string.recommend').id)
this.commodity = context.resourceManager.getStringSync($r('app.string.commodity').id)
let context: Context = getContext(this);
this.recommend = context.resourceManager.getStringSync($r('app.string.recommend').id);
this.commodity = context.resourceManager.getStringSync($r('app.string.commodity').id);
}
// 分享弹框
controller: TabsController = new TabsController()
shareDialog: CustomDialogController
controller: TabsController = new TabsController();
shareDialog: CustomDialogController;
build() {
Column() {
@ -77,7 +77,7 @@ export struct Information {
alignment: DialogAlignment.Bottom,
customStyle: true,
})
this.shareDialog.open()
this.shareDialog.open();
})
Row() {
@ -91,7 +91,7 @@ export struct Information {
}
.opacity(0.6)
.onClick(() => {
this.collected = !this.collected
this.collected = !this.collected;
})
Row({ space: 6 }) {
@ -116,12 +116,12 @@ export struct Information {
firstButton: getContext(this).resourceManager.getStringSync($r('app.string.close')),
secondButton: getContext(this).resourceManager.getStringSync($r('app.string.go_to_view'))
}
}
};
try {
workScheduler.startWork(workInfo)
prompt.showToast({ message: $r('app.string.subscribe_notice') })
workScheduler.startWork(workInfo);
prompt.showToast({ message: $r('app.string.subscribe_notice') });
} catch (error) {
logger.info(TAG, `startWork error ${JSON.stringify(error)}`)
logger.info(TAG, `startWork error ${JSON.stringify(error)}`);
}
})
}

View File

@ -13,17 +13,18 @@
* limitations under the License.
*/
import { CITY_DATA, HOT_CITY, TAB_VALUE } from '../mock/DetailData'
import { CITY_DATA, HOT_CITY, TAB_VALUE } from '../mock/DetailData';
@Component
export struct Location {
@Link isPanel: boolean
private scroller: Scroller = new Scroller()
@State stabIndex: number = 0
@State location: boolean = true
@Link currentLocation: string
@Link isPanel: boolean;
private scroller: Scroller = new Scroller();
@State stabIndex: number = 0;
@State location: boolean = true;
@Link currentLocation: string;
@Builder cityList(city: any) {
@Builder
cityList(city: any) {
if (this.currentLocation === city.name) {
List() {
ForEach(city.city, twoCity => {
@ -34,7 +35,7 @@ export struct Location {
.height(30)
.fontSize(14)
.onClick(() => {
this.currentLocation = city.name + '/' + twoCity
this.currentLocation = city.name + '/' + twoCity;
})
}
}
@ -54,7 +55,7 @@ export struct Location {
.height(6)
.margin({ top: 10 })
.onClick(() => {
this.isPanel = !this.isPanel
this.isPanel = !this.isPanel;
})
}
.width('100%')
@ -118,7 +119,7 @@ export struct Location {
.maxLines(3)
.fontColor($r('app.color.blank'))
.onClick(() => {
this.currentLocation = item
this.currentLocation = item;
})
})
}
@ -141,9 +142,9 @@ export struct Location {
.width('100%')
.onClick(() => {
if (item.name === undefined) {
this.currentLocation = item
this.currentLocation = item;
} else {
this.currentLocation = item.name
this.currentLocation = item.name;
}
})
this.cityList(item)
@ -158,7 +159,7 @@ export struct Location {
.divider({ strokeWidth: 2, color: $r('app.color.divider'), startMargin: 0, endMargin: 20 })
.listDirection(Axis.Vertical)
.onScrollIndex((firstIndex: number, lastIndex: number) => {
this.stabIndex = firstIndex
this.stabIndex = firstIndex;
})
}
.alignItems(HorizontalAlign.Start)
@ -173,7 +174,7 @@ export struct Location {
.selectedFont({ size: 16, weight: FontWeight.Bolder })
.popupFont({ size: 30, weight: FontWeight.Bolder })
.alignStyle(this.location ? IndexerAlign.Right : IndexerAlign.Left)
.onSelected((tabIndex: number) => {
.onSelect((tabIndex: number) => {
this.scroller.scrollToIndex(tabIndex)
})
}

View File

@ -15,21 +15,21 @@
@Component
export struct SmallVideo {
@State smallVideoSrc: Resource = $r('app.media.videos')
@Link @Watch("onChanged") isHidden: boolean
@Link isCancel: boolean
@Consume('playTime') updateTime: number
smallVideoController: VideoController = new VideoController()
@State smallVideoSrc: Resource = $r('app.media.videos');
@Link @Watch("onChanged") isHidden: boolean;
@Link isCancel: boolean;
@Consume('playTime') updateTime: number;
smallVideoController: VideoController = new VideoController();
onChanged(): void {
if (this.isHidden) {
this.smallVideoController.start();
this.smallVideoController.setCurrentTime(this.updateTime)
this.smallVideoController.setCurrentTime(this.updateTime);
}
}
aboutToAppear() {
this.smallVideoController.setCurrentTime(this.updateTime)
this.smallVideoController.setCurrentTime(this.updateTime);
}
build() {
@ -44,7 +44,7 @@ export struct SmallVideo {
.muted(true)
.id('smallVideo')
.onFinish(() => {
this.isHidden = false
this.isHidden = false;
})
// 视频小窗口的右上角X
@ -54,8 +54,8 @@ export struct SmallVideo {
.position({ x: '80%', y: '10%' })
.id('closeBtn')
.onClick(() => {
this.isHidden = false
this.isCancel = false
this.isHidden = false;
this.isCancel = false;
})
}
}

View File

@ -13,7 +13,7 @@
* limitations under the License.
*/
import { COMMENT_DATA } from '../mock/DetailData'
import { COMMENT_DATA } from '../mock/DetailData';
@Component
export struct Valuation {

View File

@ -12,20 +12,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import router from '@ohos.router'
import router from '@ohos.router';
@Component
export struct VideoPage {
@State videoSrc: Resource = $rawfile('video_4.mp4')
@State controls: boolean = false
@State isFull: boolean = false
@State isPause: boolean = true
@State isPlayClick: boolean = true
@State firstClick: boolean = true
@State isHidden: boolean = true
@Link isStart: boolean
@Consume('playTime') updateTime: number
detailVideoController: VideoController = new VideoController()
@State videoSrc: Resource = $rawfile('video_4.mp4');
@State controls: boolean = false;
@State isFull: boolean = false;
@State isPause: boolean = true;
@State isPlayClick: boolean = true;
@State coverUrl: string = '';
@State firstClick: boolean = true;
@State isHidden: boolean = true;
@Link isStart: boolean;
@Consume('playTime') updateTime: number;
detailVideoController: VideoController = new VideoController();
build() {
Column() {
@ -40,7 +41,7 @@ export struct VideoPage {
.controls(this.controls)
.objectFit(ImageFit.Contain)
.onUpdate((e) => {
this.updateTime = e.time
this.updateTime = e.time;
})
.onPrepared((e) => {
console.info('VideoPage_onPrepared:' + e.duration)
@ -48,26 +49,32 @@ export struct VideoPage {
.onClick(() => {
if (this.isPlayClick) { // 判断play按钮是否用过没有用过进入这层
if (this.firstClick) { // 第一次点击视频开始播放,再次点击进入全屏
this.detailVideoController.start()
this.isHidden = !this.isHidden
this.isStart = true
this.firstClick = !this.firstClick
this.detailVideoController.start();
this.isHidden = !this.isHidden;
this.isStart = true;
this.firstClick = !this.firstClick;
} else {
router.push({ url: 'pages/FullPage', params: { videoSrc: this.videoSrc, videoTime: this.updateTime } })
router.pushUrl({
url: 'pages/FullPage',
params: { videoSrc: this.videoSrc, videoTime: this.updateTime }
});
}
} else {
router.push({ url: 'pages/FullPage', params: { videoSrc: this.videoSrc, videoTime: this.updateTime } })
router.pushUrl({
url: 'pages/FullPage',
params: { videoSrc: this.videoSrc, videoTime: this.updateTime }
});
}
})
.onFinish(() => {
this.isHidden = true
this.isStart = false
this.isHidden = true;
this.isStart = false;
})
// 空白层预览
if(this.isHidden){
if (this.isHidden) {
Column() {
Image($r('app.media.preview_Img'))
Image(this.coverUrl)
.id('previewImg')
.objectFit(ImageFit.Contain)
}
@ -77,16 +84,16 @@ export struct VideoPage {
}
// 视频上的play图标
if(this.isHidden){
if (this.isHidden) {
Column() {
Image($r('app.media.play'))
.id('playBtn')
.width(76).height(76)
.onClick(() => {
this.detailVideoController.start()
this.isHidden = !this.isHidden
this.isStart = true
this.isPlayClick = false
this.detailVideoController.start();
this.isHidden = !this.isHidden;
this.isStart = true;
this.isPlayClick = false;
})
}
}

View File

@ -13,191 +13,239 @@
* limitations under the License.
*/
import router from '@ohos.router'
import { Location } from '../components/Location'
import { Information } from '../components/Information'
import { Choice } from '../components/Choice'
import { AddressService } from '../components/AddressService'
import { Valuation } from '../components/Valuation'
import { BottomNavigation } from '../components/BottomNavigation'
import { VideoPage } from '../components/VideoPage'
import { SmallVideo } from '../components/SmallVideo'
import { SWIPER_PICTURE_DATA } from '../mock/DetailData'
import { ButtonDialogBuilder } from '@ohos/sharecomponent'
import router from '@ohos.router';
import { Location } from '../components/Location';
import { Information } from '../components/Information';
import { Choice } from '../components/Choice';
import { AddressService } from '../components/AddressService';
import { Valuation } from '../components/Valuation';
import { BottomNavigation } from '../components/BottomNavigation';
import { VideoPage } from '../components/VideoPage';
import { SmallVideo } from '../components/SmallVideo';
import { SWIPER_PICTURE_DATA } from '../mock/DetailData';
import { ButtonDialogBuilder } from '@ohos/sharecomponent';
const SRC_IMG = 'https://res5.vmallres.com/pimages/uomcdn/CN/pms/202207/gbom/6941487270880/428_428_1142FAB7EA4DCBDD8C64BF54486A7D4Bmp.png'
const SRC_IMG: string = 'https://res5.vmallres.com/pimages/uomcdn/CN/pms/202207/gbom/6941487270880/428_428_1142FAB7EA4DCBDD8C64BF54486A7D4Bmp.png';
@Component
export struct DetailPage {
@State sOpacity: number = 1
@State isPanel: boolean = false
@State goodDetailData: any[] = router.getParams()['goodItem']
@State currentLocation: string = ''
@State recommend: string = ''
@State commodity: string = ''
@State swiperIndex: number = 0
@State sOpacity: number = 1;
@State isPanel: boolean = false;
@State goodDetailData: any[] = router.getParams()['goodItem'];
@State currentLocation: string = '';
@State recommend: string = '';
@State commodity: string = '';
@State swiperIndex: number = 0;
// Video组件
@State isHidden: boolean = false
@State isState: boolean = true
@State isCancel: boolean = true
@State activeVideo: number = 0
@State openFirst: boolean = false
@Provide('playTime') playNum: number = 20
@StorageProp('curBp') curBp: string = 'md'
private shareDialog: CustomDialogController
private scroller: Scroller = new Scroller()
@State isHidden: boolean = false;
@State isState: boolean = true;
@State isCancel: boolean = true;
@State activeVideo: number = 0;
@State openFirst: boolean = false;
@Provide('playTime') playNum: number = 20;
@StorageProp('curBp') curBp: string = 'md';
private shareDialog: CustomDialogController;
private scroller: Scroller = new Scroller();
@State isShowImage: boolean = true;
@State animateAppear: boolean = false;
@State animateScale: boolean = false;
@State animatePath: boolean = false;
build() {
Stack() {
Scroll(this.scroller) {
Column({ space: 12 }) {
Stack({ alignContent: Alignment.BottomEnd }) {
Swiper() {
VideoPage({ isStart: $openFirst })
.id('VideoPage')
ForEach(SWIPER_PICTURE_DATA, item => {
Column() {
Image(this.goodDetailData['uri'])
.width('100%')
.aspectRatio(1)
}
.width('100%')
Stack({ alignContent: Alignment.Top }) {
Stack() {
Scroll(this.scroller) {
Column({ space: 12 }) {
Stack({ alignContent: Alignment.BottomEnd }) {
Swiper() {
VideoPage({ isStart: $openFirst, coverUrl: this.goodDetailData['uri'] })
.id('VideoPage')
ForEach(SWIPER_PICTURE_DATA, () => {
Column() {
Image(this.goodDetailData['uri'])
.objectFit(ImageFit.Contain)
}
.aspectRatio(1.12)
.backgroundColor('#ffffff')
.width('100%')
})
}
.height(300)
.index(this.swiperIndex)
.indicator(false)
.onChange((index: number) => {
this.swiperIndex = index;
})
Row() {
Text(`${this.swiperIndex + 1}/${SWIPER_PICTURE_DATA.length + 1}`)
.fontSize(12)
.fontColor($r('app.color.white'))
}
.width(46)
.height(24)
.borderRadius(12)
.justifyContent(FlexAlign.Center)
.backgroundColor($r('app.color.bg3'))
.margin({ right: 16, bottom: 16 })
}
.width('100%')
.height(300)
.index(this.swiperIndex)
.indicator(false)
.onChange((index: number) => {
this.swiperIndex = index
})
.backgroundColor($r('app.color.white'))
Row() {
Text(`${this.swiperIndex + 1}/${SWIPER_PICTURE_DATA.length + 1}`)
.fontSize(12)
.fontColor($r('app.color.white'))
Column() {
Information()
.margin({ top: 12 })
Choice()
.margin({ top: 12 })
AddressService({ currentLocation: $currentLocation, isPanel: $isPanel })
.margin({ top: 12 })
Valuation()
.margin({ top: 12 })
}
.width(46)
.height(24)
.borderRadius(12)
.justifyContent(FlexAlign.Center)
.backgroundColor($r('app.color.bg3'))
.margin({ right: 16, bottom: 16 })
.padding({ left: 12, right: 12 })
}
.id('goodsDetail' + this.goodDetailData['id'])
.width('100%')
.height(300)
.backgroundColor($r('app.color.white'))
Column() {
Information()
.margin({ top: 12 })
Choice()
.margin({ top: 12 })
AddressService({ currentLocation: $currentLocation, isPanel: $isPanel })
.margin({ top: 12 })
Valuation()
.margin({ top: 12 })
}
.padding({ left: 12, right: 12 })
}
.id('goodsDetail' + this.goodDetailData['id'])
.width('100%')
}
.width('100%')
.align(Alignment.Top)
.scrollBar(BarState.Off)
.padding({ bottom: this.curBp === 'sm' ? 86 : 106 })
.onScroll(() => {
if (this.activeVideo === 0 && this.openFirst) {
if (this.scroller.currentOffset().yOffset > 450) {
if (this.isState) {
this.isHidden = true
this.isState = false
.align(Alignment.Top)
.scrollBar(BarState.Off)
.padding({ bottom: this.curBp === 'sm' ? 86 : 106 })
.onScroll(() => {
if (this.activeVideo === 0 && this.openFirst) {
if (this.scroller.currentOffset().yOffset > 450) {
if (this.isState) {
this.isHidden = true;
this.isState = false;
}
} else {
this.isHidden = false;
this.isState = true;
}
} else {
this.isHidden = false
this.isState = true
}
}
})
Image($r('app.media.back'))
.width(32)
.aspectRatio(1)
.position({ x: 20, y: 20 })
.onClick(() => {
router.back()
})
Image($r("app.media.share"))
.width(32)
.aspectRatio(1)
.position({ x: '100%', y: 20 })
.translate({ x: -62, y: 0 })
.onClick(() => {
this.shareDialog = new CustomDialogController({
builder: ButtonDialogBuilder({
controller: this.shareDialog,
detailTitleText: this.recommend,
detailPriceText: '9800',
title: this.commodity,
srcImage: SRC_IMG
}),
cancel: undefined,
autoCancel: true,
alignment: DialogAlignment.Bottom,
customStyle: true
})
this.shareDialog.open()
})
Column({ space: 12 }) {
Image($r('app.media.broadcast'))
Image($r('app.media.back'))
.width(32)
.height(32)
.aspectRatio(1)
.position({ x: 20, y: 20 })
.onClick(() => {
router.back();
})
Text($r('app.string.broadcast'))
.fontSize(14)
.fontColor($r('app.color.blank'))
}
.id('directVideo')
.width(62)
.height(78)
.borderWidth(0.5)
.borderColor($r('app.color.border'))
.borderRadius(16)
.padding(6)
.backgroundColor($r('app.color.light_white'))
.position({ x: '100%', y: 160 })
.translate({ x: -82, y: 0 })
.onClick(() => {
router.push({ url: 'pages/LivePage' })
})
Image($r("app.media.share"))
.width(32)
.aspectRatio(1)
.position({ x: '100%', y: 20 })
.translate({ x: -62, y: 0 })
.onClick(() => {
this.shareDialog = new CustomDialogController({
builder: ButtonDialogBuilder({
controller: this.shareDialog,
detailTitleText: this.recommend,
detailPriceText: '9800',
title: this.commodity,
srcImage: SRC_IMG
}),
cancel: undefined,
autoCancel: true,
alignment: DialogAlignment.Bottom,
customStyle: true
})
this.shareDialog.open()
})
BottomNavigation({ goodItemData: $goodDetailData })
.position({ x: 0, y: '100%' })
.translate({ x: 0, y: -56 })
SmallVideo({ isHidden: $isHidden, isCancel: $isCancel })
.position({ x: '100%', y: '60%' })
.translate({ x: -180, y: 0 })
Panel(this.isPanel) {
Location({ isPanel: $isPanel, currentLocation: $currentLocation })
Column({ space: 12 }) {
Image($r('app.media.broadcast'))
.width(32)
.height(32)
Text($r('app.string.broadcast'))
.fontSize(14)
.fontColor($r('app.color.blank'))
}
.id('directVideo')
.width(62)
.height(78)
.borderWidth(0.5)
.borderColor($r('app.color.border'))
.borderRadius(16)
.padding(6)
.backgroundColor($r('app.color.light_white'))
.position({ x: '100%', y: 160 })
.translate({ x: -82, y: 0 })
.onClick(() => {
router.pushUrl({ url: 'pages/LivePage' });
})
BottomNavigation({
goodItemData: $goodDetailData,
animateAppear: $animateAppear,
animateScale: $animateAppear,
animatePath: $animatePath
})
.position({ x: 0, y: '100%' })
.translate({ x: 0, y: -56 })
SmallVideo({ isHidden: $isHidden, isCancel: $isCancel })
.position({ x: '100%', y: '60%' })
.translate({ x: -180, y: 0 })
Panel(this.isPanel) {
Location({ isPanel: $isPanel, currentLocation: $currentLocation })
}
.mode(PanelMode.Half)
.dragBar(false)
.halfHeight(this.curBp === 'sm' ? 650 : 530)
.miniHeight(0)
.onChange(() => {
this.isPanel = false
})
Column() {
Image(this.goodDetailData['uri'])
.borderRadius(this.animateScale ? 1000 : 0)
.transition(TransitionEffect.OPACITY)
}
.width('100%')
.height(300)
.enabled(this.animatePath)
.visibility(this.animateAppear ? 0 : 1)
.scale(this.animateScale ? (this.animatePath ? { x: 0.1, y: 0.1, centerY: '50%' } : {
x: 0.2,
y: 0.2,
centerY: '50%'
}) : { x: 1, y: 1, centerY: '100%' })
.opacity(this.animatePath ? 0.3 : 1)
.translate(this.animatePath ? { x: -80, y: 100 } : { x: 0 })
.motionPath({ path: 'Mstart.x start.y C -200 50, -150 200, end.x end.y', from: 0.0, to: 1.0, rotatable: false })
}
.height('100%')
.width('100%')
.backgroundColor($r('app.color.divider'))
// 通过isShowImage变量开关控制页面跳转动效默认为true
if (this.isShowImage) {
Column() {
Image(this.goodDetailData['uri'])
.objectFit(ImageFit.Contain)
.sharedTransition('goods' + this.goodDetailData['id'], { duration: 600, curve: Curve.Linear, delay: 100 })
.onComplete(() => {
setTimeout(() => {
this.isShowImage = false;
}, 800)
})
}
.width('100%')
.aspectRatio(1.12)
.backgroundColor('#ffffff')
}
.mode(PanelMode.Half)
.dragBar(false)
.halfHeight(this.curBp === 'sm' ? 650 : 530)
.miniHeight(0)
.onChange(() => {
this.isPanel = false
})
}
.height('100%')
.width('100%')
.backgroundColor($r('app.color.divider'))
}
aboutToAppear() {
let context: Context = getContext(this)
this.currentLocation = context.resourceManager.getStringSync($r('app.string.address').id)
this.recommend = context.resourceManager.getStringSync($r('app.string.recommend').id)
this.commodity = context.resourceManager.getStringSync($r('app.string.commodity').id)
let context: Context = getContext(this);
this.currentLocation = context.resourceManager.getStringSync($r('app.string.address').id);
this.recommend = context.resourceManager.getStringSync($r('app.string.recommend').id);
this.commodity = context.resourceManager.getStringSync($r('app.string.commodity').id);
}
}

View File

@ -13,14 +13,14 @@
* limitations under the License.
*/
import { SwiperPicturesModel, CommentModel } from '../model/DetailMode'
import { SwiperPicturesModel, CommentModel } from '../model/DetailMode';
export const SWIPER_PICTURE_DATA: Array<SwiperPicturesModel> = [
{ src: $r('app.media.swiper1') },
{ src: $r('app.media.swiper2') },
{ src: $r('app.media.swiper3') },
{ src: $r('app.media.swiper4') }
]
];
export const COMMENT_DATA: Array<CommentModel> = [
{
@ -53,7 +53,7 @@ export const COMMENT_DATA: Array<CommentModel> = [
img: $r('app.media.star'),
text: '和描述相符很喜欢,做工细致,颜色好看,原装正品'
}
]
];
export const CITY_DATA = [
{ name: 'A', city: [{ name: '安徽', city: ['亳州', '安庆'] }] },
@ -71,8 +71,8 @@ export const CITY_DATA = [
{ name: 'X', city: ['西藏', '新疆'] },
{ name: 'Y', city: ['云南'] },
{ name: 'Z', city: [{ name: '浙江', city: ['宁波', '杭州'] }] }
]
];
export const HOT_CITY = ['北京', '上海', '广州', '深圳', '杭州', '南京', '苏州', '天津', '武汉', '长沙', '重庆', '成都']
export const HOT_CITY = ['北京', '上海', '广州', '深圳', '杭州', '南京', '苏州', '天津', '武汉', '长沙', '重庆', '成都'];
export const TAB_VALUE = ['A', 'B', 'C', 'F', 'G', 'H', 'J', 'L', 'N', 'Q', 'S', 'T', 'X', 'Y', 'Z']
export const TAB_VALUE = ['A', 'B', 'C', 'F', 'G', 'H', 'J', 'L', 'N', 'Q', 'S', 'T', 'X', 'Y', 'Z'];

View File

@ -15,26 +15,26 @@
export class SwiperPicturesModel {
constructor(public src: Resource) {
this.src = src
this.src = src;
}
}
export class CommentModel {
constructor(public url: Resource, public user: string, public img: Resource, public text: string) {
this.url = url
this.user = user
this.img = img
this.text = text
this.url = url;
this.user = user;
this.img = img;
this.text = text;
}
}
export class ProductDataModel {
constructor(public id: number, public uri: Resource, public title: Resource, public info: Resource, public labels: Resource, public price: Resource) {
this.id = id
this.uri = uri
this.info = info
this.title = title
this.labels = labels
this.price = price
this.id = id;
this.uri = uri;
this.info = info;
this.title = title;
this.labels = labels;
this.price = price;
}
}

View File

@ -13,33 +13,33 @@
* limitations under the License.
*/
import hilog from '@ohos.hilog'
import hilog from '@ohos.hilog';
class Logger {
private domain: number
private prefix: string
private format: string = '%{public}s, %{public}s'
private domain: number;
private prefix: string;
private format: string = '%{public}s, %{public}s';
constructor(prefix: string) {
this.prefix = prefix
this.domain = 0xFF00
this.format.toUpperCase()
this.prefix = prefix;
this.domain = 0xFF00;
this.format.toUpperCase();
}
debug(...args: any[]) {
hilog.debug(this.domain, this.prefix, this.format, args)
hilog.debug(this.domain, this.prefix, this.format, args);
}
info(...args: any[]) {
hilog.info(this.domain, this.prefix, this.format, args)
hilog.info(this.domain, this.prefix, this.format, args);
}
warn(...args: any[]) {
hilog.warn(this.domain, this.prefix, this.format, args)
hilog.warn(this.domain, this.prefix, this.format, args);
}
error(...args: any[]) {
hilog.error(this.domain, this.prefix, this.format, args)
hilog.error(this.domain, this.prefix, this.format, args);
}
}

View File

@ -14,6 +14,6 @@
*/
export class EmitterConst {
static readonly DIALOG_EVENT_ID = 1001
static readonly ADD_EVENT_ID = 1025
static readonly DIALOG_EVENT_ID: number = 1001;
static readonly ADD_EVENT_ID: number = 1025;
}

View File

@ -13,50 +13,60 @@
* limitations under the License.
*/
import emitter from '@ohos.events.emitter'
import { EmitterConst } from '../../common/EmitterConst'
import emitter from '@ohos.events.emitter';
import { EmitterConst } from '../../common/EmitterConst';
class EventsId {
eventId: number;
constructor(eventId: number) {
this.eventId = eventId;
}
}
class EventsData {
data: Data;
constructor(data: Data) {
this.data = data;
}
}
class Data {
id: number
constructor(id: number) {
this.id = id;
}
}
export class EmitterClass {
shoppingCartGoodsList: { data: { id: number } }[] = []
shoppingCartGoodsList: EventsData[] = [];
// 单次订阅回调
public showEventsDialog(callback) {
let dialogShowEventsId = {
eventId: EmitterConst.DIALOG_EVENT_ID
}
let dialogShowEventsData = {
data: {
id: EmitterConst.DIALOG_EVENT_ID
}
}
public showEventsDialog(callback: () => void): void {
let dialogShowEventsId: EventsId = new EventsId(EmitterConst.DIALOG_EVENT_ID);
let dialogShowEventsData: EventsData = new EventsData(new Data(EmitterConst.DIALOG_EVENT_ID));
// 单次订阅事件--广告
emitter.once(dialogShowEventsId, callback)
emitter.once(dialogShowEventsId, callback);
// 事件发布
emitter.emit(dialogShowEventsId, dialogShowEventsData)
emitter.emit(dialogShowEventsId, dialogShowEventsData);
}
// 持久化订阅的事件回调
public setShoppingCartGoodsList(callback: (eventData) => void) {
let addGoodDataId = {
eventId: EmitterConst.ADD_EVENT_ID
}
public setShoppingCartGoodsList(callback): void {
let addGoodDataId: EventsId = new EventsId(EmitterConst.ADD_EVENT_ID);
// 以持久化方式订阅购物车添加事件并接收事件回调
emitter.off(EmitterConst.ADD_EVENT_ID)
emitter.on(addGoodDataId, (eventData) => {
callback(eventData)
})
emitter.off(EmitterConst.ADD_EVENT_ID);
emitter.on(addGoodDataId, (eventData: EventsData) => {
callback(eventData);
});
}
public addGoods(goodId) {
let addToShoppingCartId = {
eventId: EmitterConst.ADD_EVENT_ID
}
let shoppingCartData = {
data: {
id: goodId
}
}
public addGoods(goodId: number): void {
let addToShoppingCartId: EventsId = new EventsId(EmitterConst.ADD_EVENT_ID);
let shoppingCartData: EventsData = new EventsData(new Data(goodId));
// 持续订阅发布事件
emitter.emit(addToShoppingCartId, shoppingCartData)
emitter.emit(addToShoppingCartId, shoppingCartData);
}
}

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export class EmitterConst {
static readonly DIALOG_EVENT_ID: number = 1001;
static readonly ADD_EVENT_ID: number = 1025;
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import emitter from '@ohos.events.emitter';
import { EmitterConst } from '../../common/EmitterConst';
class EventsId {
eventId: number;
constructor(eventId: number) {
this.eventId = eventId;
}
}
class EventsData {
data: Data;
constructor(data: Data) {
this.data = data;
}
}
class Data {
id: number
constructor(id: number) {
this.id = id;
}
}
export class EmitterClass {
shoppingCartGoodsList: EventsData[] = [];
// 单次订阅回调
public showEventsDialog(callback: () => void): void {
let dialogShowEventsId: EventsId = new EventsId(EmitterConst.DIALOG_EVENT_ID);
let dialogShowEventsData: EventsData = new EventsData(new Data(EmitterConst.DIALOG_EVENT_ID));
// 单次订阅事件--广告
emitter.once(dialogShowEventsId, callback);
// 事件发布
emitter.emit(dialogShowEventsId, dialogShowEventsData);
}
// 持久化订阅的事件回调
public setShoppingCartGoodsList(callback): void {
let addGoodDataId: EventsId = new EventsId(EmitterConst.ADD_EVENT_ID);
// 以持久化方式订阅购物车添加事件并接收事件回调
emitter.off(EmitterConst.ADD_EVENT_ID);
emitter.on(addGoodDataId, (eventData: EventsData) => {
callback(eventData);
});
}
public addGoods(goodId: number): void {
let addToShoppingCartId: EventsId = new EventsId(EmitterConst.ADD_EVENT_ID);
let shoppingCartData: EventsData = new EventsData(new Data(goodId));
// 持续订阅发布事件
emitter.emit(addToShoppingCartId, shoppingCartData);
}
}

View File

@ -13,42 +13,57 @@
* limitations under the License.
*/
import router from '@ohos.router'
import Http from '@ohos/http'
import { PRODUCT_DATA } from '../../mock/ProductsData'
import { GoodResponse } from '../../model/GoodsModel'
import { Products_Data } from '../../mock/ProductsData'
import Http from '@ohos/http';
import { PRODUCT_DATA } from '../../mock/ProductsData';
import { GoodResponse } from '../../model/GoodsModel';
import { Products_Data } from '../../mock/ProductsData';
import router from '@ohos.router';
@Component
export struct GoodsList {
@State getDataFromHttp: boolean = false
private url: string
private option: object
@State productsData: GoodResponse = Products_Data
@State getDataFromHttp: boolean = false;
private url: string;
private option: object;
@State productsData: GoodResponse = Products_Data;
@State active: boolean = false;
async aboutToAppear() {
Http.setUrl(this.url)
Http.setOptions(this.option)
this.getDataFromHttp = false
let info = await Http.request()
Http.setUrl(this.url);
Http.setOptions(this.option);
this.getDataFromHttp = false;
let info = await Http.request();
if (info.responseCode === 200 && info.result !== undefined) {
this.getDataFromHttp = true
this.productsData = JSON.parse(info.result.toString())
this.getDataFromHttp = true;
this.productsData = JSON.parse(info.result.toString());
}
}
build() {
GridRow({ gutter: { x: vp2px(8), y: vp2px(8) }, }) {
GridRow({
gutter: {
x: vp2px(8),
y: vp2px(8)
},
}) {
ForEach(this.getDataFromHttp ? this.productsData.data.records : PRODUCT_DATA, item => {
GridCol({ span: { sm: 6, md: 6, lg: 4 } }) {
GridCol({
span: {
sm: 6,
md: 6,
lg: 4
}
}) {
Column() {
// 此处的商品图片需要根据父组件的宽度而变化这里使用65%
// 方案二使用router跳转页面配合共享元素动画
Image(item.uri)
.id('goods' + item.id)
.width('70%')
.aspectRatio(1)
.clip(true)
.objectFit(ImageFit.Contain)
.margin({ bottom: 12 })
.sharedTransition('goods' + item.id, { duration: 600, curve: Curve.Linear, delay: 100 })
Column() {
Text(item.title)
@ -57,14 +72,21 @@ export struct GoodsList {
Text(item.info)
.width('100%')
.fontSize(14)
.margin({ top: 6 })
.fontSize(12)
.fontColor("#858184")
.margin({
top: 6
})
Text(item.price)
.fontColor($r('app.color.pink'))
.fontSize(16)
.margin({ top: 6 })
.offset({ x: -3 }) // 因为¥是中文字符上面的xx是中文字符占的宽度不一样所以需要对齐添加offset
.margin({
top: 6
})
.offset({
x: -3
}) // 因为¥是中文字符上面的xx是中文字符占的宽度不一样所以需要对齐添加offset
Column() {
Text(item.labels)
@ -72,17 +94,27 @@ export struct GoodsList {
.fontColor($r('app.color.white'))
}
.borderRadius(6)
.padding({ left: 6, right: 6, top: 4, bottom: 4 })
.padding({
left: 6,
right: 6,
top: 4,
bottom: 4
})
.backgroundColor($r('app.color.pink'))
.margin({ top: 6 })
.margin({
top: 6
})
}
.alignItems(HorizontalAlign.Start)
}
.borderRadius(10)
.padding(12)
.backgroundColor($r('app.color.white'))
// 方案二使用正常router跳转配合共享元素动画
.onClick(() => {
router.push({
this.active = true;
router.pushUrl({
url: 'pages/Detail',
params: { goodId: item.id, goodItem: item }
})
@ -90,9 +122,12 @@ export struct GoodsList {
}
}, item => item.id.toString())
}
.padding({ left: 12, right: 12 })
.onAreaChange((oldArea: Area, newArea: Area) => {
AppStorage.SetOrCreate('listHeight', newArea.height as number)
.padding({
left: 12,
right: 12
})
.onAreaChange((newArea: Area) => {
AppStorage.setOrCreate('listHeight', newArea.height as number);
})
}
}
}

View File

@ -12,26 +12,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TITLE_BAR_DATA } from '../../mock/ProductsData'
import { GoodsList } from '../good/GoodsList'
import { SwiperComponent } from './Swiper'
import { Url } from '../../main/NavigationHomePage';
import { TITLE_BAR_DATA } from '../../mock/ProductsData';
import { TitleBarModel } from '../../model/GoodsModel';
import { GoodsList } from '../good/GoodsList';
import { SwiperComponent } from './Swiper';
@Component
export struct HomePageContent {
@State tabsIndex: number = 0
private url: string
private controller: TabsController = new TabsController()
@StorageLink('listHeight') listHeight: number = 100
@StorageLink('curBp') curBp: string = 'sm'
@State tabsIndex: number = 0;
private url: string;
private controller: TabsController = new TabsController();
@StorageLink('listHeight') listHeight: number = 100;
@StorageLink('curBp') curBp: string = 'sm';
build() {
Column() {
SwiperComponent()
.width('100%')
Row() {
ForEach(TITLE_BAR_DATA, item => {
Column({ space: 6 }) {
ForEach(TITLE_BAR_DATA, (item: TitleBarModel) => {
Column({
space: 6
}) {
Text(item.title)
.fontSize(16)
.fontWeight(400)
@ -43,31 +46,36 @@ export struct HomePageContent {
.fontColor(this.tabsIndex === item.id ? $r('app.color.pink') : Color.Black)
}
.onClick(() => {
this.tabsIndex = item.id
this.controller.changeIndex(item.id)
this.tabsIndex = item.id;
this.controller.changeIndex(item.id);
})
}, item => item.id.toString())
}, (item: TitleBarModel) => item.id.toString())
}
.width('100%')
.padding({ top: 12, bottom: 12, left: 20, right: 20 })
.padding({
top: 12,
bottom: 12,
left: 20,
right: 20
})
.justifyContent(FlexAlign.SpaceBetween)
// 主页下半部分商品展示--全部、精选、新品、实惠
Tabs({ controller: this.controller }) {
TabContent() {
GoodsList({ url: this.url })
GoodsList(new Url(this.url));
}
TabContent() {
GoodsList({ url: this.url })
GoodsList(new Url(this.url));
}
TabContent() {
GoodsList({ url: this.url })
GoodsList(new Url(this.url));
}
TabContent() {
GoodsList({ url: this.url })
GoodsList(new Url(this.url));
}
}
.height(this.listHeight + 12)

View File

@ -13,26 +13,31 @@
* limitations under the License.
*/
import { NAV_DATA } from '../../mock/ProductsData'
import { TitleBarComponent } from '../../components/home/TitleBar'
import { HomePageContent } from '../../components/home/HomePageContent'
import { NAV_DATA } from '../../mock/ProductsData';
import { TitleBarComponent } from '../../components/home/TitleBar';
import { HomePageContent } from '../../components/home/HomePageContent';
import { NavDataModel } from '../../model/GoodsModel';
import { Url } from '../../main/NavigationHomePage';
@Component
export struct MainPage {
@State navTabsIndex: number = 0
private url: string
private navController: TabsController = new TabsController()
@StorageProp('curBp') curBp: string = 'sm'
@State navTabsIndex: number = 0;
private url: string;
private navController: TabsController = new TabsController();
@StorageProp('curBp') curBp: string = 'sm';
build() {
Column() {
TitleBarComponent()
.backgroundImageSize({ width: '100%', height: '100%' })
.backgroundImageSize({
width: '100%',
height: '100%'
})
.backgroundImage($r('app.media.title_bar'), ImageRepeat.NoRepeat)
Scroll() {
Column() {
Row() {
ForEach(NAV_DATA, item => {
ForEach(NAV_DATA, (item: NavDataModel) => {
Row() {
Text(item.navData)
.fontSize(16)
@ -42,10 +47,10 @@ export struct MainPage {
}
.align(Alignment.Center)
.onClick(() => {
this.navTabsIndex = item.id
this.navController.changeIndex(item.id)
this.navTabsIndex = item.id;
this.navController.changeIndex(item.id);
})
}, item => item.id.toString())
}, (item: NavDataModel) => item.id.toString())
Row() {
Divider()
@ -57,24 +62,31 @@ export struct MainPage {
.width(16)
.height(16)
.objectFit(ImageFit.Contain)
.margin({ left: 4 })
.margin({
left: 4
})
Text($r('app.string.classification'))
.fontSize(16)
.opacity(0.8)
.fontColor($r('app.color.white'))
.margin({ left: 2 })
.margin({
left: 2
})
}
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding(12)
HomePageContent({ url: this.url })
HomePageContent(new Url(this.url));
}
}
.width('100%')
.height('100%')
.backgroundImageSize({ width: '100%', height: 200 })
.backgroundImageSize({
width: '100%',
height: 200
})
.backgroundImage($r('app.media.home_background'), ImageRepeat.NoRepeat)
.scrollBar(BarState.Off)
.flexGrow(1)

View File

@ -13,29 +13,36 @@
* limitations under the License.
*/
import { GoodsList } from '../good/GoodsList'
import { NEW_PRODUCT_TITLE_BAR_DATA, SWIPER_DATA } from '../../mock/ProductsData'
import { GoodsList } from '../good/GoodsList';
import { NEW_PRODUCT_TITLE_BAR_DATA, SWIPER_DATA } from '../../mock/ProductsData';
import { NewProductTitleBarModel, SwiperModel } from '../../model/GoodsModel';
import { Url } from '../../main/NavigationHomePage';
@Component
export struct NewProduct {
@State tabsIndex: number = 0
@StorageProp('curBp') curBp: string = 'md'
private url: string
private controller: TabsController = new TabsController()
@State tabsIndex: number = 0;
@StorageProp('curBp') curBp: string = 'md';
private url: string;
private controller: TabsController = new TabsController();
build() {
Column() {
Scroll() {
Column() {
Swiper() {
ForEach(SWIPER_DATA, item => {
ForEach(SWIPER_DATA, (item: SwiperModel) => {
Navigator({ target: 'pages/detail' }) {
Image(item.img)
.objectFit(ImageFit.Cover)
.width('100%')
.borderRadius({ bottomLeft: 12, bottomRight: 12, topLeft: 0, topRight: 0 })
.borderRadius({
bottomLeft: 12,
bottomRight: 12,
topLeft: 0,
topRight: 0
})
}
}, item => item.id.toString())
}, (item: SwiperModel) => item.id.toString())
}
.width('100%')
.height(186)
@ -43,10 +50,17 @@ export struct NewProduct {
.itemSpace(10)
.displayCount(this.curBp === 'sm' ? 1 : this.curBp === 'md' ? 2 : 3)
// 这里的导航点需要位于swiper的右下角此处使用right:24
.indicatorStyle({ right: 24, selectedColor: $r('app.color.point'), color: $r('app.color.point_selected') })
.indicator(
Indicator
.dot()
.selectedItemWidth(10)
.right(24)
.color($r('app.color.point_selected'))
.selectedColor($r('app.color.point'))
)
Row() {
ForEach(NEW_PRODUCT_TITLE_BAR_DATA, item => {
ForEach(NEW_PRODUCT_TITLE_BAR_DATA, (item: NewProductTitleBarModel) => {
Column() {
Text(item.title)
.fontSize(16)
@ -57,10 +71,10 @@ export struct NewProduct {
.justifyContent(FlexAlign.Center)
.align(Alignment.Center)
.onClick(() => {
this.tabsIndex = item.id
this.controller.changeIndex(item.id)
this.tabsIndex = item.id;
this.controller.changeIndex(item.id);
})
}, item => item.id.toString())
}, (item: NewProductTitleBarModel) => item.id.toString())
Row() {
Image($r('app.media.line_navclass'))
@ -71,21 +85,32 @@ export struct NewProduct {
.width(16)
.height(16)
.objectFit(ImageFit.Contain)
.margin({ left: 4 })
.margin({
left: 4
})
Text($r('app.string.classification'))
.fontSize(16)
.opacity(0.6)
.fontColor($r('app.color.blank'))
.margin({ left: 2 })
.margin({
left: 2
})
}
}
.width('100%')
.padding({ left: 12, right: 12, bottom: 16, top: 16 })
.padding({
left: 12,
right: 12,
bottom: 16,
top: 16
})
.justifyContent(FlexAlign.SpaceBetween)
GoodsList({ url: this.url })
GoodsList(new Url(this.url));
}
.padding({ bottom: 12 })
.padding({
bottom: 12
})
}
.layoutWeight(1)
.scrollBar(BarState.Off)

View File

@ -13,16 +13,17 @@
* limitations under the License.
*/
import { Cart } from '../shoppingCart/Cart'
import { FavorGoodList } from '../shoppingCart/FavorGoodlist'
import { ProductDataModel } from '../../model/GoodsModel'
import { Cart } from '../shoppingCart/Cart';
import { FavorGoodList } from '../shoppingCart/FavorGoodlist';
import { ProductDataModel } from '../../model/GoodsModel';
import { Url } from '../../main/NavigationHomePage';
@Preview
@Component
export struct ShopCart {
private url: string
@StorageLink('goodsListHeight') goodsListHeight: number = 100
@State shoppingCartGoodsList: ProductDataModel[] = AppStorage.Get('shoppingCartGoodsList')
private url: string;
@StorageLink('goodsListHeight') goodsListHeight: number = 100;
@State shoppingCartGoodsList: ProductDataModel[] = AppStorage.get('shoppingCartGoodsList');
build() {
Column() {
@ -43,25 +44,39 @@ export struct ShopCart {
.opacity(0.6)
}
.width('100%')
.margin({ top: 16, bottom: 12 })
.margin({
top: 16,
bottom: 12
})
Cart({ shoppingCartGoodsListToCart: $shoppingCartGoodsList })
Cart({ shoppingCartGoodsListToCart: $shoppingCartGoodsList });
}
.width('100%')
.padding({ right: 12 })
.padding({
right: 12
})
.backgroundColor($r('app.color.divider'))
Text($r('app.string.guess_you_like'))
.fontSize(20)
.fontColor($r('app.color.blank'))
.padding({ top: 24, bottom: 20, left: 12 })
FavorGoodList({ url: this.url })
.padding({
top: 24,
bottom: 20,
left: 12
})
FavorGoodList(new Url(this.url));
}
.padding({ bottom: 12 })
.padding({
bottom: 12
})
.alignItems(HorizontalAlign.Start)
}
.layoutWeight(1)
.padding({ left: 12, right: 12 })
.padding({
left: 12,
right: 12
})
.scrollBar(BarState.Off)
.align(Alignment.Top)

View File

@ -13,30 +13,124 @@
* limitations under the License.
*/
import { INDEX_DATA } from '../../mock/ProductsData'
import { INDEX_DATA } from '../../mock/ProductsData';
import { SwiperModel } from '../../model/GoodsModel';
const isNewSlide: boolean = true;
@Component
export struct SwiperComponent {
@StorageProp('curBp') curBp: string = 'md'
@StorageProp('curBp') curBp: string = 'md';
@State currentIndex: number = 2;
build() {
Swiper() {
ForEach(INDEX_DATA, item => {
Image(item.img)
.objectFit(ImageFit.Cover)
.width('100%')
.height('100%')
.borderRadius(16)
})
/**
* Get the image offset coefficients.
*
* @param index
* @returns offset coefficients
*/
getImgCoefficients(index: number): number {
let coefficient: number = this.currentIndex - index;
let tempCoefficient: number = Math.abs(coefficient);
if (tempCoefficient <= 2) {
return coefficient;
}
.padding({ left: 12, right: 12 })
.height(170)
.autoPlay(true)
.itemSpace(20)
.displayCount(this.curBp === 'sm' ? 1 : this.curBp === 'md' ? 2 : 3)
.indicatorStyle({
selectedColor: $r('app.color.red'),
color: $r('app.color.white')
let dataLength: number = INDEX_DATA.length;
let tempOffset: number = dataLength - tempCoefficient;
if (tempOffset <= 2) {
if (coefficient > 0) {
return -tempOffset;
}
return tempOffset;
}
return 0;
}
/**
* Get the image offset.
*
* @param index
* @returns offset
*/
getOffSetX(index: number): number {
let offsetIndex: number = this.getImgCoefficients(index);
let tempOffset: number = Math.abs(offsetIndex);
let offsetX: number = 0;
if (tempOffset === 1) {
offsetX = -40 * offsetIndex;
}
return offsetX;
}
startAnimation(isLeft: boolean): void {
animateTo({
duration: 300,
}, () => {
let dataLength: number = INDEX_DATA.length;
let tempIndex: number = isLeft ? this.currentIndex + 1 : this.currentIndex - 1 + dataLength;
this.currentIndex = tempIndex % dataLength;
})
}
}
build() {
if (!isNewSlide) {
Swiper() {
ForEach(INDEX_DATA, (item: SwiperModel) => {
Image(item.img)
.objectFit(ImageFit.Cover)
.width('100%')
.height('100%')
.borderRadius(16)
})
}
.padding({
left: 12,
right: 12
})
.height(170)
.autoPlay(true)
.itemSpace(20)
.displayCount(this.curBp === 'sm' ? 1 : this.curBp === 'md' ? 2 : 3)
.indicator(
Indicator
.dot()
.selectedColor($r('app.color.red'))
.color($r('app.color.white'))
)
} else {
Column() {
Stack() {
ForEach(INDEX_DATA, (item: SwiperModel, index: number) => {
Row() {
Image(item.img)
.objectFit(ImageFit.Fill)
.borderRadius(8)
.aspectRatio(48 / 25)
.opacity(1 - 0.2 * Math.min(2, Math.abs(this.getImgCoefficients(index))))
}
.borderRadius(8)
.offset({
x: this.getOffSetX(index),
y: 0
})
.blur(10 * Math.abs(this.getImgCoefficients(index)))
.zIndex(index !== this.currentIndex && this.getImgCoefficients(index) === 0 ?
0 : 2 - Math.abs(this.getImgCoefficients(index)))
.height(index !== this.currentIndex && this.getImgCoefficients(index) === 0 ?
"78%" : `${100 - 14 * Math.abs(this.getImgCoefficients(index))}%`)
}, (item: SwiperModel) => JSON.stringify(item))
}
.height(157)
.alignContent(Alignment.Center)
.gesture(
PanGesture({ direction: PanDirection.Horizontal })
.onActionStart((event: GestureEvent) => {
this.startAnimation(event.offsetX < 0);
})
)
}
.width('100%')
.height('25%')
}
}
}

View File

@ -13,15 +13,19 @@
* limitations under the License.
*/
import router from '@ohos.router'
import { FIND_SEARCH_TEXT_DATA } from '../../mock/ProductsData'
import router from '@ohos.router';
import { FIND_SEARCH_TEXT_DATA } from '../../mock/ProductsData';
import { SearchTextModel } from '../../model/GoodsModel';
@Component
export struct TitleBarComponent {
build() {
Column() {
Flex({ justifyContent: FlexAlign.SpaceAround, alignItems: ItemAlign.Center, wrap: FlexWrap.Wrap }) {
Flex({
justifyContent: FlexAlign.SpaceAround,
alignItems: ItemAlign.Center,
wrap: FlexWrap.Wrap
}) {
Row() {
Image($r('app.media.logo'))
.width(24)
@ -32,9 +36,9 @@ export struct TitleBarComponent {
.aspectRatio(1)
.objectFit(ImageFit.Contain)
.onClick(() => {
router.push({
router.pushUrl({
url: 'pages/ScanPage'
})
});
})
}
.width('100%')
@ -46,7 +50,7 @@ export struct TitleBarComponent {
.width(20)
.aspectRatio(1)
Swiper() {
ForEach(FIND_SEARCH_TEXT_DATA, item => {
ForEach(FIND_SEARCH_TEXT_DATA, (item: SearchTextModel) => {
Column() {
Text(item.searchText)
.opacity(0.6)
@ -56,7 +60,7 @@ export struct TitleBarComponent {
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}, item => item.id.toString())
}, (item: SearchTextModel) => item.id.toString())
}
.loop(true)
.autoPlay(true)
@ -68,13 +72,28 @@ export struct TitleBarComponent {
.zIndex(2)
.width('100%')
.justifyContent(FlexAlign.Start)
.margin({ top: 8, bottom: 12 })
.padding({left: 12, right: 12})
.margin({
top: 8,
bottom: 12
})
.padding({
left: 12,
right: 12
})
.backgroundColor($r('app.color.white'))
.border({ width: 2, color: $r('app.color.white'), radius: 40 })
.border({
width: 2,
color: $r('app.color.white'),
radius: 40
})
}
.margin({ top: 12 })
.padding({ left: 12, right: 12 })
.margin({
top: 12
})
.padding({
left: 12,
right: 12
})
}
.width('100%')
}

View File

@ -13,13 +13,13 @@
* limitations under the License.
*/
import { ProductDataModel } from '../../model/GoodsModel'
import { PRODUCT_DATA } from '../../mock/ProductsData'
import { ProductDataModel } from '../../model/GoodsModel';
import { PRODUCT_DATA } from '../../mock/ProductsData';
@Component
export struct Cart {
@StorageProp('curBp') curBp: string = 'sm'
@Link shoppingCartGoodsListToCart: ProductDataModel[]
@StorageProp('curBp') curBp: string = 'sm';
@Link shoppingCartGoodsListToCart: ProductDataModel[];
build() {
Column() {
@ -33,7 +33,10 @@ export struct Cart {
.width(24)
.aspectRatio(1)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 8 })
.margin({
left: 12,
right: 8
})
Text($r('app.string.shopping_self_support'))
.fontSize(14)
.fontWeight(400)
@ -52,7 +55,10 @@ export struct Cart {
.width(70)
.height(80)
.objectFit(ImageFit.Contain)
.margin({ left: 12, right: 16 })
.margin({
left: 12,
right: 16
})
Column() {
Text(PRODUCT_DATA[item].title)
@ -64,7 +70,9 @@ export struct Cart {
.width('100%')
.fontSize(12)
.opacity(0.6)
.margin({ top: 12 })
.margin({
top: 12
})
Row() {
Text(PRODUCT_DATA[item].price)
@ -78,21 +86,30 @@ export struct Cart {
.height(24)
.objectFit(ImageFit.Contain)
Text(`${1}`)
.margin({ left: 10, right: 10 })
.margin({
left: 10,
right: 10
})
.fontSize(12)
Image($r('app.media.add'))
.width(24)
.height(24)
.objectFit(ImageFit.Contain)
}
.margin({ right: 12 })
.margin({
right: 12
})
}
.width('100%')
.margin({ top: 12 })
.margin({
top: 12
})
}
.flexGrow(1)
.flexShrink(1)
.margin({ top: 20 })
.margin({
top: 20
})
}
.width('100%')
}, item => item.toString())
@ -100,6 +117,9 @@ export struct Cart {
.width('100%')
.backgroundColor($r('app.color.white'))
.borderRadius(16)
.padding({ top: 12, bottom: 12 })
.padding({
top: 12,
bottom: 12
})
}
}

View File

@ -13,38 +13,40 @@
* limitations under the License.
*/
import emitter from '@ohos.events.emitter'
import router from '@ohos.router'
import Http from '@ohos/http'
import { GoodResponse, ShopCartItemDataModel } from '../../model/GoodsModel'
import { Products_Data, SHOP_CART_ITEM_DATA } from '../../mock/ProductsData'
import router from '@ohos.router';
import Http from '@ohos/http';
import { GoodResponse, ShopCartItemDataModel } from '../../model/GoodsModel';
import { Products_Data, SHOP_CART_ITEM_DATA } from '../../mock/ProductsData';
@Component
export struct FavorGoodList {
@State flag: boolean = false
private url: string
private option: object
@State productsData: GoodResponse = Products_Data
@State flag: boolean = false;
private url: string;
private option: object;
@State productsData: GoodResponse = Products_Data;
async aboutToAppear() {
Http.setUrl(this.url)
Http.setOptions(this.option)
this.flag = false
let info = await Http.request()
Http.setUrl(this.url);
Http.setOptions(this.option);
this.flag = false;
let info = await Http.request();
if (info.responseCode === 200) {
this.flag = true
this.productsData = JSON.parse(info.result.toString())
this.flag = true;
this.productsData = JSON.parse(info.result.toString());
}
}
@Builder GoodItem(shopItem: ShopCartItemDataModel) {
@Builder
GoodItem(shopItem: ShopCartItemDataModel) {
Column() {
// 这里的图片需要根据父组件宽度自适应此处使用70%
Image(shopItem.uri)
.width('70%')
.aspectRatio(1)
.objectFit(ImageFit.Contain)
.margin({ bottom: 12 })
.margin({
bottom: 12
})
Column() {
Text(shopItem.title)
.width('100%')
@ -52,16 +54,27 @@ export struct FavorGoodList {
Text(shopItem.price)
.fontColor($r('app.color.red'))
.fontSize(16)
.margin({ top: 6 })
.offset({ x: -3 }) // 因为¥是中文字符上面的xx是中文字符占的宽度不一样所以需要对齐添加offset
.margin({
top: 6
})
.offset({
x: -3
}) // 因为¥是中文字符上面的xx是中文字符占的宽度不一样所以需要对齐添加offset
Column() {
Text(shopItem.labels)
.fontSize(10)
.fontColor($r('app.color.white'))
}
.borderRadius(5)
.margin({ top: 6 })
.padding({ left: 6, right: 6, top: 4, bottom: 4 })
.margin({
top: 6
})
.padding({
left: 6,
right: 6,
top: 4,
bottom: 4
})
.backgroundColor($r('app.color.red'))
}
.alignItems(HorizontalAlign.Start)
@ -71,24 +84,37 @@ export struct FavorGoodList {
.padding(12)
.backgroundColor($r('app.color.white'))
.onClick(() => {
router.push({
router.pushUrl({
url: 'pages/Detail',
params: { goodId: shopItem.id, goodItem: shopItem }
params: {
goodId: shopItem.id,
goodItem: shopItem
}
})
})
}
build() {
GridRow({ gutter: { x: vp2px(8), y: vp2px(8) } }) {
GridRow({
gutter: {
x: vp2px(8),
y: vp2px(8)
}
}) {
ForEach(this.flag ? this.productsData.data.records : SHOP_CART_ITEM_DATA, item => {
GridCol({ span: { sm: 6, md: 6, lg: 4 } }) {
this.GoodItem(item)
GridCol({
span: {
sm: 6,
md: 6,
lg: 4 }
}) {
this.GoodItem(item);
}
}, item => item.id.toString())
}
.onAreaChange((oldArea: Area, newArea: Area) => {
console.info(`LSQ: newArea is ${newArea.height}`)
AppStorage.SetOrCreate('goodsListHeight', newArea.height as number)
.onAreaChange((newArea: Area) => {
console.info(`LSQ: newArea is ${newArea.height}`);
AppStorage.setOrCreate('goodsListHeight', newArea.height as number);
})
}
}

View File

@ -13,11 +13,12 @@
* limitations under the License.
*/
import { ORDER_DATA } from '../../mock/ProductsData'
import { ORDER_DATA } from '../../mock/ProductsData';
import { OrderModel } from '../../model/GoodsModel';
@Component
export struct MyOrderComponent {
@StorageProp('curBp') curBp: string = 'sm'
@StorageProp('curBp') curBp: string = 'sm';
build() {
Column() {
@ -35,29 +36,45 @@ export struct MyOrderComponent {
.objectFit(ImageFit.Contain)
}
}
.padding({ left: 12, right: 12 })
.padding({
left: 12,
right: 12
})
.width('100%')
Row() {
ForEach(ORDER_DATA, item => {
ForEach(ORDER_DATA, (item: OrderModel) => {
Column() {
Image(item.img)
.aspectRatio(1)
.width(28)
.objectFit(ImageFit.Contain)
.margin({ bottom: 12 })
.margin({
bottom: 12
})
Text(item.title)
.fontSize(12)
}
.layoutWeight(1)
}, item => item.id.toString())
}, (item: OrderModel) => item.id.toString())
}
.width('100%')
.margin({ top: 14 })
.margin({
top: 14
})
}
.padding({ left: 12, right: 12, top: 16, bottom: 16 })
.border({ radius: 16 })
.padding({
left: 12,
right: 12,
top: 16,
bottom: 16
})
.border({
radius: 16
})
.backgroundColor($r('app.color.white'))
.margin({ top: 12 })
.margin({
top: 12
})
}
}

View File

@ -15,15 +15,17 @@
@Component
export struct RewardSectionComponent {
@Builder options(img: Resource, label: Resource) {
@Builder
options(img: Resource, label: Resource) {
Column() {
Image(img)
.aspectRatio(1)
.width(40)
.objectFit(ImageFit.Contain)
Text(label)
.margin({ top: 12 })
.margin({
top: 12
})
.fontSize(12)
}
.width('25%')
@ -32,14 +34,19 @@ export struct RewardSectionComponent {
build() {
Row() {
this.options($r('app.media.vip_channel'), $r('app.string.point_reward'))
this.options($r('app.media.point_reward'), $r('app.string.interaction'))
this.options($r('app.media.interaction'), $r('app.string.interaction'))
this.options($r('app.media.card_volumn'), $r('app.string.card_volume'))
this.options($r('app.media.vip_channel'), $r('app.string.point_reward'));
this.options($r('app.media.point_reward'), $r('app.string.interaction'));
this.options($r('app.media.interaction'), $r('app.string.interaction'));
this.options($r('app.media.card_volumn'), $r('app.string.card_volume'));
}
.width('100%')
.padding({ top: 16, bottom: 16})
.padding({
top: 16,
bottom: 16
})
.backgroundColor($r('app.color.white'))
.border({ radius: 16 })
.border({
radius: 16
})
}
}

View File

@ -15,8 +15,8 @@
@Component
export struct ServiceSectionComponent {
@Builder serverSection(img: Resource, label: Resource) {
@Builder
serverSection(img: Resource, label: Resource) {
Column() {
Image(img)
.width(40)
@ -24,7 +24,9 @@ export struct ServiceSectionComponent {
.objectFit(ImageFit.Contain)
Text(label)
.fontSize(12)
.margin({ top: 12 })
.margin({
top: 12
})
}
.width('25%')
.justifyContent(FlexAlign.Center)
@ -39,8 +41,13 @@ export struct ServiceSectionComponent {
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
.padding({ top: 16, bottom: 16})
.padding({
top: 16,
bottom: 16
})
.backgroundColor($r('app.color.white'))
.border({ radius: 16 })
.border({
radius: 16
})
}
}

View File

@ -13,30 +13,49 @@
* limitations under the License.
*/
import router from '@ohos.router'
import { FAVOR_LIVE_LIST_DATA } from '../../mock/ProductsData'
import { MyOrderComponent } from '../user/MyOrders'
import { RewardSectionComponent } from '../user/RrewardSection'
import { ServiceSectionComponent } from '../user/ServiceSection'
import router from '@ohos.router';
import { FAVOR_LIVE_LIST_DATA } from '../../mock/ProductsData';
import { FavorLiveListsModel } from '../../model/GoodsModel';
import { MyOrderComponent } from '../user/MyOrders';
import { RewardSectionComponent } from '../user/RrewardSection';
import { ServiceSectionComponent } from '../user/ServiceSection';
@Component
export struct User {
@StorageProp('curBp') curBp: string = 'sm'
@StorageProp('curBp') curBp: string = 'sm';
build() {
Column() {
Scroll() {
GridRow({ columns: { sm: 4, md: 8, lg: 12 }, gutter: { x: vp2px(8), y: vp2px(12) } }) {
GridCol({ span: { sm: 4, md: 8, lg: 12 } }) {
GridRow({
columns: {
sm: 4,
md: 8,
lg: 12
},
gutter: {
x: vp2px(8),
y: vp2px(12)
}
}) {
GridCol({
span: {
sm: 4,
md: 8,
lg: 12
}
}) {
Column() {
Row() {
Image($r('app.media.setting'))
.width(24)
.aspectRatio(1)
.objectFit(ImageFit.Contain)
.margin({ right: 16 })
.margin({
right: 16
})
.onClick(() => {
router.replace({
router.replaceUrl({
url: 'pages/Setting'
})
})
@ -59,7 +78,9 @@ export struct User {
.fontSize(16)
.fontWeight(500)
.fontColor($r('app.color.white'))
.margin({ bottom: 12 })
.margin({
bottom: 12
})
Row() {
Row() {
Text($r('app.string.sign_Info'))
@ -78,33 +99,59 @@ export struct User {
.padding(4)
.borderRadius(10)
.backgroundColor($r('app.color.point_selected'))
.margin({ left: 4 })
.margin({
left: 4
})
}
}
.alignItems(HorizontalAlign.Start)
.padding({ left: 12 })
.padding({
left: 12
})
}
.width('100%')
.padding({ left: 12 })
.padding({
left: 12
})
MyOrderComponent()
MyOrderComponent();
}
}
GridCol({ span: { sm: 4, md: 4, lg: 6 } }) {
RewardSectionComponent()
GridCol({
span: {
sm: 4,
md: 4,
lg: 6
}
}) {
RewardSectionComponent();
}
GridCol({ span: { sm: 4, md: 4, lg: 6 } }) {
ServiceSectionComponent()
GridCol({
span: {
sm: 4,
md: 4,
lg: 6
}
}) {
ServiceSectionComponent();
}
GridCol({ span: { sm: 4, md: 8, lg: 12 } }) {
GridCol({
span: {
sm: 4,
md: 8,
lg: 12
}
}) {
Row() {
Text($r('app.string.often_see_live'))
.fontSize(16)
.fontWeight(500)
.margin({ left: 12 })
.margin({
left: 12
})
Blank()
Row() {
Text($r('app.string.read_more'))
@ -117,11 +164,19 @@ export struct User {
}
}
.width('100%')
.padding({ top: 4 })
.padding({
top: 4
})
}
ForEach(FAVOR_LIVE_LIST_DATA, item => {
GridCol({ span: { sm: 2, md: 4, lg: 4 } }) {
ForEach(FAVOR_LIVE_LIST_DATA, (item: FavorLiveListsModel) => {
GridCol({
span: {
sm: 2,
md: 4,
lg: 4
}
}) {
Stack({ alignContent: Alignment.TopStart }) {
Image(item.imgSrc)
.objectFit(ImageFit.Cover)
@ -133,27 +188,46 @@ export struct User {
}
.backgroundColor($r('app.color.red'))
.borderRadius(10)
.padding({ left: 6, right: 6, bottom: 2, top: 2 })
.padding({
left: 6,
right: 6,
bottom: 2,
top: 2
})
Text(item.viewsInfo)
.fontSize(10)
.fontColor($r('app.color.white'))
.margin({ left: 6 })
.margin({
left: 6
})
}
.borderRadius(10)
.padding({ right: 6 })
.padding({
right: 6
})
.backgroundColor($r('app.color.point'))
.margin({ left: 12, top: 12 })
.margin({
left: 12,
top: 12
})
}
.width('100%')
}
}, item => item.id.toString())
}, (item: FavorLiveListsModel) => item.id.toString())
}
.padding({ left: 12, right: 12, bottom: 12 })
.padding({
left: 12,
right: 12,
bottom: 12
})
}
.layoutWeight(1)
.scrollBar(BarState.Off)
.backgroundImageSize({ width: '100%', height: '25%' })
.backgroundImageSize({
width: '100%',
height: '25%'
})
.backgroundImage($r('app.media.home_mask'), ImageRepeat.NoRepeat)
Divider()

View File

@ -13,23 +13,32 @@
* limitations under the License.
*/
import { TAB_TITLE_DATA } from '../mock/ProductsData'
import { MainPage } from '../components/home/MainPage'
import { NewProduct } from '../components/home/NewProduct'
import { ShopCart } from '../components/home/ShopCart'
import { User } from '../components/user/User'
import { TAB_TITLE_DATA } from '../mock/ProductsData';
import { MainPage } from '../components/home/MainPage';
import { NewProduct } from '../components/home/NewProduct';
import { ShopCart } from '../components/home/ShopCart';
import { User } from '../components/user/User';
AppStorage.Link('isUpdateDialogOpen') || AppStorage.SetOrCreate('isUpdateDialogOpen', false)
AppStorage.link('isUpdateDialogOpen') || AppStorage.setOrCreate('isUpdateDialogOpen', false);
export class Url {
url: string;
constructor(url: string) {
this.url = url;
}
}
@Entry
@Component
export struct NavigationHomePage {
@State tabsIndex: number = AppStorage.Get('nowIndex') || 0
@StorageProp('curBp') curBp: string = 'sm'
private url: string
private controller: TabsController = new TabsController()
@State tabsIndex: number = AppStorage.get('nowIndex') || 0;
@StorageProp('curBp') curBp: string = 'sm';
private url: string;
private controller: TabsController = new TabsController();
@Builder TabBarBuilder(index: number) {
@Builder
TabBarBuilder(index: number) {
Column() {
Image(this.getTabBarImage(index))
.id('homeTab' + index)
@ -39,7 +48,9 @@ export struct NavigationHomePage {
Text(TAB_TITLE_DATA[index].title)
.fontSize(10)
.fontWeight(500)
.margin({ top: 4 })
.margin({
top: 4
})
.opacity(this.tabsIndex === index ? 1 : 0.6)
.fontWeight(this.tabsIndex === index ? 500 : 400)
.fontColor(this.tabsIndex === index ? $r('app.color.pink') : Color.Black)
@ -48,7 +59,7 @@ export struct NavigationHomePage {
.width('100%')
.height('100%')
.onClick(() => {
this.controller.changeIndex(index)
this.controller.changeIndex(index);
})
}
@ -60,20 +71,28 @@ export struct NavigationHomePage {
controller: this.controller
}) {
TabContent() {
MainPage({ url: this.url })
}.tabBar(this.TabBarBuilder(0))
MainPage(new Url(this.url));
}.tabBar(
this.TabBarBuilder(0)
)
TabContent() {
NewProduct({ url: this.url })
}.tabBar(this.TabBarBuilder(1))
NewProduct(new Url(this.url));
}.tabBar(
this.TabBarBuilder(1)
)
TabContent() {
ShopCart({ url: this.url })
}.tabBar(this.TabBarBuilder(2))
ShopCart(new Url(this.url));
}.tabBar(
this.TabBarBuilder(2)
)
TabContent() {
User()
}.tabBar(this.TabBarBuilder(3))
User();
}.tabBar(
this.TabBarBuilder(3)
)
}
.scrollable(false)
.vertical(this.curBp === 'sm' ? false : true)
@ -81,16 +100,16 @@ export struct NavigationHomePage {
.barWidth(this.curBp === 'sm' ? '100%' : 56)
.barHeight(this.curBp === 'sm' ? 56 : '100%')
.onChange((index: number) => {
this.tabsIndex = index
this.tabsIndex = index;
})
}
.backgroundColor($r('app.color.divider'))
}
getTabBarImage(index: number) {
getTabBarImage(index: number): Resource {
if (this.tabsIndex === index) {
return TAB_TITLE_DATA[index].selectedUri
return TAB_TITLE_DATA[index].selectedUri;
}
return TAB_TITLE_DATA[index].uri
return TAB_TITLE_DATA[index].uri;
}
}

View File

@ -244,129 +244,129 @@ export const PRODUCT_DATA: Array<ProductDataModel> = [
{
id: 0,
uri: $r('app.media.product001'),
title: $r('app.string.product_data_title_device'),
info: $r('app.string.product_data_title_device'),
title: $r('app.string.product_data_title_device0'),
info: $r('app.string.product_data_info_device0'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price0')
},
{
id: 1,
uri: $r('app.media.product002'),
title: $r('app.string.product_data_title_device'),
info: $r('app.string.product_data_title_device'),
title: $r('app.string.product_data_title_device1'),
info: $r('app.string.product_data_info_device1'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price1')
},
{
id: 2,
uri: $r('app.media.product003'),
title: $r('app.string.product_data_title_device'),
info: $r('app.string.product_data_title_device'),
title: $r('app.string.product_data_title_device2'),
info: $r('app.string.product_data_info_device2'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price2')
},
{
id: 3,
uri: $r('app.media.product004'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device3'),
info: $r('app.string.product_data_info_device3'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price3')
},
{
id: 4,
uri: $r('app.media.product005'),
title: $r('app.string.product_data_title_device'),
info: $r('app.string.product_data_title_device'),
title: $r('app.string.product_data_title_device4'),
info: $r('app.string.product_data_info_device4'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price4')
},
{
id: 5,
uri: $r('app.media.product006'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device5'),
info: $r('app.string.product_data_info_device5'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price5')
},
{
id: 6,
uri: $r('app.media.product007'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device5'),
info: $r('app.string.product_data_info_device5'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price5')
},
{
id: 7,
uri: $r('app.media.product008'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device7'),
info: $r('app.string.product_data_info_device7'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price7')
},
{
id: 8,
uri: $r('app.media.product001'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device0'),
info: $r('app.string.product_data_info_device0'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price0')
},
{
id: 9,
uri: $r('app.media.product002'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device1'),
info: $r('app.string.product_data_info_device1'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price1')
},
{
id: 10,
uri: $r('app.media.product003'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device2'),
info: $r('app.string.product_data_info_device2'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price2')
},
{
id: 11,
uri: $r('app.media.product004'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device3'),
info: $r('app.string.product_data_info_device3'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price3')
},
{
id: 12,
uri: $r('app.media.product005'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device4'),
info: $r('app.string.product_data_info_device4'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price4')
},
{
id: 13,
uri: $r('app.media.product006'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device5'),
info: $r('app.string.product_data_info_device5'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price5')
},
{
id: 14,
uri: $r('app.media.product007'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device5'),
info: $r('app.string.product_data_info_device5'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price5')
},
{
id: 15,
uri: $r('app.media.product008'),
title: $r('app.string.product_data_title_device'),
info: undefined,
title: $r('app.string.product_data_title_device7'),
info: $r('app.string.product_data_info_device7'),
labels: $r('app.string.product_data_labels_new_product'),
price: $r('app.string.product_data_price')
price: $r('app.string.product_data_price7')
}
]

View File

@ -212,14 +212,102 @@
"name": "product_data_title_device",
"value": "XX equipment new product discount!"
},
{
"name": "product_data_title_device4",
"value": "华为电脑包"
},
{
"name": "product_data_info_device4",
"value": "保时捷联名款 | 多层内胆"
},
{
"name": "product_data_price4",
"value": "¥699"
},
{
"name": "product_data_title_device5",
"value": "华为P50"
},
{
"name": "product_data_info_device5",
"value": "4800像素 | 120W快充"
},
{
"name": "product_data_price5",
"value": "¥6999"
},
{
"name": "product_data_title_device0",
"value": "battery"
},
{
"name": "product_data_info_device",
"value": "XX equipment new product discount!"
},
{
"name": "product_data_labels_new_product",
"value": "new"
},
{
"name": "product_data_info_device0",
"value": "20000mA USB-C18W"
},
{
"name": "product_data_title_device2",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device2",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_title_device1",
"value": "HUAWEI MateBook"
},
{
"name": "product_data_info_device1",
"value": "32GB 16英寸触屏"
},
{
"name": "product_data_title_device3",
"value": "华为按摩椅"
},
{
"name": "product_data_info_device3",
"value": "AI智能芯片 | 语音声控"
},
{
"name": "product_data_title_device7",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device7",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_price7",
"value": "¥6999"
},
{
"name": "product_data_price3",
"value": "¥8999"
},
{
"name": "product_data_price",
"value": "¥4999"
},
{
"name": "product_data_price1",
"value": "¥4122"
},
{
"name": "product_data_price0",
"value": "¥138"
},
{
"name": "product_data_price2",
"value": "¥1388"
},
{
"name": "order_data_title_obligation",
"value": "Pending payment"

View File

@ -28,6 +28,42 @@
"name": "shopping_self_support",
"value": "mall self-operated"
},
{
"name": "product_data_title_device4",
"value": "华为电脑包"
},
{
"name": "product_data_info_device4",
"value": "保时捷联名款 | 多层内胆"
},
{
"name": "product_data_price4",
"value": "¥699"
},
{
"name": "product_data_title_device7",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device7",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_price7",
"value": "¥6999"
},
{
"name": "product_data_title_device5",
"value": "华为P50"
},
{
"name": "product_data_info_device5",
"value": "4800像素 | 120W快充"
},
{
"name": "product_data_price5",
"value": "¥6999"
},
{
"name": "phone_name",
"value": "Feature Phone 5G Network Speed"
@ -212,12 +248,64 @@
"name": "product_data_title_device",
"value": "XX equipment new product discount!"
},
{
"name": "product_data_info_device0",
"value": "20000mA USB-C18W"
},
{
"name": "product_data_title_device1",
"value": "HUAWEI MateBook"
},
{
"name": "product_data_info_device1",
"value": "32GB 16英寸触屏"
},
{
"name": "product_data_title_device2",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device2",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_title_device3",
"value": "华为按摩椅"
},
{
"name": "product_data_info_device3",
"value": "AI智能芯片 | 语音声控"
},
{
"name": "product_data_price3",
"value": "¥8999"
},
{
"name": "product_data_info_device",
"value": "20000mA"
},
{
"name": "product_data_price",
"value": "¥4999"
},
{
"name": "product_data_price0",
"value": "¥138"
},
{
"name": "product_data_price2",
"value": "¥1388"
},
{
"name": "product_data_title_device0",
"value": "battery"
},
{
"name": "product_data_labels_new_product",
"value": "new"
},
{
"name": "product_data_price",
"name": "product_data_price1",
"value": "¥4122"
},
{

View File

@ -12,6 +12,42 @@
"name": "classification",
"value": "分类"
},
{
"name": "product_data_title_device4",
"value": "华为电脑包"
},
{
"name": "product_data_info_device4",
"value": "保时捷联名款 | 多层内胆"
},
{
"name": "product_data_price4",
"value": "¥699"
},
{
"name": "product_data_title_device7",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device7",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_price7",
"value": "¥6999"
},
{
"name": "product_data_title_device5",
"value": "华为P50"
},
{
"name": "product_data_info_device5",
"value": "4800像素 | 120W快充"
},
{
"name": "product_data_price5",
"value": "¥6999"
},
{
"name": "guess_you_like",
"value": "猜你喜欢"
@ -108,6 +144,10 @@
"name": "favor_live_lists_data_viewsInfo",
"value": "45.6万人观看"
},
{
"name": "product_data_price0",
"value": "¥138"
},
{
"name": "tab_title_data_home",
"value": "首页"
@ -210,16 +250,64 @@
},
{
"name": "product_data_title_device",
"value": "XX设备 新品优惠!"
"value": "xx设备 新品优惠!"
},
{
"name": "product_data_info_device",
"value": "xx设备 新品优惠!"
},
{
"name": "product_data_title_device0",
"value": "HUAWEI移动电源"
},
{
"name": "product_data_info_device0",
"value": "20000毫安 USB-C18W"
},
{
"name": "product_data_title_device1",
"value": "HUAWEI MateBook"
},
{
"name": "product_data_info_device1",
"value": "32GB 16英寸触屏"
},
{
"name": "product_data_title_device2",
"value": "华为畅享 50z"
},
{
"name": "product_data_info_device2",
"value": "高清三摄 | 超能续航"
},
{
"name": "product_data_labels_new_product",
"value": "新品"
},
{
"name": "product_data_title_device3",
"value": "华为按摩椅"
},
{
"name": "product_data_info_device3",
"value": "AI智能芯片 | 语音声控"
},
{
"name": "product_data_price3",
"value": "¥8999"
},
{
"name": "product_data_price",
"value": "¥4999"
},
{
"name": "product_data_price1",
"value": "¥4122"
},
{
"name": "product_data_price2",
"value": "¥1388"
},
{
"name": "order_data_title_obligation",
"value": "待付款"

View File

@ -1,6 +1,6 @@
{
"hvigorVersion": "2.0.0",
"hvigorVersion": "3.0.2",
"dependencies": {
"@ohos/hvigor-ohos-plugin": "2.0.0"
"@ohos/hvigor-ohos-plugin": "3.0.2"
}
}
}