苍穹外卖--sky-take-out(五)前端

kussmcx 2024-07-08 12:33:09 阅读 73

大部分笔记都是写在语雀的,这是一次性从本人语雀复制过来的,可能结构有些错乱


基础创建

环境要求

node.js

npm

Vue CLI

创建前端工程

使用vue ui命令创建

项目结构

启动项目

打开命令行窗口

快捷键ctrl+j

或者

运行

输入:npm run serve

停止服务

ctrl+c

修改端口号

与后端的tomcat端口号冲突

如何修改

在vue.config.js中配置前端服务号端口

devServe: {

port: 7070

}

小结

vue的基本使用

vue组件

以.vue结尾template--htmlstyle--cssscript--js

文本插值

作用:用来绑定data方法返回的对象属性

用法:{ {}}

举例:

属性绑定

作用:为标签的属性绑定data方法中返回的属性

用法:v-bind:xxx简写::xxx

举例:

<input>标签:输入框

<input type="text" value="xxx"> 表示:输入框为文本输入框,value是文本框里面的内容;

<img>:图片标签;

<br>:换行

<hr>:分割线

事件绑定

作用:为元素绑定对应的事件

用法:v-on:xxx,简写为@xxx

<input type="button" value="xxx" @xxx> 按钮标签

添加方法的时候需要在methods里面定义

双向绑定

作用:表单输入项和data方法中的属性进行绑定,任意一方改变都会同步给另一方

用法:v-model

条件渲染

作用:根据表达式的值来动态渲染页面元素

用法:v-if、v-else、v-else-if

axios

Axios是一个基于promise的网络请求库,作用于浏览器和nodejs中

安装命令:

npm install axios

导入命令:

import axios from 'axios'

跨域问题

在vue.config.json配置

发送post和get请求

问题

res =>{ console.log(res.data) }什么意思

这是一个简单的箭头函数(arrow function)在 JavaScript 中。这个函数接受一个参数 res 并打印 res.data 到控制台。

具体来说:

res => { ... }:这是一个箭头函数,它接受一个参数 res。console.log(res.data):这是函数体中的代码,用于打印 res.data 的值到控制台。

这个函数通常在处理异步操作(如 AJAX 请求或 Promise)的回调中看到,特别是当你使用像 Axios 这样的 HTTP 客户端库进行 API 调用时。在这种情况下,res 通常是一个包含 API 响应信息的对象,而 res.data 通常包含实际的响应数据。

例如,在使用 Axios 进行 GET 请求时,你可能会看到这样的代码:

<code>axios.get('https://api.example.com/data')

.then(res => {

console.log(res.data);

})

.catch(error => {

console.error(error);

});

在这个例子中,当 Axios 的 GET 请求成功时,它会调用 .then() 方法,并传递一个包含响应信息的对象作为参数(在这里是 res)。然后,箭头函数 res => { console.log(res.data); } 会被调用,并打印 res.data 的值到控制台。如果请求失败,.catch() 方法会被调用,并打印错误到控制台。

get请求时没有jwt令牌

axios.get('/api/admin/shop/status',{

headers: {

token: 'eyJhbGciOiJIUzI1NiJ9.eyJlbXBJZCI6MSwiZXhwIjoxNzE1Nzc3Mjk4fQ.eMABPnG4Y6xboMZry8ulLq_RUGdo4o1b_Sm7M_vmxPg'

}

})

添加令牌在请求头中;

第一个参数是路径,第二则就是在请求头中加入jwt令牌

报错

记得开启redis,后端的查询需要redis

统一相应方式

小结

Vue-Router路由

不同访问路径展示不同的访问界面

vue属于单页面应用,所谓的路由,就是根据浏览器路径不同,用不同的视图组件替换这个页面内容

创建

在vue ui时勾选router选项即可

这样就创建好了

小结

为什么我们没有进行第二步?

因为我们是可视化创建的,所以勾选router时自动就下载了

路由配置

路由组成

具体的配置

路由路径和视图的对应关系

在/src/router/index.js文件中

路由链接组件<router-link>

在/src/App.vue中

路由视图组件<router-view>

不用加什么东西,就当作是一个占位符;

加上就行

视图的位置

在/src/views/文件夹里

路由跳转

问题

如果用户访问的路由地址不存在,该如何处理?

创建一个404界面来提示用户,该界面不存在

在/src/router/index.js中,加入/404的路由路径和视图的联系

在src/views/里面创建404View.vue文件

重定向

当访问不存在时,并不是访问/404,所以需要将没有存在的路径转到404去

在/src/router/index.js中

小结

嵌套路由

嵌套路由:组件内要切换内容,就需要用到嵌套路由(子路由)

实现步骤

导入elementui

前往element官网:Element - The world's most popular Vue UI framework

执行npm i element-ui -S进行下载安装

引入文件

使用布局容器

在views目录下面创建一个包container/containerView

自动生成模板代码的插件:vetur

去官网找到相关代码,复制到对应的区域

创建3个子视图

在src/router/index.js中配置路由映射规则(嵌套路由配置)

在布局容器视图中添加<router-view>,实现子视图组件展示

在containerView.vue中

将原来的main换成占位符

添加<router-link>实现路由请求

注意

问题

如果直接访问/container时,如何默认展示某个子视图组件

可以使用redirect重定向;

小结

vuex

介绍

安装

npm install vuex@next --save

概念

使用

创建带有vuex功能的脚手架工程(在ui界面创建时勾选)

定义和展示共享数据

在src/store/index.js中集中定义共享数据;

修改共享数据

在mutations中定义函数,且之能在mutations中修改

在/src/store/index.js中

必须同步操作

在/src/app.vue中

异步共享数据

在actions中定义函数,用于调用mutation

比如axios

调用actions的方法

小结

TypeScript

介绍

解决tsc -v错误的问题:typeScript安装及TypeScript tsc 不是内部或外部命令,也不是可运行的程序或批处理文件解决办法_tsc' 不是内部或外部命令,也不是可运行的程序 或批处理文件。-CSDN博客

ts为什么要增加类型支持

小结

ts的常用类型

类型标注的位置

字符串、数字、布尔类型

字面量类型

interface类型

class类

小结

前端项目开发

技术选型

node.js

vue

ElementUI

axios

vuex

vue-router

typescript

代码结构

 


员工管理

解决npm install报错的问题

npm install 报错问题解决合集-CSDN博客

导入代码环境部署

直接导入代码即可

node版本下降到12.18.2版本:

windows中如何将已安装的nodejs高版本降级为低版本_nodejs降低版本windows-CSDN博客

- api:存放封装了Ajax请求文件的目录

- components:公共组件存放目录

- views:存放视图组件的目录

- App.vue:项目的主组件,页面的入口文件

- main.ts:整个项目的入口文件

- router.ts:路由文件

axios与Ajax请求的联系

axios与Ajax请求的联系主要体现在以下几个方面:

技术基础:

Ajax:即Asynchronous Javascript And XML(异步JavaScript和XML),是Jesse James Garrett在2005年提出的一种使用现有技术集合的“新”方法,这些技术包括HTML或XHTML、CSS、JavaScript、DOM、XML、XSLT等,以及最重要的XMLHttpRequest。axios:是一个基于Promise的网络请求库,既可以用于node.js,也可以用于浏览器中。它的底层实现同样依赖于XMLHttpRequest(在浏览器中)或http模块(在node.js中)。

功能特性:

Ajax:允许在不重新加载整个页面的情况下,与服务器交换数据并更新部分网页内容。它使用异步方式与服务器通信,通过XMLHttpRequest对象在浏览器与服务器之间传输数据。axios:从功能上讲,它封装了原生的XMLHttpRequest(或node.js的http模块),提供了更简洁、更易于使用的API。它支持Promise API,可以方便地处理异步请求,并且具有请求和响应拦截、数据转换、取消请求、自动转换JSON数据等特性。

使用方式:

Ajax:通常使用原生的JavaScript代码或jQuery等库来编写Ajax请求。代码相对繁琐,需要手动处理请求和响应的各个环节。axios:通过Promise实现了对Ajax技术的一种封装,使得请求处理更加简洁和优雅。例如,可以使用axios.get()、axios.post()等方法来发送请求,并通过.then()和.catch()来处理请求成功和失败的情况。

关系总结:

可以说,axios是对Ajax技术的一种封装和扩展。它通过提供更易用、更强大的API和功能,使得开发人员可以更方便地进行网络请求处理。在实际应用中,axios已经成为前端开发中广泛使用的网络请求库之一。

综上所述,axios与Ajax请求的联系主要体现在它们都是用于实现浏览器与服务器之间异步通信的技术,而axios则是对Ajax技术的一种封装和扩展,提供了更简洁、更易于使用的API和功能。

启动项目

npm run serve

跟踪login登录视图组件

① 获得登录页面路由地址

登录页面完整的访问地址为 http://localhost:8888/#/login,其中登录页面的路由地址为 /login,我们需要通过此路由地址找到对应的登录视图组件

② 从main.ts中找到路由文件

main.ts是整个前端项目的入口文件,在此文件中会创建Vue实例,在创建Vue实例时需要传入路由对象,所以从此文件中可以找到对应的路由文件位置。如下所示:

③ 从路由文件中找到登录视图组件

在路由文件中会配置整个项目所有的路由映射规则,我们只需要找到 /login 这个路径对应的实体组件即可。如下所示:

④ 从登录视图组件中找到登录方法

从上面的路由文件可以确定登录视图组件就是src/views/login/index.vue,此时就可以打开这个文件,然后仔细阅读代码,找到登录方法,如下所示:

⑤ 跟踪登录方法的执行过程

找到登录方法后,就需要跟踪代码的执行过程,主要就是观察前后端的交互过程。例如前端如何发送的Ajax请求,后端返回的数据格式等等

员工分页查询实现

需求分析与接口设计

业务规则:

根据页码展示员工信息(员工姓名、账号、手机号、账号状态、最后操作时间等)每页展示10条数据分页查询时可以根据需要,输入员工姓名进行查询

接口基本信息

Path: /admin/employee/page

Method: GET

请求参数

Query

参数名称

是否必须

示例

备注

name

张三

员工姓名

page

1

页码

pageSize

10

每页记录数

返回数据

名称

类型

是否必须

默认值

备注

其他信息

code

number

必须

msg

null

非必须

data

object

必须

├─ total

number

必须

├─ records

object []

必须

item 类型: object

├─ id

number

必须

├─ username

string

必须

├─ name

string

必须

├─ password

string

必须

├─ phone

string

必须

├─ sex

string

必须

├─ idNumber

string

必须

├─ status

number

必须

├─ createTime

string,null

必须

├─ updateTime

string

必须

├─ createUser

number,null

必须

├─ updateUser

number

必须

代码开发

要开发前端代码,首先需要找到对应的组件。从路由文件 router.ts 中找到员工管理页面(组件)。

可以看到,员工管理页面(组件)的位置为:src/views/employee/index.vue。我们只需要在此文件中开发员工分页查询相关的前端代码即可,整个开发过程大概可以分为以下几个关键步骤:

根据产品原型,制作页面头部效果(输入框、查询按钮等)为查询按钮绑定单击事件,发送Ajax请求,查询员工分页数据,实现前后端交互提供 vue 的初始化方法,在页面加载后就查询分页数据使用ElementUI提供的表格组件展示分页数据使用ElementUI提供的分页条组件实现翻页效果

注意:开发过程中,并不是所有的代码都实现了再测试,而是开发一部分,就需要测试一下,看效果,如果有问题再调整。没有问题,再继续开发、测试。所以,这是一个逐渐完善的过程。下面我们就按照上面的几个关键步骤来开发,每开发完一个关键步骤,就需要测试一下,来验证我们的代码是否正确。

制作页面头部效果

注意:输入框和按钮都是使用 ElementUI 提供的组件,对于前端的组件只需要参考 ElementUI 提供的文档,进行修改即可。实现代码如下:

<code><div class="tableBar">code>

<label style="margin-right: 5px">code>

员工姓名:

</label>

<el-input placeholder="请输入员工姓名" style="width: 15%" />code>

<el-button type="primary" style="margin-left: 20px">查询</el-button>code>

<el-button type="primary" style="float: right">+添加员工</el-button>code>

</div>

结果展示:

完成前后端数据交互

第一步:为查询按钮绑定单击事件

第二步:在methods中定义 pageQuery 方法,先验证当前方法能否正常执行

注意:按照开发规范,真正发送Ajax请求的代码需要封装到 api目录下的ts文件中(src/api/employee.ts)

第三步:在src/api/employee.ts 中定义 getEmployeeList 方法,实现发送Ajax请求获取分页数据

注意:发送 Ajax 请求的URL地址需要和前面我们设计的分页查询接口对应

第四步:在员工管理组件中导入 employee.ts 中定义的方法,并在data() 方法中定义分页相关的模型数据

注意:需要将name属性和上面的员工姓名输入框进行双向绑定,如下:

第五步:在pageQuery 方法中调用 getEmployeeList 方法

自动发送Ajax请求

前面的代码我们已经实现了前后端数据交互,但是有一个问题,就是只有在点击查询按钮时才会发生Ajax请求,实现分页数据查询。我们通常需要的是在当前页面(组件)加载后,就需要发送Ajax请求,查询第一页的数据。要实现这个效果,我们可以通过vue的生命周期方法,即created方法来做到,代码如下:

使用表格展示分页数据

前面我们已经实现了前后端数据交互,现在就需要将后端返回的数据通过表格展示出来,我们可以使用ElementUI提供的表格组件,具体使用方法可以参照官方提供的示例 Element - The world's most popular Vue UI framework

效果展示:

实现分页条实现翻页效果

结果展示

启用禁用员工状态

接口设计

新增员工

产品原型

接口设计

代码开发

在员工管理列表页面,点击 “添加员工”按钮,跳转到新增页面在新增员工页面录入员工相关信息点击“保存”按钮完成新增操作

第一步

为“添加员工”按钮绑定单击事件

第二步

编写 handleAddEmp 方法,进行路由跳转

注意:在路由文件中已经配置了如下路由规则

第三步

根据产品原型,开发页面元素

页面效果为:

第四步

定义模型数据和表单校验规则(elment去复制修改)

第五步

在 employee.ts 中封装新增员工方法,发送Ajax请求,实现前后端交互

注意:

发送请求的方式和相关参数,必须和前面的接口设计保持一致使用此方法时,别忘了在组件中通过import导入

第六步

在 methods 中定义提交表单的方法 submitForm

修改员工

需求分析

修改员工功能涉及到2个接口,分别是根据id查询员工信息和根据id修改员工信息。具体接口设计如下:

(1)根据id查询员工 接口

基本信息

Path: /admin/employee/{id}

Method: GET

请求参数

路径参数

参数名称

示例

备注

id

100

员工id

返回数据

名称

类型

是否必须

默认值

备注

其他信息

code

integer

必须

format: int32

data

object

必须

├─ createTime

string

非必须

format: date-time

├─ createUser

integer

非必须

format: int64

├─ id

integer

非必须

format: int64

├─ idNumber

string

非必须

├─ name

string

非必须

├─ password

string

非必须

├─ phone

string

非必须

├─ sex

string

非必须

├─ status

integer

非必须

format: int32

├─ updateTime

string

非必须

format: date-time

├─ updateUser

integer

非必须

format: int64

├─ username

string

非必须

msg

string

非必须

(2)根据id修改员工信息 接口

基本信息

Path: /admin/employee

Method: PUT

请求参数

Headers

参数名称

参数值

是否必须

示例

备注

Content-Type

application/json

Body

名称

类型

是否必须

默认值

备注

其他信息

id

integer

必须

format: int64

idNumber

string

必须

name

string

必须

phone

string

必须

sex

string

必须

username

string

必须

返回数据

名称

类型

是否必须

默认值

备注

其他信息

code

integer

必须

format: int32

data

string

非必须

msg

string

非必须

代码开发

在员工管理列表页面点击 “修改”按钮,跳转到修改页面在修改员工页面录入员工相关信息点击“保存”按钮完成修改操作

注意:

由于添加员工和修改员工的表单项非常类似,所以添加和修改操作可以共用同一个页面(addEmployee.vue)修改员工涉及到原始数据回显,所以页面跳转时需要传递员工id作为参数

第一步

在员工管理页面中,为“修改”按钮绑定单击事件,用于跳转到修改页面

第二步

在methods中编写 handleUpdateEmp 方法,实现路由跳转

注意:使用路由对象的push方法在进行路由跳转时,可以通过地址栏传递参数,具体语法为:

this.$router.push({path: 路由路径, query:{参数名:参数值}})

第三步

在 addEmployee.vue 组件中定义模型数据optType,用于区分本次操作是新增还是修改

注意:区分当前操作是新增员工还是修改员工,只需要尝试获取路由参数id。如果能获取到则当前操作为修改,否则为新增。具体获取路由参数的语法为:

this.$router.query.参数名

第四步

如果是修改操作,需要根据id查询员工原始信息用于页面回显,需要在 employee.ts 中创建queryEmployeeById方法

注意:

发送请求的方式和相关参数,必须和前面的接口设计保持一致使用此方法时,别忘了在组件中通过import导入

第五步:在 addEmployee.vue 组件的 created 方法中查询员工原始信息用于页面数据回显

到目前位置已经实现了员工信息的回显,可以进行简单的测试,如果回显没有问题再继续开发后面的代码

第六步

如果是修改操作,“保存并继续添加员工” 按钮则不需要显示,通过 v-if 指令进行判断

第七步

在 employee.ts 中创建方法,用于修改员工,发送Ajax请求

注意:

发送请求的方式和相关参数,必须和前面的接口设计保持一致使用此方法时,别忘了在组件中通过import导入

第八步

修改 addEmployee.vue 组件中的 submitForm 方法,需要根据当前操作类型执行新增或者修改操作

套餐管理

套餐分页查询

需求分析与接口

要展示套餐分页数据,就需要前后端进行数据交互,对应的接口有两个:

分类查询接口(用于套餐分类下拉框中分类数据展示)套餐分页查询接口

1)分类查询接口

基本信息

Path: /admin/category/list

Method: GET

请求参数

Query

参数名称

是否必须

示例

备注

type

2

分类类型:1为菜品分类,2为套餐分类

返回数据

名称

类型

是否必须

默认值

备注

其他信息

code

integer

必须

format: int32

data

object []

非必须

item 类型: object

├─ createTime

string

非必须

format: date-time

├─ createUser

integer

非必须

format: int64

├─ id

integer

非必须

format: int64

├─ name

string

非必须

├─ sort

integer

非必须

format: int32

├─ status

integer

非必须

format: int32

├─ type

integer

非必须

format: int32

├─ updateTime

string

非必须

format: date-time

├─ updateUser

integer

非必须

format: int64

msg

string

非必须

(2)套餐分页查询接口

基本信息

Path: /admin/setmeal/page

Method: GET

请求参数

Query

参数名称

是否必须

示例

备注

categoryId

分类id

name

套餐名称

page

页码

pageSize

每页记录数

status

套餐起售状态

返回数据

名称

类型

是否必须

默认值

备注

其他信息

code

number

必须

msg

null

非必须

data

object

非必须

├─ total

number

非必须

├─ records

object []

非必须

item 类型: object

├─ id

number

必须

├─ categoryId

number

必须

├─ name

string

必须

├─ price

number

必须

├─ status

number

必须

├─ description

string

必须

├─ image

string

必须

├─ updateTime

string

必须

├─ categoryName

string

必须

代码开发

先找到对应组件

router.ts

根据产品原型,制作页面头部效果(输入框、下拉框、查询按钮等)动态填充套餐分类下拉框中的分类数据为查询按钮绑定单击事件,发送Ajax请求,查询套餐分页数据,实现前后端交互提供 vue 的初始化方法,在页面加载后就查询分页数据使用ElementUI提供的表格组件展示分页数据使用ElementUI提供的分页条组件实现翻页效果

制作页面头部效果

<code><template>

<div class="dashboard-container">code>

<div class="container">code>

<div class="tableBar">code>

<label style="margin-right:5px">套餐名称:</label>code>

<el-input v-model="name" placeholder="请输入套餐名称" style="width:15%" />code>

<!-- 选择器 -->

<label style="margin-right:5px">套餐分类:</label>code>

<el-select v-model="value" placeholder="请选择">code>

<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value">code>

</el-option>

</el-select>

<label style="margin-right:5px">套餐状态:</label>code>

<el-select v-model="saleStatus" placeholder="请选择">code>

<el-option v-for="item in saleStatusArr" :key="item.value" :label="item.label" :value="item.value">code>

</el-option>

</el-select>

<el-button type="primary" style="margin-left: 20px" @click="pageQuery()">查询</el-button>code>

<div style="float: right">code>

<el-button type="danger">批量删除</el-button>code>

<el-button type="info">+新建套餐</el-button>code>

</div>

</div>

</div>

</div>

</template>

<script lang="ts">code>

export default {

data() {

return {

name: '', //套餐名称,对应上面的输入框

page: 1, //当前页码

pageSize: 10, //每页记录数

total: 0, //总记录数

records: [], //当前页要展示的数据集合

options: [{

value: '选项1',

label: '黄金糕'

}, {

value: '选项2',

label: '双皮奶'

}, {

value: '选项3',

label: '蚵仔煎'

}, {

value: '选项4',

label: '龙须面'

}, {

value: '选项5',

label: '北京烤鸭'

}],

value: '',

saleStatusArr:[{

value:'0',

label: '起售'

},{

value: '1',

label: '停售'

}]

}

}

}

</script>

注意:当前套餐分类下拉框中的数据是直接在页面固定写死的,后续需要改为从后端动态获取。

动态填充套餐分类下拉框数据

现在需要将套餐分类下拉框中的数据改为动态获取,即前端需要发送Ajax请求,调用后端的分类查询接口,然后将后端返回的套餐分类数据动态展示在下拉框中。因为本次前后端交互是需要查询分类数据,所以按照项目规范,发送Ajax请求的代码需要定义到 src/api/category.ts 文件中。

此处只需要将此方法(getCategoryByType)导入当前组件,然后在 created 方法中调用此方法,获取套餐分类数据,动态填充套餐分类下拉框即可。

注意:因为此处我们要查询的是套餐分类,所以传递的参数type值为2。

前面我们已经初步实现了页面头部制作,并且可以填充下拉框中的数据了。但是命名上并不是特别规范,所以我们需要进行一个调整,具体修改后端的代码如下:

效果展示:

 

动态获取套餐分页数据

1、为查询按钮绑定单击事件

2、 在methods中定义 pageQuery 方法,先验证当前方法能否正常执行

注意:按照开发规范,真正发送Ajax请求的代码需要封装到 api目录下的ts文件中(src/api/setMeal.ts)

3、在src/api/setMeal.ts 中定义 getSetmealPage 方法,实现发送Ajax请求获取分页数据

注意:发送 Ajax 请求的URL地址需要和前面我们设计的分页查询接口对应

4、在套餐管理组件中导入 setMeal.ts 中定义的方法,并在data() 方法中定义分页相关的模型数据

注意:需要将属性和上面的输入框、下拉框进行双向绑定。

5、在pageQuery 方法中调用 getSetmealPage方法,实现前后端数据交互

自动发送Ajax请求

前面的代码我们已经实现了前后端数据交互,但是有一个问题,就是只有在点击查询按钮时才会发生Ajax请求,实现分页数据查询。我们通常需要的是在当前页面(组件)加载后,就需要发送Ajax请求,查询第一页的数据。要实现这个效果,我们可以通过vue的生命周期方法,即created方法来做到,

使用表格展示分页数据

使用ElementUI提供的表格组件

<code><div>

<el-table :data="records" stripe class="tableBox" style="width: 100%">code>

<el-table-column type="selection" wide="25"/>code>

<el-table-column prop="name" label="套餐名字" width="180">code>

</el-table-column>

<el-table-column label="图片">code>

<template slot-scope="scope">code>

<el-image style="width: 80px; height: 40px; border: none" :src="scope.row.image"></el-image>code>

</template>

</el-table-column>

<el-table-column prop="categoryName" label="套餐分类">code>

</el-table-column>

<el-table-column prop="price" label="套餐价格">code>

</el-table-column>

<el-table-column label="售卖状态">code>

<div class="tableColumn-status" :class="{'stop-usr': scope.row.status === 0}">code>

{ { scope.row.status === 0 ? "禁用" : "启用" }}

</div>

</el-table-column>

<el-table-column prop="updateTime" label="最后操作时间"></el-table-column>code>

<el-table-column label="操作" align="center" width="250px">code>

<template slot-scope="scope">code>

<el-button type="text" size="small">修改</el-button>code>

<el-button type="text" size="small">{ { scope.row.status === 0 ? "启用" : "禁用"}}code>

</el-button>

<el-button type="text" size="small">删除</el-button>code>

</template>

</el-table-column>

</el-table>

</div>

使用分页条实现翻页效果

使用 ElementUI 提供的分页条组件,并绑定事件处理函数



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。