Salesforce LWC 开发笔记

样式

修改input label和输入框样式

控制的样式:variant

<lightning-input type="checkbox" label="check" variant="label-stacked"></lightning-input>
  • The variant changes the appearance of an input field.
  • Accepted variants include standard, label-inline, label-hidden, and label-stacked.
  • This value defaults to standard, which displays the label above the field.
  • Use label-hidden to hide the label but make it available to assistive technology.
  • Use label-inline to horizontally align the label and input field.
  • Use label-stacked to place the label above the input field.
    增加帮助文本
field-level-help="The event name must 50 characters or less"
<lightning-input type="text" label="helptext"  field-level-help="The event name must 50 characters or less"></lightning-input>

调用apex方法

import getAllListViewName(参数名,可随意取名) from '@salesforce/apex/类名.方法名';

在方法中调用

	connectedCallback(){ //方法
		getAllListViewName({apex参数名:要传送的值}) //如果多个参数,用 , 隔开
        .then((result) => {
            for (let i = 0; i < result.length; i++) {
                let listview = new Object();
                listview.label = result[i].Name;
                listview.value = result[i].Id;
                this.listViewoptions = [...this.listViewoptions,listview];
            }
        })
        .catch((error)=>{
            console.log(error + '---getAllListViewName error-----' + JSON.stringify(error));
        })
	}

单独作为一个方法使用
注意,如果使用该方法,必须在apex方法上加上注释:、@AuraEnabled(Cacheable = true)

@wire(getAllListViewName,{apex参数名:要传送的值,参数2:值2})//如果多个参数,用 , 隔开
    getLsitViewById({ error, data }){
        if(data){

        }else if(error){

        }
    }

打开其他页面

LWC 自带跳转方法为 NavigationMixin
Navigate to Different Page Types - Salesforce Lightning Component Library

Forcetrails: Open standard record edit/view page from lwc datatable/tree grid

带参数的新建页面

	navigateToNewContactWithDefaults() {
        const defaultValues = encodeDefaultFieldValues({
            FirstName: 'Morag',
            LastName: 'de Fault',
            LeadSource: 'Other'
        });
		console.log(defaultValues);
		this[NavigationMixin.Navigate]({
            type: 'standard__objectPage',
            attributes: {
                objectApiName: 'Contact',
                actionName: 'new'
            },
            state: {
                defaultFieldValues: defaultValues
            }
        });
    }

From https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.use_navigate_default

如果想要打开页面同时刷新页面页面,可在 NavigationMixin.GenerateUrl, 然后在 then 方法中设置页面开发方式,

		this[NavigationMixin.GenerateUrl]({
            type: 'standard__recordRelationshipPage',
            attributes: {
                recordId: this.contactId,
                objectApiName: 'Contact',
                relationshipApiName: 'Cases',
                actionName: 'view'
            }
        }).then(url => {window.open(url)});

在同一个页面中打开并且刷新页面:

.then((url) => {
   window.location.href = url;
});

跳转另一个lwc页面
这会有一个问题,如果是console app,新打开的tab显示的name是loading,目前无法解决,只能通过跳转aura,然后再aura中设置tab name。

let componentDef = {
    componentDef: this.jumpPageName,
    attributes: {
        label: 'Navigated From Another LWC Without Using Aura'
    }
};
// Encode the componentDefinition JS object to Base64 format to make it url addressable
let encodedComponentDef = btoa(JSON.stringify(componentDef));
this[NavigationMixin.Navigate]({
    type: 'standard__webPage',
    attributes: {
        url: '/one/one.app#' + encodedComponentDef
    }
});

详细页面按钮获取当前页面ID

Current Record ID in LWC, Aura, and Quick Action - Niks Developer

由aura 组件传到lwc中

<aura:component implements="flexipage:availableForAllPageTypes,force:lightningQuickAction,force:hasRecordId" 
                access="global" >
	<c:actionLWC recordId="{!v.recordId}"></c:actionLWC>
</aura:component>
<template>
    <lightning-card title="Lightning Web Component">
        <div class="slds-p-around_small">
            Current Record ID in Lightning Web Component: <strong>{recordId}</strong> <br/><br/>
        </div>
    </lightning-card>
</template>
import { LightningElement, api } from 'lwc';
export default class CurrentRecord extends LightningElement {
    @api recordId;
}

From https://niksdeveloper.com/salesforce/current-record-id-in-lwc-aura-and-quick-action/

注意: 如果 recordId 想要在 connectedCallback() 方法中使用,在某种场景是获取不到的, 如果获取不到, 可以尝试以下方法
某种场景: 通过 action button 进入页面。

import { LightningElement, api} from 'lwc';

export default class actiontestlwcpage extends LightningElement {
    @api recordId;

    connectedCallback() {
        const urlSearchParams = new URLSearchParams(window.location.search);
        this.recordId = urlSearchParams.get('recordId');
        if (this.recordId) {
            console.log('Found recordId: ' + this.recordId);
        }
    }
}

Get current page url/param

获取参数

let query = location.search;
let searchParams = new URLSearchParams(query);
this.allParam  = searchParams.get('c__callObjectIdentifier')

获取base url

search = window.location.href;
//get base url
baseurl = this.search.substring(0, this.search.indexOf('/lightning'));

打开弹框

<template>
    <!-- lightning button for open modal window -->
    <lightning-button variant="brand"
       label="What is Modal/PopUp in LWC?"
       title="What is Modal/PopUp in LWC?"
       onclick={openModal}
       class="slds-m-left_x-small">
    </lightning-button>
    <!--Use template if:true to display/hide popup based on isModalOpen value-->  
    <template if:true={isModalOpen}>
        <!-- Modal/Popup Box LWC starts here -->
        <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" aria-describedby="modal-content-id-1" class="slds-modal slds-fade-in-open">
            <div class="slds-modal__container">
                <!-- Modal/Popup Box LWC header here -->
                <header class="slds-modal__header">
                    <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}>
                        <lightning-icon icon-name="utility:close"
                            alternative-text="close"
                            variant="inverse"
                            size="small" ></lightning-icon>
                        <span class="slds-assistive-text">Close</span>
                    </button>
                    <h2 id="modal-heading-01" class="slds-text-heading_medium slds-hyphenate">Modal/PopUp Box header LWC</h2>
                </header>
                <!-- Modal/Popup Box LWC body starts here -->
                <div class="slds-modal__content slds-p-around_medium" id="modal-content-id-1">
                    <p><b>Modals/Popup Box are used to display content in a layer above the app.
                    </b></p>
                    <p><b>This paradigm is used in cases such as the creation or editing of a record, as well as various types of messaging and wizards.
                    </b></p>
                </div>
                <!-- Modal/Popup Box LWC footer starts here -->
                <footer class="slds-modal__footer">
                    <button class="slds-button slds-button_neutral" onclick={closeModal} title="Cancel">Cancel</button>
                    <button class="slds-button slds-button_brand" onclick={submitDetails} title="OK">OK</button>
                </footer>
            </div>
        </section>
        <div class="slds-backdrop slds-backdrop_open"></div>
    </template>
 </template>
import { LightningElement,track } from 'lwc';
export default class ModalPopupLWC extends LightningElement {
    //Boolean tracked variable to indicate if modal is open or not default value is false as modal is closed when page is loaded 
    @track isModalOpen = false;
    openModal() {
        // to open modal set isModalOpen tarck value as true
        this.isModalOpen = true;
    }
    closeModal() {
        // to close modal set isModalOpen tarck value as false
        this.isModalOpen = false;
    }
    submitDetails() {
        // to close modal set isModalOpen tarck value as false
        //Add your code to call apex method or do some processing
        this.isModalOpen = false;
    }
}

https://www.sfdcpoint.com/salesforce/modal-popup-lightning-web-component-lwc/

设置lwc页面可用的场景

配置 xxx.js-meta.xml 文件
需设置isExposed 为true,同时配置targets

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="lwcExercise">
    <apiVersion>46.0</apiVersion>
    <isExposed>true</isExposed>
    <masterLabel>lwc练习</masterLabel>
    <description>lwc练习用的</description>
    <targets>
        <target>lightning__AppPage</target>
        <target>lightning__HomePage</target>
        <target>lightning__RecordPage</target>
        <target>lightning__Inbox</target>
        <target>lightningCommunity__Page</target>
        <target>lightningCommunity__Default</target>
        <target>lightningSnapin__ChatMessage</target>
    </targets>
    <targetConfigs>
        <targetConfig targets="lightning__AppPage">
            <property name="name" type="String" label="Name" placeholder="哈哈哈" description="单纯的一个文本。测试用"/>
        </targetConfig>
    </targetConfigs>
</LightningComponentBundle>

在lwc页面中展示另一个lwc页面

假设有两个页面
currentPage
showThisPage
现在需要在currentPage中展示showThisPage的内容
每一个大写字母前需要加-

<c-show-this-page></c-show-this-page>

如果需要传参数,则在currentPage.js触发传参的地方加上
可能需要加上延迟传参

this.timeoutId = setTimeout(this.doExpensiveThing.bind(this), 500);
	doExpensiveThing(){
	   if (this.showSearchContact) 
	   {
	       this.template.querySelector('c-search-account-page').changeMessage(this.searchmap);
	   }
    }

showThisPage.js中通过@api接受

@api
changeMessage(searchmap){

}

也可以直接在调用 child page de 代码直接传参
情况1: 如果参数都是小写 pagetype ,则直接 pagetype = ‘xx’
情况2: 如果参数有大小写 pageType, 写法: page-type=‘xx’

<c-show-this-page pagetype = 'xx' page-type="test"></c-show-this-page>

在child page那边,使用 @API 接受

@api pagetype; // 情况1
@api pageType; // 情况2

参考文档

showThisPage 把参数传送回到currentPage
在触发的地方
showThisPage.js

const selectEvent = new CustomEvent('方法名', {
  参数名: 参数
});
this.dispatchEvent(selectEvent);

currentPage.html

<c-show-this-page on方法名={要调用的JS方法}></c-show-this-page>

currentPage.js

调用的JS方法(参数){
}

参考一: https://developer.salesforce.com/docs/component-library/documentation/lwc/events_propagation

参考二: http://amitsalesforce.blogspot.com/2019/07/events-in-lightning-web-components-lwc.html

Datatable

隐藏表头的操作:在row中添加 hideDefaultActions:true

{ label: 'Priority', fieldName: 'Priority', hideDefaultActions:true, type: 'text' },

某一列是按钮

{
      type: "button",
      hideDefaultActions:true,
      typeAttributes: {
          label: 'Edit',
          title: 'Edit',
          name: 'Edit',
          value: 'Edit',
          variant:'brand' 设置样式
      },
      cellAttributes: {
          style: 'transform: scale(0.55);float:right; ',
          alignment: 'right' 设置位置用
      }
  }

点击动作

<lightning-datatable 
	key-field="id" 
	data={caseListData} 
	max-row-selection="1" 
	columns={caseColumns}
	onrowselection={getCaseRowActions} 
	data-id="casetalbe"
	onrowaction={viewRecord}>
</lightning-datatable>
viewRecord(event){
    var actionName = event.detail.action.name;
    if (actionName == 'Edit') 
    {
    }
}

需要展示在前端的list二次赋值

list = [];
this.list = [...this.list,addParem];

JS相关方法

判断object 是否为空

Object.keys( object). length === 0

赋值一个obj到另一个obj

JSON.parse(JSON.stringify(productData))

List 的插入方式

push
splice(指定位置,要删除的元素(为0时代表不删除),要插入的元素)

去掉前后空格

replace(/^\s*|\s*$/g,"") 

对 List 类型根据某个字段进行排序
list.sort((a, b) => b.filed- a.filed);

日期时间 Datetime/Date

日期相关方法参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString

// formatDate.js
import { LightningElement } from 'lwc';
import LOCALE from '@salesforce/i18n/locale';
export default class FormatDate extends LightningElement {
    date = new Date(2020, 6, 7);
    formattedDate = new Intl.DateTimeFormat(LOCALE).format(this.date);
}

String 转换成 Date/Datetime类型

var strardate = new Date(Date.parse('2022-12-12T12:12:12.000Z'));
var today = new Date();
//获取年份
strardate.getFullYear()//获取月份
strardate.getMonth()//获取日
strardate.getDay()//获取时
strardate.getHours()//获取分
strardate.getMinutes()//获取秒
strardate.getSeconds()

From https://developer.salesforce.com/docs/component-library/documentation/en/lwc/create_i18n

把 String 的 yyyy-mm-ddTHH:MM:SSZ (2022-12-28T03:43:45Z) 转成日期时间的 28/12/2022, 11:43 am

const formatDate = (isoString) => {
   const date = new Date(isoString);
    return new Intl.DateTimeFormat('en-AU', {
        day: '2-digit',
        month: '2-digit',
        year: 'numeric',
        hour: '2-digit',
        minute: '2-digit',
        hour12: true
    }).format(date);
};

formatDate('2022-12-28T03:43:45Z')

获取当前用户的Id

import { LightningElement } from 'lwc';
import uId from '@salesforce/user/Id';
export default class CurrentUser extends LightningElement {
    userId = uId;
}

From https://niksdeveloper.com/salesforce/get-current-user-id-in-salesforce/

弹框提示

import { ShowToastEvent } from 'lightning/platformShowToastEvent';
this.dispatchEvent(
    new ShowToastEvent({
        title: 'Success',
        message: 'Record deleted',
        variant: 'success'
    })
);
this.dispatchEvent(
    new ShowToastEvent({
        title: 'Error deleting record',
        message: error.body.message,
        variant: 'error'
    })
);

Get record type

import { getObjectInfo } from 'lightning/uiObjectInfoApi';
import CASEPRODUCT_OBJECT from '@salesforce/schema/Case_Related_Product__c';

@wire(getObjectInfo, { objectApiName: CASEPRODUCT_OBJECT })
    objectInfo;

    recordTypeId() {
        const rtis = this.objectInfo.data.recordTypeInfos;
        for (var i = 0; i < rtis.length; i++) {
        	if (rtis[i].name == 'With Existing Product') {
        		this.WithProdutrecordTypeId = rtis[i].recordTypeId;
        	} else if(rtis[i].name == 'Without Existing Product') {
        		this.WithoutProdutrecordTypeId = rtis[i].recordTypeId;
        	}
        }
    }

Custom lable

import labelreference from '@salesforce/label/c.labelreference';

const columns = [
    { label: labelreference, fieldName: 'name' }
];

From https://salesforce.stackexchange.com/questions/321789/lwc-lightning-datatable-custom-labels

<template>
    <lightning-card  title={label.WelcomeLabel} variant="narrow">
        <p>
            <lightning-button label={label.NewCaseLabel}></lightning-button>
        </p>
        <p>{label.HomePageLabel}</p>
    </lightning-card>
</template>

From https://www.sfdcpoint.com/salesforce/custom-labels-in-lightning-web-component-lwc/

修改textarea的高度

:host{
	--sds-c-textarea-sizing-min-height:96px;
}

初始化方法

connectedCallback(){}

Datatable选中行事件

onrowselection:选择数据时触发的动作
selected-rows:被选中的数据,类型是List,获取的是table中key-field对应的字段的值。

html:

<template>
	<lightning-datatable
	        columns={columns}
	        data-id="selectTable"
	        data={data}
	        key-field="Id"
	        onrowselection={getSelectedRecords}
	        selected-rows={selectedRows}>
	</lightning-datatable>
	<lightning-button label="选择指定行" onclick={handleSelect}> </lightning-button>
</template>

Js:

import { LightningElement, track, wire,api } from 'lwc';
export default class searchAccountPage extends NavigationMixin(LightningElement) {
	this.columns = [
	{label: '姓', fieldName: 'LastName', hideDefaultActions:true, type: 'text'},
	{label: '名', fieldName: 'FirstName', hideDefaultActions:true, type: 'text'}
	{label: '年龄', fieldName: 'Age', hideDefaultActions:true, type: 'text'}
	{label: '性别', fieldName: 'Sex', hideDefaultActions:true, type: 'text'}
	{label: '邮箱', fieldName: 'Email', hideDefaultActions:true, type: 'text'}
	];
	this.data = [
	{'LastName':'王','FirstName':'1','Age':'11','Sex':'女','Email':'11@11.com','Id':'1'},
	{'LastName':'王','FirstName':'2','Age':'22','Sex':'女','Email':'11@11.com','Id':'2'},
	{'LastName':'王','FirstName':'3','Age':'33','Sex':'女','Email':'11@11.com','Id':'3'},
	{'LastName':'王','FirstName':'4','Age':'44','Sex':'男','Email':'11@11.com','Id':'4'},
	{'LastName':'王','FirstName':'5','Age':'55','Sex':'男','Email':'11@11.com','Id':'5'}
	];
	//获取前端中被选中的行
	getSelectedRecords(event) {
	    // 获取被选中的数据,这是一个list
	    const selectedRows = event.detail.selectedRows;
	    // 获取别选中的数据的长度
	    const recordsCount = event.detail.selectedRows.length;
	}
	//从后台中设置被选中的行
	handleSelect(){
		//放的是tabel中key-field字段对应的值
		var selectIdlist = '3';
		//如果是要清空之前的行在选中新的行。
		this.selectedRows = [];
		//放入新选中的行
		this.selectedRows.push(selectIdlist);
	}
}

LWC 和 Aura的双向调用

1.LWC 调用 Aura的方法
参考:https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.events_sending_to_aura_components

lwc

// categoryFilter.js
import { LightningElement } from 'lwc';

export default class CategoryFilter extends LightningElement {
    handleCheckboxChange() {
        // 赋值要传送到aura中的参数---开始
        const filters = Array.from(
            this.template.querySelectorAll('lightning-input'),
        )
            .filter(element => element.checked)
            .map(element => element.label);
       //赋值要传送到aura中的参数---结束
       //调用aura的方法-----开始 
        const filterChangeEvent = new CustomEvent('filterchangeaura中需要调用的属性名(去掉方法前面的on)', {
            detail: { filters(传送的参数) },
        });
        // Fire the custom event
        this.dispatchEvent(filterChangeEvent);
        //调用aura的方法-----结束
    }
}
<!-- categoryFilter.html -->
<template>
    <lightning-input label="Category 1" type="checkbox" onchange={handleCheckboxChange}></lightning-input>
    <lightning-input label="Category 2" type="checkbox" onchange={handleCheckboxChange}></lightning-input>
</template>

AURA

<!-- auraDomEventListener.cmp -->
<aura:component implements="flexipage:availableForAllPageTypes">
    <c:categoryFilter onfilterchange(lwc中调用的属性名)="{!c.handleFilterChange}"/>
</aura:component>
// auraDomEventListenerController.js
({
    handleFilterChange: function(component, event) {
    	//获取lwc中传过来的参数。
        var filters = event.getParam('filters');
    },
});

2.aura调用lwc的方法
https://developer.salesforce.com/docs/component-library/documentation/en/lwc/lwc.interop_aura_composition

aura

<!-- auraComponent.cmp file -->
<aura:component implements="flexipage:availableForAllPageTypes">
    <lightning:card title="Aura Hello World" iconName="custom:custom30" />
    <c:lwcHelloWorld name="Earthling" />
    <lightning:button variant="brand" label="Call LWC Function" onclick="{! c.handleClick }" /> 
</aura:component>
<!-- auraComponent.controller file -->
({  
  handleClick : function(component, event, helper) 
    {  
      component.find('lwcHelloWorld').sendName();   
    }  
})

LWC

<!-- lwcHelloWorld.html -->
<template>
    <lightning-card title="LWC Hello World" icon-name="custom:custom14">
        <div class="slds-card__body slds-card__body_inner">
            Hello, {name}!
        </div>
    </lightning-card>
</template>
// lwcHelloWorld.js
import { LightningElement, api } from 'lwc';

export default class HelloWorld extends LightningElement {
	//传参使用@api方法
    @api name;
    @api
    sendName(){
    }
    
}

aura调用lwc的方法:

cmp.find('lwc名称').lwc中的方法名()

tab的相关操作(aura可用,lwc暂不支持)

https://developer.salesforce.com/docs/atlas.en-us.232.0.api_console.meta/api_console/sforce_api_console_methods_lightning_workspaceAPI.htm

两个不同页面的lwc之间传值

https://developer.salesforce.com/docs/component-library/documentation/en/lwc/use_message_channel_publish

导出xls文件

JS:

	columnHeader = ['ID', 'FirstName', 'LastName', 'Email' ] 
    conatctData = [
        {ID:'111',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1112',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1113',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1114',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1115',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1116',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1117',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
        {ID:'1118',FirstName:'yrdy',LastName:'test',Email:'122@qq.com'},
    ]  

    exportFileJs(){
        // Prepare a html table
        let doc = '<table>';
        // Add styles for the table
        doc += '<style>';
        doc += 'table, th, td {';
        doc += '    border: 1px solid black;';
        doc += '    border-collapse: collapse;';
        doc += '}';          
        doc += '</style>';
        // Add all the Table Headers
        doc += '<tr>';
        this.columnHeader.forEach(element => {            
            doc += '<th>'+ element +'</th>'           
        });
        doc += '</tr>';
        // Add the data rows
        this.conatctData.forEach(record => {
            doc += '<tr>';
            doc += '<th>'+record.ID+'</th>'; 
            doc += '<th>'+record.FirstName+'</th>'; 
            doc += '<th>'+record.LastName+'</th>';
            doc += '<th>'+record.Email+'</th>'; 
            doc += '</tr>';
        });
        doc += '</table>';
        var element = 'data:application/vnd.ms-excel,' + encodeURIComponent(doc);
        let downloadElement = document.createElement('a');
        downloadElement.href = element;
        downloadElement.target = '_self';
        // use .csv as extension on below line if you want to export data as csv
        downloadElement.download = 'Contact Data.xls';
        document.body.appendChild(downloadElement);
        downloadElement.click();
        
    }

配置Jest Test

官方参考文档

Install Node.js and
在这个连接进行安装:https://nodejs.org/en/download/

检查是否安装成功(以下三个步骤都在Command Prompt中完成):
在电脑设置中打开 Command Prompt

输入:

node --version

再输入:

npm --version

更新电脑Salesforce CLI 版本(该代码运行时间较长, 耐心等待):

sf update

打开VS code, 并且创建新的项目, 连接到对应环境,
在中输入指令(该代码运行时间较长, 耐心等待):

sf force lightning lwc test setup

更加详细的请看官方文档.

定义 Console App 里面 LWC Tab 的 Icon 和 lable

LWC Tab 初始化的时候会是这样, 所以需要在代码中配置 tab 的 ICON 和 Label
在这里插入图片描述

代码

import { LightningElement, wire } from 'lwc';
import {
    IsConsoleNavigation,
    getFocusedTabInfo,
    setTabLabel,
    setTabIcon
} from 'lightning/platformWorkspaceApi';

const TAB_LABEL = 'Test Label';

export default class testpage extends LightningElement {
    @wire(IsConsoleNavigation) isConsoleNavigation;

    async setTabLabel() {
        console.log('this.isConsoleNavigation =:' + this.isConsoleNavigation);
        if (!this.isConsoleNavigation) {
            return;
        }
        const { tabId } = await getFocusedTabInfo();
        setTabLabel(tabId, TAB_LABEL);
        setTabIcon(tabId, 'utility:einstein', {
            iconAlt: 'Account Insights'
        });
    }

    connectedCallback() {
        this.setTabLabel();
    }
}

google 搜索关键词: setTabLabel() for Lightning Experience
参考文档

获取链接的参数

import { CurrentPageReference } from 'lightning/navigation';


@wire(CurrentPageReference)
currentPageReference;

connectedCallback() {
	 console.log(`c__myParam = ${this.currentPageReference.state.c__myParam}`);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值