React 仪器租赁项目
遇见的错误
警告错误 PascalCase
解决方案:
由于我的组件命名为了Left_nav这种格式的,把组件名给改成了LeftNav成功消除了警告信息。记得组件名第一个字母需得大写,后面用驼峰命名
注册界面
Form表单的使用:
表单
记得先需要初始化表单元素:
const register = () => {
//初始化表单元素
const [form] = React.$Vant.Form.useForm()
}
手机号
注意:表单input在vue2不是<input> 而是 Field
{/* 手机号 */}
<div className="wrap-input100 validate-input m-b-10">
<React.$Vant.Form.Item
name="mobile"
label="手机号"
rules={[
{ required: true, message: '请输入手机号码' },
{ pattern: /^1[3456789]{1}\d{9}$/, message: '请输入正确格式的手机号' }
]}
>
<React.$Vant.Field placeholder="请输入手机号码" />
</React.$Vant.Form.Item>
</div>
密码
{/* 密码 */}
<div className="wrap-input100 validate-input m-b-10">
<React.$Vant.Form.Item
name="password"
label="密码"
rules={[
{ required: true, message: '请输入密码' },
]}
>
<React.$Vant.Field type="password" placeholder="请输入密码" />
</React.$Vant.Form.Item>
</div>
注册的提交按钮:
<div className="container-login100-form-btn p-t-10">
<React.$Vant.Button nativeType="submit" className="login100-form-btn">注 册</React.$Vant.Button>
</div>
链接跳转:
首先:需要初始化路由跳转对象
const register = () => {
//钩子函数初始化路由跳转对象
const navigate = React.$Router.useNavigate()
}
<React.$Router.NavLink to='/business/base/login' className="txt1">立即登录</React.$Router.NavLink>
后端:
创建模块:php think build --module rent
创建控制器:php think make:controller rent/business/Base
构建api接口请求,需要安装异步请求工具axios
安装异步请求工具axios
yarn add axios -S
去git拿到封装好的请求服务封装request.js文件,需要改一下请求前缀
需要注意,改完请求的默认前缀之后,需要修改前端的代理配置
api接口请求:
路径 - - rent\src\api\business\base.js
//引入封装的请求服务
import { POST, UPLOAD } from '@/services/request.js'
//导出接口
const base = {
register(data = {})
{
return POST({
// /rent/business/base/register
url: '/business/base/register',
params: data
})
},
login(data = {})
{
return POST({
url: '/business/base/login',
params: data
})
},
}
export default base
前端接收到后端请求的数据信息:
//钩子函数初始化路由跳转对象
const navigate = React.$Router.useNavigate()
const finish = async (values) => {
var result = await React.$API.login(values)
if (result.code) {
React.$Vant.Notify.show({
type: 'success',
message: result.msg,
duration: 1000,
onClose: () => {
// 存放cookie的语法
React.$Cookie.save('LoginAuth', result.data)
React.$LoginAuth = result.data
navigate(result.url)
}
})
} else {
React.$Vant.Notify.show({
type: 'danger',
message: result.msg
})
return false
}
}
cookie
安装cookie:
yarn add react-cookies -S
路径 - - rent\src\index.js
挂载cookie:
// 引入cookie
import cookie from 'react-cookies'
//挂载全局自定义属性
React.$Cookie = cookie
将登录信息做一个react全局属性
//将我们的登录信息,做一个React全局属性,如果没有登录就给空对象,如果有登录就给cookie信息
React.$LoginAuth = cookie.load('LoginAuth') ? cookie.load('LoginAuth') : {}
使用cookie:
路径 - - rent\src\components\business\base\index.js
/设置状态数据
const [LoginAuth, setLoginAuth] = React.useState(React.$LoginAuth)
//用钩子函数来代替生命周期
React.useEffect(() => {
var LoginAuth = React.$Cookie.load('LoginAuth') ? React.$Cookie.load('LoginAuth') : {}
// console.log(LoginAuth)
//设置状态数据
setLoginAuth(LoginAuth)
}, [])
前端输出:
如果有昵称,则输出昵称,如果没有昵称则输出手机号,如果没有手机号则显示请先登录
const NickName = () => {
if (LoginAuth.nickname) {
return (
<h2>{LoginAuth.nickname}</h2>
)
} else if (LoginAuth.mobile) {
return (
<h2>{LoginAuth.mobile_text}</h2>
)
} else {
return (
<h2>请先登录</h2>
)
}
}
如果没有登录需要跳转到登录
首先 在路由中组装登录组件
路径 — rent\src\routers\index.js
<Route key={idx} path={son.path} element={<AuthRouter auth={son.auth} component={<son.component />} />}></Route>
一开始点击我的页面的时候,需要判断用户是否有登录,如果没有登录,则点击我的 的时候需要跳转到登录界面
路径 - - rent\src\routers\auth.js
做的一个路由:
import React from 'react'
import {Navigate} from 'react-router-dom'
const AuthRouter = (props) =>
{
// console.log(props)
// 根据传递过来的props里面的auth属性来判断路由是否需要登录
if(props.auth)
{
//说明需要登录
//获取cookie的信息
var LoginAuth = React.$Cookie.load('LoginAuth') ? React.$Cookie.load('LoginAuth') : {}
if(!LoginAuth || JSON.stringify(LoginAuth) === "{}")
{
//说明没有cookie 意味着没有登录,跳转到登录界面去
return (
<Navigate to="/business/base/login" />
)
}else
{
//说明有cookie,那就显示给他当前访问的页面组件
return (
<>
{props.component}
</>
)
}
}else
{
//不需要登录
return (
<>
{props.component}
</>
)
}
}
export default AuthRouter
登录的时候需要获取cookie内的信息:
调用login登录接口之后,看是否有用户信息,有信息则登录,并且存放cookie的信息
const finish = async (values) => {
var result = await React.$API.login(values)
if (result.code) {
React.$Vant.Notify.show({
type: 'success',
message: result.msg,
duration: 1000,
onClose: () => {
// 存放cookie的语法
React.$Cookie.save('LoginAuth', result.data)
React.$LoginAuth = result.data
navigate(result.url)
}
})
} else {
React.$Vant.Notify.show({
type: 'danger',
message: result.msg
})
return false
}
}
退出登录
组件:
<div className="my_dind">
<div className="bt">
<a onClick={logout}>
<h3><img src="/assets/images/my_x_02.png" alt="" />退出登录</h3>
<div className="right">
<img src="/assets/images/right_jiant.png" alt="" />
</div>
</a>
</div>
</div>
使用路由跳转:
//钩子函数初始化路由跳转对象
const navigate = React.$Router.useNavigate()
触发登录事件:onClick={logout}
路径 - - rent\src\components\business\base\index.js
// 退出登录
const logout = () => {
React.$Vant.Dialog.confirm({
title: '退出提醒',
message: '是否确认退出登录'
}).then(() => {
//删除cookie,并跳转到登录界面
React.$Cookie.remove('LoginAuth')
React.$LoginAuth = {}
//跳转到登录界面
navigate('/business/base/login')
})
.catch(() => { })
}
修改个人资料
组件:
手机号:
<React.$Vant.Form form={form} onFinish={profile}>
<React.$Vant.Form.Item
label="手机号"
name="mobile"
initialValue={LoginAuth.mobile}
rules={[
{required:true, message: '请输入手机号'}
]}
>
<React.$Vant.Field disabled />
</React.$Vant.Form.Item>
</React.$Vant.Form>
密码:
<React.$Vant.Form.Item
name="password"
label="密码"
>
<React.$Vant.Field placeholder="留空,不需要密码" />
</React.$Vant.Form.Item>
邮箱:
<React.$Vant.Form.Item
name="email"
label="邮箱"
initialValue={LoginAuth.email}
rules={[
{required:true, message: '请输入邮箱'},
{type:'email', message: '请输入正确的邮箱格式'}
]}
>
<React.$Vant.Field placeholder="请输入邮箱" />
</React.$Vant.Form.Item>
性别:
Popup:弹出方式 bottom:从底部弹出
picker 下拉选择框
点击性别的时候,设置显示为true - - SetGenderShow(true)},点击取消时则关闭
defaultIndex:默认选中(0,1,2数字)
{/* 性别 */}
<React.$Vant.Form.Item
label="性别"
onClick={() => {SetGenderShow(true)}}
>
<React.$Vant.Field placeholder="请选择性别" isLink readonly value={LoginAuth.gender_text} />
</React.$Vant.Form.Item>
<React.$Vant.Popup position="bottom" round visible={GenderShow} onClose={() => {SetGenderShow(false)}}>
<React.$Vant.Picker
title="性别"
columns={GenderList}
defaultIndex={LoginAuth.gender}
onConfirm={GenderConfirm}
onCancel={() => {SetGenderShow(false)}}
/>
</React.$Vant.Popup>
获取性别数据:
// 表单内容
const [form] = React.$Vant.Form.useForm()
// 性别
const [GenderShow, SetGenderShow] = React.useState(false)
const GenderList = [
{text:'保密', value:0},
{text:'男', value:1},
{text:'女', value:2},
]
//点击确认按钮
const GenderConfirm = (gender) =>
{
//隐藏picker
SetGenderShow(false)
LoginAuth.gender = gender.value
LoginAuth.gender_text = gender.text
SetLoginAuth(LoginAuth)
}
地区:
安装城市地区数据代码:
//安装城市地区数据
yarn add @vant/area-data -S
引入地区数据:
import { areaList } from '@vant/area-data'
地区数据:
RegionStr—地区 RegionCode—地区码
//地区
const [RegionShow, SetRegionShow] = React.useState(false)
const [region, SetRegion] = React.useState('')
const [code, SetCode] = React.useState('')
//初始化地区,获取cookie中的省市区
const RegionInit = () =>
{
var RegionStr = ''
var RegionCode = ''
if(LoginAuth.province_text)
{
RegionStr += LoginAuth.province_text
RegionCode = LoginAuth.province
}
if(LoginAuth.city_text)
{
RegionStr += `/${LoginAuth.city_text}`
RegionCode = LoginAuth.city
}
if(LoginAuth.district_text)
{
RegionStr += `/${LoginAuth.district_text}`
RegionCode = LoginAuth.district
}
SetRegion(RegionStr)
SetCode(RegionCode)
}
//选择地区后,点击确认按钮的时候,调用RegionInit()
const RegionConfirm = (result) =>
{
SetRegionShow(false)
var [province, city, district] = result
LoginAuth.province = province.code
LoginAuth.province_text = province.name
LoginAuth.city = city.code
LoginAuth.city_text = city.name
LoginAuth.district = district.code
LoginAuth.district_text = district.name
SetLoginAuth(LoginAuth)
RegionInit()
}
地区组件:
{/* 地区 */}
<React.$Vant.Form.Item
label="地区"
onClick={() => {SetRegionShow(true)}}
>
<React.$Vant.Field placeholder="请选择地区" isLink readonly value={region} />
</React.$Vant.Form.Item>
<React.$Vant.Popup position="bottom" round visible={RegionShow} onClose={() => {SetRegionShow(false)}}>
<React.$Vant.Area
title="请选择地区"
areaList={areaList}
value={code}
onCancel={() => {SetRegionShow(false)}}
onConfirm={RegionConfirm}
/>
</React.$Vant.Popup>
头像:
头像组件:
Uploader 文件上传 ,maxCount:最多选择一张 initialValue:初始值
头像:
//头像
const [avatar, SetAvatar] = React.useState([
{url: LoginAuth.avatar_text}
])
{/* 头像 */}
<React.$Vant.Form.Item
label="头像"
name="avatar"
initialValue={[
{url: LoginAuth.avatar_text}
]}
>
<React.$Vant.Uploader maxCount={1} value={avatar} />
</React.$Vant.Form.Item>
表单提交:
在页面直接提交
//表单提交
const profile = async (form) =>
{
// console.log(form);
// console.log(LoginAuth);
//组装数据
var data = {
id: LoginAuth.id,
nickname: form.nickname,
email: form.email,
gender: LoginAuth.gender,
province: LoginAuth.province,
city: LoginAuth.city,
district: LoginAuth.district,
}
//判断密码有填写在去修改
if(form.password)
{
data.password = form.password
}
//判断有头像数据,在去更新
if(form.avatar.length > 0 && form.avatar[0].file)
{
data.avatar = form.avatar[0].file
}
// console.log(data)
//调用接口
var result = await React.$API.profile(data)
//如果更新成功
if(result.code)
{
React.$Vant.Notify.show({
type:'success',
message: result.msg,
duration: 1000,
onClose: () => {
// 重新覆盖cookie
React.$Cookie.save('LoginAuth', result.data)
React.$LoginAuth = result.data
//返回上一个界面
navigate(-1)
}
})
}else
{
//更新资料失败
React.$Vant.Notify.show({
type:'danger',
message: result.msg
})
}
}
修改资料后端
isPost()请求 或者 isAjax()都可以 ,都是axios异步请求
// 修改资料
public function profile()
{
//isPost()请求 或者 isAjax()都可以
if($this->request->isAjax())
{
$params = $this->request->param();
$id = $this->request->param('id', 0, 'trim');
$nickname = $this->request->param('nickname', '', 'trim');
$email = $this->request->param('email', '', 'trim');
$gender = $this->request->param('gender', '', 'trim');
$province = $this->request->param('province', '', 'trim');
$city = $this->request->param('city', '', 'trim');
$district = $this->request->param('district', '', 'trim');
$password = $this->request->param('password', '', 'trim');
//先确认这个用户是存在
$business = $this->BusinessModel->find($id);
if(!$business)
{
$this->error('用户不存在');
exit;
}
//组装数据
$data = [
'id' => $id,
'nickname' => $nickname,
'email' => $email,
'gender' => $gender,
'province' => $province,
'city' => $city,
'district' => $district,
];
//判断是否有修改过邮箱,如果有修改过邮箱,那么认证状态也要修改
if($email != $business['email'])
{
$data['status'] = 0;
}
//判断密码是否要修改
if(!empty($password))
{
//重新生成密码盐
$salt = build_ranstr();
$password = md5($password.$salt);
$data['password'] = $password;
$data['salt'] = $salt;
}
//接收文件上传
if(isset($_FILES['avatar']) && $_FILES['avatar']['size'] > 0)
{
//调用公共方法
$success = build_upload('avatar');
if($success['result'])
{
//上传成功
$data['avatar'] = $success['data'];
}else
{
//上传失败
$this->error($success['msg']);
exit;
}
}
//准备更新数据库
$result = $this->BusinessModel->validate('common/Business/Business.ShopProfile')->isUpdate(true)->save($data);
if($result === FALSE)
{
$this->error($this->BusinessModel->getError());
exit;
}else
{
//更新资料成功
//删除旧图片,更新cookie
if(isset($data['avatar']))
{
//判断旧图片是否存在,如果存在就删除掉
@is_file(".".$business['avatar']) && unlink(".".$business['avatar']);
}
//查询一次最新的数据出来,并返回
$update = $this->BusinessModel->find($id);
$this->success('修改成功', '/business/base/index', $update);
exit;
}
}
}
邮箱验证
省略:装api接口,安装路由
在首页页面中:
路径 - - rent老师\src\components\business\base\index.js
const Email = () => {
// 未认证
if(LoginAuth.status != 1)
{
return (
<div className="my_dind">
<div className="bt">
<React.$Router.NavLink to="/business/base/ems">
<h3><img src="/assets/images/my_x_01.png" alt="" />邮箱认证</h3>
<div className="right">
<img src="/assets/images/right_jiant.png" alt="" />
</div>
</React.$Router.NavLink>
</div>
</div>
)
}else
{
return (
<></>
)
}
}
邮箱组件 + 验证码:
验证码:点击获取验证码的时候,触发send发送事件,并且其为禁止点击,设置定时器进行60s倒计时。
//设置状态数据
const [LoginAuth, SetLoginAuth] = React.useState(React.$LoginAuth)
const [msg, SetMsg] = React.useState('发送验证码')
const [disabled, SetDisabled] = React.useState(false)
{msg}是上面的const–msg数据
验证码:
<React.$Vant.Form.Item
name="code"
label="验证码"
rules={[
{required:true, message: '请输入邮箱'}
]}
>
<React.$Vant.Field
placeholder="请输入邮箱验证码"
suffix={
<React.$Vant.Button size="small" type="primary" disabled={disabled} onClick={send}>{msg}</React.$Vant.Button>
}
/>
</React.$Vant.Form.Item>
点击发送验证码之后,触发send点击事件:
const send = async () =>
{
//先组装数据
var data = {
id: LoginAuth.id
}
//调用后端sendmsg()发送验证码方法
var result = await React.$API.sendems(data)
//如果发送验证码成功
if(result.code)
{
React.$Vant.Notify.show({
type:'success',
message: result.msg
})
}else
{
React.$Vant.Notify.show({
type:'danger',
message: result.msg
})
}
//定时器
var sec = 60
let T = setInterval(() => {
// 修改msg内容
SetMsg(`${sec} s`)
//设置按钮禁用
SetDisabled(true)
//停止定时器
if(sec <= 0)
{
clearInterval(T)
sec = 60
SetDisabled(false)
SetMsg('重新发送验证码')
return false
}else
{
sec--
}
}, 10)
}
后端发送验证码方法:
/**
* 发送邮箱验证码
*/
public function sendems()
{
if($this->request->isAjax())
{
//接收id
$id = $this->request->param('id', 0, 'trim');
//判断一下 有没有这个人
$business = $this->BusinessModel->find($id);
if(!$business)
{
$this->error('用户不存在');
exit;
}
$email = trim($business['email']);
//判断邮箱是否为空
if(empty($email))
{
$this->error('邮箱为空,无法验证,请先更新邮箱地址');
exit;
}
//生成一个新的验证码
$code = build_ranstr(6);
//组装数据
$data = [
'event' => 'EmailCheck', //自定义
'email' => $email,
'code' => $code,
];
//要将发送成功的验证码插入到数据中
//开启事务
$this->EMSModel->startTrans();
//插入数据
$result = $this->EMSModel->save($data);
if($result === FALSE)
{
$this->error('验证码添加失败');
exit;
}
//调用方法
$success = send_email($email, $code);
//邮件发送失败
if(!$success['result'])
{
//回滚插入的验证码记录
$this->EMSModel->rollback();
$this->error($success['msg']);
exit;
}else
{
//提交事务
$this->EMSModel->commit();
$this->success('验证码发送成功,请注意查收');
exit;
}
}
}
提交表单验证邮箱
表单组件:
<React.$Vant.Form form={form} onFinish={ems}>
......
</React.$Vant.Form>
提交后触发ems事件:
const ems = async (form) =>
{
// 组装数据
var data = {
id: LoginAuth.id,
code: form.code
}
//调用接口
var result = await React.$API.checkems(data)
if(result.code)
{
React.$Vant.Notify.show({
type:'success',
message: result.msg,
duration: 1000,
onClose: () => {
// 重新覆盖cookie
React.$Cookie.save('LoginAuth', result.data)
React.$LoginAuth = result.data
navigate(-1)
}
})
}else
{
React.$Vant.Notify.show({
type:'danger',
message: result.msg
})
}
}
后端验证邮箱的方法:
/**
* 验证邮箱
*/
public function checkems()
{
if($this->request->isAjax())
{
$id = $this->request->param('id', 0, 'trim');
$code = $this->request->param('code', 0, 'trim');
//判断用户是否存在
$business = $this->BusinessModel->find($id);
if(!$business)
{
$this->error('用户不存在');
exit;
}
if(empty($business['email']))
{
$this->error('您的邮箱为空,请先修改邮箱');
exit;
}
if($business['status'])
{
$this->error('您已通过邮箱验证,无须重复验证');
exit;
}
//根据条件查询出验证码记录
$where = [
'email'=>$business['email'],
'code' => $code
];
$ems = $this->EMSModel->where($where)->find();
if(!$ems)
{
$this->error("验证码有误,请重新输入");
exit;
}
// 验证码的时间 验证码失效时间
$checktime = $ems['createtime'] + 3600*24;
if($checktime < time())
{
//直接删除
$this->EMSModel->destroy($ems['id']);
$this->error('验证码过期');
exit;
}
//更新验证状态
// 1.更新用户表 2.验证码的删除
$this->BusinessModel->startTrans();
$this->EMSModel->startTrans();
//更新用户表
$BusessinData = [
'id' => $business['id'],
'status' => 1
];
$BusessinStatus = $this->BusinessModel->isUpdate(true)->save($BusessinData);
if($BusessinStatus === FALSE)
{
$this->error('更新用户验证状态失败');
exit;
}
//删除验证记录
$EMStatus = $this->EMSModel->destroy($ems['id']);
if($EMStatus === FALSE)
{
$this->BusinessModel->rollback();
$this->error('验证码删除失败');
exit;
}
if($BusessinStatus === FALSE || $EMStatus === FALSE)
{
$this->EMSModel->rollback();
$this->BusinessModel->rollback();
$this->error('验证失败');
exit;
}else
{
//提交事务
$this->BusinessModel->commit();
$this->EMSModel->commit();
//查询一次最新的数据出来,并返回
$update = $this->BusinessModel->find($id);
$this->success('邮箱验证成功', null, $update);
exit;
}
}
}
文章列表
做上拉加载,下拉刷新效果
需要用到分页,先引入:
const [page, SetPage] = React.useState(1)
文章列表组件:
触发下拉加载,下拉刷新 :refresh事件
{/* 文章列表 */}
<React.$Vant.PullRefresh
onRefresh={refresh}
>
<React.$Vant.List className="catelist" finished={finished} onLoad={load} offset={5} loading={loading} autoCheck={false}>
<Items />
</React.$Vant.List>
</React.$Vant.PullRefresh>
</div>
refresh事件:
设置定时器:1s后完成,并且提示信息,先需要把列表数据和分页数据清空
// 刷新
const refresh = async () =>
{
//清空列表数据
SetList([])
//设置分页数据为第一页,刷新后回到第一页
SetPage(1)
SetFinished(false)
return new Promise((resolve) => {
setTimeout(() => {
//调用ListData()函数
ListData()
React.$Vant.Toast.info('刷新成功')
resolve(true)
}, 1000)
})
}
页面详细信息
解析数据库的html标签输出
react输出描述内容 用dangerouslySetInnerHTML 解析html标签:
<div className="wom_de" dangerouslySetInnerHTML={{__html:info.description}}></div>
页面上下篇
组件使用:
<div className="shangxia_piab">
<PrevCate />
<NextCate />
</div>
上一篇 方法:
首先,每次点击外部的时候,都是需要获取id,因此初始化路由参数对象 - - 获取id
const [id, SetID] = useState(searchParams.get('id'))
const PrevCate = () =>
{
//定义ToPrev,链接跳转后 刷新navigate(0)
let ToPrev = () =>
{
SetID(prev.id)
navigate(`/business/category/info?id=${prev.id}`)
navigate(0)
}
//如果有数据 ,则点击返回上一篇
if(prev)
{
return (
<p>上一篇:
<a onClick={ToPrev}>{prev.name}</a>
</p>
)
}else
{
return (
<p>上一篇:已经到顶了</p>
)
}
}
下一篇同理。
数据输出时
//初始化路由参数对象
const [info, SetInfo] = React.useState({})
组件:info.()输出信息 –
<div className="bt">
<h2>{info.name}</h2>
<div className="text">
<span>{info.createtime_text}</span>
<span>文章作者:{info.nickname}</span>
</div>
</div>
轮播图
轮播图组件:
{/* banner 图片 */}
<div className="banner_shouy">
<React.$Vant.Swiper>
{Banner()}
</React.$Vant.Swiper>
</div>
Banner方法:
const Banner = () => {
if (hot) {
return hot.map((item, index) => {
return (
<React.$Vant.Swiper.Item key={index}>
<React.$Router.NavLink to={`/business/category/info?id=${item.id}`}>
<img alt="" src={item.image_text} />
</React.$Router.NavLink>
</React.$Vant.Swiper.Item>
)
})
}
}
产品中心
组件:
<React.$Vant.ActionBar>
<React.$Vant.ActionBar.Icon text="首页" icon={<React.$Icon.ShopO />} onClick={home} />
{check()}
<React.$Vant.ActionBar.Button type="danger" text="立即租赁" onClick={lease} />
</React.$Vant.ActionBar>
首页跳转:
const home = () =>
{
navigate('/')
}
收藏:
走验证场景验证器:
模型:
/**
* 验证场景
*/
protected $scene = [
//我们根据业务场景 分配了不同 验证模式 自定义
'category' => ['busid', 'cateid'],
'product' => ['busid', 'proid']
];
控制器:
$result = $this->CollectionModel->validate('common/Business/Collection.category')->save($data);
收藏与取消收藏:
因为收藏与取消收藏是需要登录后才可以进行的操作,并且还需要知道操作是进行的是收藏 还是 取消收藏。
组件用checked :
添加 collection:
const [collection, SetCollection] = React.useState(false)
collection从后端产品中获取的数据:
const check = () =>
{
if(collection)
{
return (
<React.$Vant.ActionBar.Icon text="已收藏" icon={<React.$Icon.Star color="#f44336" />} onClick={cancel} />
)
}else
{
return (
<React.$Vant.ActionBar.Icon text="收藏" icon={<React.$Icon.StarO />} onClick={Collection} />
)
}
}
收藏:
调用后端接口:
// 收藏
const Collection = async () =>
{
if(!LoginAuth || JSON.stringify(LoginAuth) === "{}")
{
React.$Vant.Toast.info('请先登录')
return false
}
//组装数据
var data = {
busid: LoginAuth.id,
proid: pid
}
var result = await React.$API.ProductCollection(data)
if(result.code)
{
React.$Vant.Notify.show({
type:'success',
message: result.msg,
duration: 1000,
onClose: () => {
SetCollection(true)
}
})
}else
{
React.$Vant.Notify.show({
type:'danger',
message: result.msg
})
}
}
收藏的后端代码:
// 收藏方法
public function collection()
{
if($this->request->isPost())
{
$proid = $this->request->param('proid', 0, 'trim');
$busid = $this->request->param('busid', 0, 'trim');
//先找出商品是否存在
$product = $this->ProductModel->find($proid);
if(!$product)
{
$this->error('收藏商品不存在');
exit;
}
//组装数据
$data = [
'busid' => $busid,
'proid' => $proid
];
$result = $this->CollectionModel->validate('common/Business/Collection.product')->save($data);
if($result === FALSE)
{
$this->error($this->CollectionModel->getError());
exit;
}else
{
$this->success('收藏成功');
exit;
}
}
}
取消收藏调用接口:
//取消收藏
let cancel = async () =>
{
//组装数据
var data = {
proid: pid,
busid: LoginAuth.id
}
var result = await React.$API.ProductCancel(data)
if(result.code)
{
React.$Vant.Notify.show({
type:'success',
message: result.msg,
duration: 1000,
onClose: () => {
SetCollection(false)
}
})
}else
{
React.$Vant.Notify.show({
type:'danger',
message: result.msg
})
}
}
取消收藏的后端代码:
// 取消收藏方法
public function cancel()
{
$proid = $this->request->param('proid', 0, 'trim');
$busid = $this->request->param('busid', 0, 'trim');
//先找出商品是否存在
$product = $this->ProductModel->find($proid);
if(!$product)
{
$this->error('收藏商品不存在');
exit;
}
//组装数据
$where = [
'busid' => $busid,
'proid' => $proid
];
//删除记录
$result = $this->CollectionModel->destroy($where);
if($result === FALSE)
{
$this->error($this->CollectionModel->getError());
exit;
}else
{
$this->success('取消收藏成功');
exit;
}
}