refactor(api):

- 重构 API模块,将 API 按模块进行组织
- 登录,完成手机号登录页、添加备案号、及密码手机号登录切换,添加注册入口
- 更新iconfont图标
- 退出登录清缓存管理掉账号密码手机号
- 添加商品列表页和详情页,登录进入改为商品页
This commit is contained in:
fhysy 2025-03-04 15:57:57 +08:00
parent 38b17951cf
commit a7454355f4
13 changed files with 2091 additions and 582 deletions

View File

@ -1,8 +1,10 @@
import {request} from './request.js'
export default{
// 商品
productApi:require("./module/productApi.js").default,
// 订单,模块
orderApi:require("./orderApi.js").default,
orderApi:require("./module/orderApi.js").default,
/*
* 登录相关
*/
@ -67,4 +69,14 @@ export default{
})
})
},
getSmsCode(data) {// 获取短信验证码
return new Promise((resolve, reject) => {
request.get('/resource/sms/code',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
}

View File

@ -1,4 +1,4 @@
import {request} from './request'
import {request} from '../request'
export default {
// 获取订单列表
getOrderList(data){

View File

@ -0,0 +1,147 @@
import {request} from '../request'
export default {
// 获取商品列表
getProductList(data){
return new Promise((resolve, reject) => {
request.get('/mall/product/list',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 获取商品详情
getProductDetail(id){
return new Promise((resolve, reject) => {
request.get('/mall/product/' + id)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 获取订单商品列表
getMallclientOrderProductList(data){
return new Promise((resolve, reject) => {
request.get('/mallclient/clientorderItem/list',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 查询订单商品素材模板列表
getProductMaterialDictList(data){
return new Promise((resolve, reject) => {
request.get('/mall/materialDict/listWithProduct',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 查询订单商品素材列表(已有)
getMallOrderProductMaterialList(data){
return new Promise((resolve, reject) => {
request.get('/mall/material/list',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 查询订单商品素材模板素材项列表
getProductMaterialDictItemList(data){
return new Promise((resolve, reject) => {
request.get('/mall/materialTemplate/listById',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 删除文件
delOssFile(id){
console.log("id",id)
return new Promise((resolve, reject) => {
request.delete('/resource/oss/' + id)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 订单素材列表(流程)
getOrderMaterialList(data){
return new Promise((resolve, reject) => {
request.get('/mall/orderMaterial/list',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 新增订单素材(流程)
AddOrderMaterial(data){
return new Promise((resolve, reject) => {
request.post('/mall/orderMaterial',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 修改素材(批量)
mallMaterialUpdateBatch(data){
return new Promise((resolve, reject) => {
request.put('/mall/material/updateBatch',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 提交商品素材列表(完成)
mallMaterialCommit(orderId,productId){
return new Promise((resolve, reject) => {
request.put('/mall/material/commit/' + orderId + '/' + productId)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 启动任务(流程)
startWorkFlow(data){
return new Promise((resolve, reject) => {
request.post('/workflow/task/startWorkFlow',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
// 办理流程(流程)
completeTask(data){
return new Promise((resolve, reject) => {
request.post('/workflow/task/completeTask',data)
.then((res) =>{
resolve(res);
}).catch(err =>{
reject(err);
})
})
},
}

View File

@ -10,6 +10,13 @@
"navigationBarBackgroundColor": "#1890ff"
}
},
{
"path": "pages/auth/codeLogin",
"style": {
"navigationBarTitleText": "手机号注册/登录",
"navigationBarBackgroundColor": "#1890ff"
}
},
{
"path": "pages/auth/login",
"style": {
@ -24,6 +31,13 @@
// "navigationStyle": "custom"
}
},
{
"path": "pages/tabBar/product",
"style": {
"navigationBarTitleText": "商品"
// "navigationStyle": "custom"
}
},
{
"path": "pages/tabBar/order",
"style": {
@ -636,6 +650,22 @@
"navigationBarTitleText": "素材上传",
"navigationBarBackgroundColor": "#fff"
}
},{
"path": "videoView",
"style": {
"navigationBarTitleText": "视频预览",
"navigationBarBackgroundColor": "#fff"
}
}]
},
{
"root": "pages/product/",
"pages": [{
"path": "detail",
"style": {
"navigationBarTitleText": "商品详情",
"navigationBarBackgroundColor": "#fff"
}
}]
}
],
@ -648,6 +678,11 @@
"text": "消息",
"iconPath": "static/images/toolbar/new.png",
"selectedIconPath": "static/images/toolbar/new-active.png"
}, {
"pagePath": "pages/tabBar/product",
"text": "商品",
"iconPath": "static/images/toolbar/product.png",
"selectedIconPath": "static/images/toolbar/product-active.png"
}, {
"pagePath": "pages/tabBar/order",
"text": "订单",
@ -673,6 +708,23 @@
"path": "pages/auth/passwordLogin",
"name": "默认页面" //
},
{
"path": "pages/auth/codeLogin",
"name": "验证码登录" //
},
{
"path": "pages/fun/videoView",
"name": "预览" //
},
{
"path": "pages/tabBar/product",
"name": "商品" //
},
{
"path": "pages/product/detail",
"name": "商品详情" ,//
"query": "id=1888110308906405890"
},
{
"path": "pages/tabBar/order",
"name": "订单" //

607
pages/auth/codeLogin.vue Normal file
View File

@ -0,0 +1,607 @@
<template>
<view class="login-ctn">
<view class="login-bg">
<image src="http://static.drgyen.com/app/hc-app-power/images/login-header.png" mode=""></image>
</view>
<view class="login-header">
<view class="login-header-img-box">
<!-- #ifdef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
</view>
<view class="login-header-text">{{appConfig.name}}</view>
</view>
<view class="login-form-ctn">
<view class="login-form">
<u-form :model="form" :rules="rules" ref="uForm">
<u-form-item v-if="tenantEnabled && isTenant" label=" " label-width="60" prop="tenantId" left-icon="home"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<view style="width: 100%;display: flex;align-items: center;justify-content: space-between;" @click="tenantShow=true">
<text>{{activeTenantObj.companyName}}</text>
<u-icon name="arrow-down"></u-icon>
</view>
</u-form-item>
<u-form-item label=" " label-width="60" prop="phonenumber" left-icon="account"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<u-input v-model="form.phonenumber" placeholder="请输入手机号" />
</u-form-item>
<u-form-item label=" " label-width="60" prop="smsCode" left-icon="phone"
:left-icon-style="{ color: '#ccc', fontSize: '34rpx' }">
<u-button slot="right" type="primary" :loading="smsLoading" size="mini" @click="getCode">{{smsLoading?'获取验证码中...':'获取验证码'}}</u-button>
<u-input v-model="form.smsCode" placeholder="请输入验证码" />
</u-form-item>
</u-form>
<!-- <view class="login-function-ctn" v-if="current===0">
<text class="text--base--grey" @click="goForgotPasswordFn">忘记密码?</text>
</view> -->
<view class="login-button-ctn">
<u-button shape="circle" :loading="loading" :custom-style="{ background: 'linear-gradient(270deg, #0066CC 8%, #1890FF 100%)' , height:'100rpx' }"
@click="submit" type="primary">登录未注册自动注册</u-button>
</view>
<view class="protocol-box">
<!-- <u-checkbox v-model="protocolStatus">阅读并同意以下协议<text @click.stop="goPolicy">用户协议</text></u-checkbox> -->
</view>
<view class="other-login-box">
<view class="other-login-item" @click="goPasswordLogin">
<view class="other-login-bg">
<u-icon name="lock-fill" color="#fff" size="56"></u-icon>
</view>
<text class="other-login-name">密码登录</text>
</view>
</view>
</view>
</view>
<view class="login-version-info">
<view>Copyright 2022-2025. {{ icpLicense ? ' 备案号:' + icpLicense : '' }}</view>
</view>
<u-select v-model="tenantShow" :list="tenantList" label-name="companyName" value-name="tenantId" @confirm="changeTenant"></u-select>
<u-toast ref="uToast" />
</view>
</template>
<script>
let userToken = '';
import config from "@/common/api/config.js"
export default {
data() {
return {
protocolStatus: true,
usetTypeValue: '企业用户',
list: [{
name: '普通用户',
},
{
name: '企业用户',
}
],
captchaData: null,
current: 0,
form: {
clientId: "",
grantType: "sms",
rememberMe: false,
tenantId: "",
phonenumber: "",
smsCode: ""
},
mode:null,
rules: {
// 190
phonenumber: [{
required: true,
message: '请输入手机号',
trigger: ['change', 'blur'],
}],
smsCode: [{
required: true,
message: '请输入验证码',
trigger: ['change', 'blur'],
}],
code: [{
required: true,
message: '请输入验证码',
trigger: ['change', 'blur'],
}]
},
tenantShow:false,
tenantList:[],
activeTenantObj:{
tenantId: "",
companyName: "",
domain: "",
logo: null,
registerEnable: false
},
//
tenantEnabled:true,
query:{},
isTenant: true,
appid:'',
smsLoading:false,
loading:false,
icpLicense:'',
}
},
computed: {
appConfig() {
return this.$store.state.app.appConfig
},
},
onLoad(e) {
// #ifdef MP-WEIXIN
const accountInfo = uni.getAccountInfoSync();
this.appid = accountInfo.miniProgram.appId;
// #endif
if(e){
this.query = e;
}
if(e.tenantId){
this.form.tenantId = e.tenantId;
}
//
if (e.q && e.q != "undefined") { //
const qrUrl = decodeURIComponent(e.q) //
//GetWxMiniProgramUrlParam()
e = this.GetWxMiniProgramUrlParam(qrUrl); // json
}
console.log("当前参数",e)
if(e.mode){
this.mode = e.mode;
}
this.getTenantList();
if(e.mode == '1'){ //mode:1
this.form.phonenumber = e.user || '';
// this.autoLogin()
}else{
userToken = uni.getStorageSync('userToken');
console.log("userToken", userToken)
if (userToken) {
uni.switchTab({
url: "../tabBar/product"
})
} else {
// this.getCode();
}
}
this.usetTypeValue = e.userType == "user" ? "普通用户" : "企业用户";
},
onShow() {
if(this.mode != '1'){
uni.getStorage({
key: 'phonenumber',
}).then(res => {
//
if (res.length == 2) {
this.form.phonenumber = res[1].data;
}
})
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
methods: {
getTenantList(){
uni.request({
url: config.baseUrl + "/auth/tenant/list",
method: "GET",
data: {},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log("res11",res);
if(res.data.code == 200){
let data = res.data.data;
this.tenantEnabled = data.tenantEnabled === undefined ? true : data.tenantEnabled;
if(this.tenantEnabled){
this.tenantList = data.voList || [];
let logo = '';
let title = '';
let icpLicense = '';
// #ifdef H5
if(this.query.tenantId){
this.form.tenantId = this.query.tenantId;
data.voList.forEach((item) => {
if (item.tenantId === this.query.tenantId) {
logo = item.logo;
title = item.companyName;
icpLicense = item.icpLicense || '';
}
});
this.isTenant = false;
} else if (data.voList != null && data.voList.length === 1 && data.voList[0].domain === window.location.host) {
this.form.tenantId = data.voList[0].tenantId;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
this.isTenant = false;
} else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
}
// #endif
// #ifdef MP-WEIXIN
if(this.appid){
let isAppid = true;
data.voList.forEach((item) => {
if (item.appId === this.appid) {
this.form.tenantId = item.tenantId;
logo = item.logo;
title = item.companyName;
icpLicense = item.icpLicense || '';
isAppid = false;
}
});
if(isAppid){
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0];
icpLicense = data.voList[0].icpLicense || '';
logo = data.voList[0].logo;
title = data.voList[0].companyName;
}else{
this.isTenant = false;
}
}else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
}
// #endif
if(title){
this.appConfig.logo = logo;
this.appConfig.name = title;
}else{
this.appConfig.logo = '';
this.appConfig.name = this.$store.state.app.appConfig;
}
if(icpLicense){
this.icpLicense = icpLicense;
}
}
}
}
});
},
changeTenant(e){
console.log("e",e[0].value)
this.tenantList.forEach((item) => {
if (item.tenantId == e[0].value) {
this.activeTenantObj = item;
this.form.tenantId = item.tenantId;
this.appConfig.logo = item.logo;
this.appConfig.name = item.companyName;
this.icpLicense = item.icpLicense || '';
}
});
},
GetWxMiniProgramUrlParam(url) {
let theRequest = {};
if (url.indexOf("#") != -1) {
const str = url.split("#")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
} else if (url.indexOf("?") != -1) {
const str = url.split("?")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
}
return theRequest;
},
//
goPasswordLogin(){
uni.reLaunch({
url: './passwordLogin'
});
},
goPolicy() {
uni.navigateTo({
url: '/pages/tabBar/my/userPolicy'
})
},
goForgotPasswordFn() {
uni.navigateTo({
url: `./forgotPassword?userType=${this.usetTypeValue=="普通用户"?"user":"company"}`
})
},
//
getCode() {
if(this.$u.test.mobile(this.form.phonenumber)){
this.smsLoading = true;
this.$api.getSmsCode({ phonenumber: this.form.phonenumber }).then((res) => {
console.log(res, "resss");
if(res.code == 200){
this.$refs.uToast.show({
title: '验证码发送成功',
type: 'success',
})
}
this.smsLoading = false;
}).catch((err)=>{
this.$refs.uToast.show({
title: err,
type: 'error',
})
this.smsLoading = false;
})
}else{
this.$refs.uToast.show({
title: '请输入正确的手机号格式',
type: 'error',
})
}
},
//
autoLogin(){
uni.request({
url: config.baseUrl + "/login",
method: "POST",
data: {
phonenumber: this.form.phonenumber,
smsCode: this.form.smsCode,
},
header: {
UserType: this.usetTypeValue == "普通用户" ? "PERSONAL" : "TENANT",
},
success: (res) => {
console.log(res);
if (res.data.token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.token);
uni.setStorage({
key: 'userType',
data: this.usetTypeValue,
}).then(res => {
return uni.setStorage({
key: 'phonenumber',
data: this.form.phonenumber,
})
}).then(res => {
return uni.setStorage({
key: 'smsCode',
data: this.form.smsCode,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/product"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCode();
}
}
});
},
submit() {
if(!this.protocolStatus){
this.$refs.uToast.show({
title: '请先阅读并同意用户协议',
})
}else{
this.$refs.uForm.validate(valid => {
if (valid) {
this.loading = true;
uni.request({
url: config.baseUrl + "/auth/login",
method: "POST",
data: {
...this.form,
clientId: config.clientId,
},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log(res);
if (res.data.code == 200 && res.data.data.access_token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.data.access_token);
uni.setStorage({
key: 'userType',
data: this.usetTypeValue,
}).then(res => {
return uni.setStorage({
key: 'phonenumber',
data: this.form.phonenumber,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/product"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCode();
}
this.loading = false;
},
fail() {
this.loading = false;
}
});
} else {
console.log('验证失败');
}
});
}
}
}
}
</script>
<style lang="scss" scoped>
.login-ctn {
width: 100%;
height: 100%;
padding-top: 500rpx;
background: #fff;
:not(not) {
box-sizing: border-box;
}
}
.login-bg {
width: 100%;
height: 515rpx;
position: absolute;
left: 0;
top: 0;
z-index: 1;
image {
width: 100%;
height: 100%;
}
}
.login-header {
width: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 10;
height: 500rpx;
display: flex;
flex-direction: column;
align-items: center;
.login-header-img-box {
margin-top: 132rpx;
margin-left: 2rpx;
border-radius: 50%;
background: #FFFFFF;
}
&-img {
display: block;
width: 198rpx;
height: 198rpx;
}
&-text {
font-size: 40rpx;
line-height: 40rpx;
font-family: Source Han Sans CN;
font-weight: 500;
color: #FFFFFF;
margin-top: 40rpx;
}
}
.login-form-ctn {
margin-bottom: 20rpx;
.login-form {
background-color: #fff;
padding: 20rpx 60rpx;
&-title {
text-align: center;
font-size: 40rpx;
font-family: Source Han Sans CN;
font-weight: 800;
color: #262626;
}
}
}
.login-button-ctn {
margin-top: 20rpx;
}
.login-function-ctn {
display: flex;
justify-content: flex-end;
padding: 30rpx 0rpx;
}
.login-version-info {
position: absolute;
left: 0;
bottom: 40rpx;
width: 100%;
text-align: center;
font-size: $uni-font-size-sm;
color: #aaa;
}
.protocol-box {
padding: 20rpx 0;
color: #f5f5f5;
font-size: 26rpx;
text {
color: #0066cc;
}
}
.other-login-box {
margin-top: 20rpx;
display: flex;
justify-content: center;
align-items: center;
.other-login-item {
.other-login-bg {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background: #0066cc;
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 10rpx;
}
.other-login-name {
color: #7d7d7d;
font-weight: bold;
}
}
}
</style>

View File

@ -1,3 +1,469 @@
<template>
<view class="login-ctn">
<view class="login-bg">
<image src="http://static.drgyen.com/app/hc-app-power/images/login-header.png" mode=""></image>
</view>
<view class="login-header">
<view class="login-header-img-box">
<!-- #ifdef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
</view>
<view class="login-header-text">{{appConfig.name}}</view>
</view>
<view class="login-form-ctn">
<view class="login-form">
<u-form :model="form" :rules="rules" ref="uForm">
<u-form-item v-if="tenantEnabled && isTenant" label=" " label-width="60" prop="tenantId" left-icon="account"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<view style="width: 100%;display: flex;align-items: center;justify-content: space-between;" @click="tenantShow=true">
<text>{{activeTenantObj.companyName}}</text>
<u-icon name="arrow-down"></u-icon>
</view>
</u-form-item>
<u-form-item label=" " label-width="60" prop="username" left-icon="account"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<u-input v-model="form.username" placeholder="请输入手机号/账号" />
</u-form-item>
<u-form-item label=" " label-width="60" prop="password" left-icon="lock-open"
:left-icon-style="{ color: '#ccc', fontSize: '36rpx' }">
<u-input class="password-input" v-model="form.password" type="password" placeholder="请输入密码" />
</u-form-item>
<!-- <u-form-item label=" " label-width="60" prop="code" left-icon="chat"
:left-icon-style="{ color: '#ccc', fontSize: '34rpx' }">
<u-image slot="right" mode="scaleToFill" width="160" height="60" @click="getCodeImageFn"
:src="'data:image/jpg;base64,' + captchaData.img"></u-image>
<u-input v-model="form.code" placeholder="请输入验证码" />
</u-form-item> -->
</u-form>
<view class="login-function-ctn">
<text class="text--base--grey" @click="goPhoneLogin">我要注册</text>
</view>
<view class="login-button-ctn">
<u-button shape="circle" :custom-style="{ background: 'linear-gradient(270deg, #0066CC 8%, #1890FF 100%)' , height:'100rpx' }"
@click="submit" type="primary">立即登录</u-button>
</view>
<view class="protocol-box">
<!-- <u-checkbox v-model="protocolStatus">阅读并同意以下协议<text @click.stop="goPolicy">用户协议</text></u-checkbox> -->
</view>
<view class="other-login-box">
<view class="other-login-item" @click="goPhoneLogin">
<view class="other-login-bg">
<u-icon name="phone-fill" color="#fff" size="56"></u-icon>
</view>
<text class="other-login-name">手机登录</text>
</view>
</view>
</view>
</view>
<view class="login-version-info">
<view>Copyright 2022-2025. {{ icpLicense ? ' 备案号:' + icpLicense : '' }}</view>
</view>
<u-select v-model="tenantShow" :list="tenantList" label-name="companyName" value-name="tenantId" @confirm="changeTenant"></u-select>
<u-toast ref="uToast" />
</view>
</template>
<script>
let userToken = '';
import config from "@/common/api/config.js"
export default {
data() {
return {
protocolStatus: true,
usetTypeValue: '企业用户',
list: [{
name: '普通用户',
},
{
name: '企业用户',
}
],
captchaData: null,
current: 0,
form: {
clientId: "",
grantType: "password",
rememberMe: false,
tenantId: "",
username: "",
password: ""
},
mode:null,
rules: {
//
username: [{
required: true,
message: '请输入手机号/账号',
trigger: ['change', 'blur'],
}],
password: [{
required: true,
message: '请输入密码',
trigger: ['change', 'blur'],
}],
code: [{
required: true,
message: '请输入验证码',
trigger: ['change', 'blur'],
}]
},
tenantShow:false,
tenantList:[],
activeTenantObj:{
tenantId: "",
companyName: "",
domain: "",
logo: null,
registerEnable: false
},
//
tenantEnabled:true,
query:{},
isTenant: true,
appid:'',
icpLicense:'',
}
},
computed: {
appConfig() {
return this.$store.state.app.appConfig
},
},
onLoad(e) {
// #ifdef MP-WEIXIN
const accountInfo = uni.getAccountInfoSync();
this.appid = accountInfo.miniProgram.appId;
// #endif
if(e){
this.query = e;
}
if(e.tenantId){
this.form.tenantId = e.tenantId;
}
//
if (e.q && e.q != "undefined") { //
const qrUrl = decodeURIComponent(e.q) //
//GetWxMiniProgramUrlParam()
e = this.GetWxMiniProgramUrlParam(qrUrl); // json
}
console.log("当前参数",e)
if(e.mode){
this.mode = e.mode;
}
this.getTenantList();
if(e.mode == '1'){ //mode:1
this.form.username = e.user || '';
this.form.password = e.pwd || '';
this.autoLogin()
}else{
userToken = uni.getStorageSync('userToken');
console.log("userToken", userToken)
if (userToken) {
uni.switchTab({
url: "../tabBar/product"
})
} else {
// this.getCodeImageFn();
}
}
this.usetTypeValue = e.userType == "user" ? "普通用户" : "企业用户";
},
onShow() {
if(this.mode != '1'){
uni.getStorage({
key: 'username',
}).then(res => {
//
if (res.length == 2) {
this.form.username = res[1].data;
}
return uni.getStorage({
key: 'password',
})
}).then(res => {
if (res.length == 2) {
this.form.password = res[1].data;
}
})
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
methods: {
getTenantList(){
uni.request({
url: config.baseUrl + "/auth/tenant/list",
method: "GET",
data: {},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log("res11",res);
if(res.data.code == 200){
let data = res.data.data;
this.tenantEnabled = data.tenantEnabled === undefined ? true : data.tenantEnabled;
if(this.tenantEnabled){
this.tenantList = data.voList || [];
let logo = '';
let title = '';
let icpLicense = '';
// #ifdef H5
if(this.query.tenantId){
this.form.tenantId = this.query.tenantId;
data.voList.forEach((item) => {
if (item.tenantId === this.query.tenantId) {
logo = item.logo;
title = item.companyName;
icpLicense = item.icpLicense || '';
}
});
this.isTenant = false;
} else if (data.voList != null && data.voList.length === 1 && data.voList[0].domain === window.location.host) {
this.form.tenantId = data.voList[0].tenantId;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
this.isTenant = false;
} else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
}
// #endif
// #ifdef MP-WEIXIN
if(this.appid){
let isAppid = true;
data.voList.forEach((item) => {
if (item.appId === this.appid) {
console.log("appId",item)
this.form.tenantId = item.tenantId;
logo = item.logo;
title = item.companyName;
icpLicense = item.icpLicense || '';
isAppid = false;
}
});
if(isAppid){
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
}else{
this.isTenant = false;
}
}else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
icpLicense = data.voList[0].icpLicense || '';
}
// #endif
console.log("title",title,logo)
if(title){
this.appConfig.logo = logo;
this.appConfig.name = title;
}else{
this.appConfig.logo = '';
this.appConfig.name = this.$store.state.app.appConfig;
}
if(icpLicense){
this.icpLicense = icpLicense;
}
}
}
}
});
},
changeTenant(e){
console.log("e",e[0].value)
this.tenantList.forEach((item) => {
if (item.tenantId == e[0].value) {
this.activeTenantObj = item;
this.form.tenantId = item.tenantId;
this.appConfig.logo = item.logo;
this.appConfig.name = item.companyName;
this.icpLicense = item.icpLicense || '';
}
});
},
GetWxMiniProgramUrlParam(url) {
let theRequest = {};
if (url.indexOf("#") != -1) {
const str = url.split("#")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
} else if (url.indexOf("?") != -1) {
const str = url.split("?")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
}
return theRequest;
},
//
goPhoneLogin(){
uni.reLaunch({
url: './codeLogin'
});
},
goPolicy() {
uni.navigateTo({
url: '/pages/tabBar/my/userPolicy'
})
},
goForgotPasswordFn() {
uni.navigateTo({
url: `./forgotPassword?userType=${this.usetTypeValue=="普通用户"?"user":"company"}`
})
},
//
getCodeImageFn() {
this.$get("/captchaImage").then((res) => {
console.log(res, "resss");
this.captchaData = res;
})
},
//
autoLogin(){
uni.request({
url: config.baseUrl + "/login",
method: "POST",
data: {
username: this.form.username,
password: this.form.password,
},
header: {
UserType: this.usetTypeValue == "普通用户" ? "PERSONAL" : "TENANT",
},
success: (res) => {
console.log(res);
if (res.data.token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.token);
uni.setStorage({
key: 'userType',
data: this.usetTypeValue,
}).then(res => {
return uni.setStorage({
key: 'username',
data: this.form.username,
})
}).then(res => {
return uni.setStorage({
key: 'password',
data: this.form.password,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/product"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCodeImageFn();
}
}
});
},
submit() {
if(!this.protocolStatus){
this.$refs.uToast.show({
title: '请先阅读并同意用户协议',
})
}else{
this.$refs.uForm.validate(valid => {
if (valid) {
uni.request({
url: config.baseUrl + "/auth/login",
method: "POST",
data: {
...this.form,
clientId: config.clientId,
},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log(res);
if (res.data.code == 200 && res.data.data.access_token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.data.access_token);
uni.setStorage({
key: 'tenantId',
data: this.form.tenantId,
}).then(res => {
return uni.setStorage({
key: 'username',
data: this.form.username,
})
}).then(res => {
return uni.setStorage({
key: 'password',
data: this.form.password,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/product"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCodeImageFn();
}
}
});
} else {
console.log('验证失败');
}
});
}
}
}
}
</script>
<style lang="scss" scoped>
.login-ctn {
width: 100%;
@ -82,7 +548,7 @@
.login-function-ctn {
display: flex;
justify-content: flex-end;
// justify-content: flex-end;
padding: 30rpx 0rpx;
}
@ -113,11 +579,14 @@
align-items: center;
.other-login-item {
display: flex;
flex-direction: column;
align-items: center;
.other-login-bg {
width: 100rpx;
height: 100rpx;
border-radius: 50%;
background: #07c160;
background: #0066cc;
display: flex;
justify-content: center;
align-items: center;
@ -130,459 +599,4 @@
}
}
}
</style>
<template>
<view class="login-ctn">
<view class="login-bg">
<image src="http://static.drgyen.com/app/hc-app-power/images/login-header.png" mode=""></image>
</view>
<view class="login-header">
<view class="login-header-img-box">
<!-- #ifdef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
<!-- #ifndef APP-PLUS -->
<image class="login-header-img" :src="appConfig.logo" mode=""></image>
<!-- #endif -->
</view>
<view class="login-header-text">{{appConfig.name}}</view>
</view>
<view class="login-form-ctn">
<view class="login-form">
<u-form :model="form" :rules="rules" ref="uForm">
<u-form-item v-if="tenantEnabled && isTenant" label=" " label-width="60" prop="tenantId" left-icon="account"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<view style="width: 100%;display: flex;align-items: center;justify-content: space-between;" @click="tenantShow=true">
<text>{{activeTenantObj.companyName}}</text>
<u-icon name="arrow-down"></u-icon>
</view>
</u-form-item>
<u-form-item label=" " label-width="60" prop="username" left-icon="account"
:left-icon-style="{ color: '#ccc', fontSize: '30rpx' }">
<u-input v-model="form.username" placeholder="请输入手机号/账号" />
</u-form-item>
<u-form-item label=" " label-width="60" prop="password" left-icon="lock-open"
:left-icon-style="{ color: '#ccc', fontSize: '36rpx' }">
<u-input class="password-input" v-model="form.password" type="password" placeholder="请输入密码" />
</u-form-item>
<!-- <u-form-item label=" " label-width="60" prop="code" left-icon="chat"
:left-icon-style="{ color: '#ccc', fontSize: '34rpx' }">
<u-image slot="right" mode="scaleToFill" width="160" height="60" @click="getCodeImageFn"
:src="'data:image/jpg;base64,' + captchaData.img"></u-image>
<u-input v-model="form.code" placeholder="请输入验证码" />
</u-form-item> -->
</u-form>
<!-- <view class="login-function-ctn" v-if="current===0">
<text class="text--base--grey" @click="goForgotPasswordFn">忘记密码?</text>
</view> -->
<view class="login-button-ctn">
<u-button shape="circle" :custom-style="{ background: 'linear-gradient(270deg, #0066CC 8%, #1890FF 100%)' , height:'100rpx' }"
@click="submit" type="primary">立即登录</u-button>
</view>
<view class="protocol-box">
<!-- <u-checkbox v-model="protocolStatus">阅读并同意以下协议<text @click.stop="goPolicy">用户协议</text></u-checkbox> -->
</view>
<!-- <view class="other-login-box">
<view class="other-login-item" @click="goWxLogin">
<view class="other-login-bg">
<u-icon name="weixin-fill" color="#fff" size="56"></u-icon>
</view>
<text class="other-login-name">微信登录</text>
</view>
</view> -->
</view>
</view>
<!-- <view class="login-version-info">
<view>Copyright 2022-2024 {{appConfig.companyName}} Powered By DSservice</view>
<view>{{appConfig.contractRecordNumber || ''}}</view>
</view> -->
<u-select v-model="tenantShow" :list="tenantList" label-name="companyName" value-name="tenantId" @confirm="changeTenant"></u-select>
<u-toast ref="uToast" />
</view>
</template>
<script>
let userToken = '';
import config from "@/common/api/config.js"
export default {
data() {
return {
protocolStatus: true,
usetTypeValue: '企业用户',
list: [{
name: '普通用户',
},
{
name: '企业用户',
}
],
captchaData: null,
current: 0,
form: {
clientId: "",
grantType: "password",
rememberMe: false,
tenantId: "",
username: "",
password: ""
},
mode:null,
rules: {
//
username: [{
required: true,
message: '请输入手机号/账号',
trigger: ['change', 'blur'],
}],
password: [{
required: true,
message: '请输入密码',
trigger: ['change', 'blur'],
}],
code: [{
required: true,
message: '请输入验证码',
trigger: ['change', 'blur'],
}]
},
tenantShow:false,
tenantList:[],
activeTenantObj:{
tenantId: "",
companyName: "",
domain: "",
logo: null,
registerEnable: false
},
//
tenantEnabled:true,
query:{},
isTenant: true,
appid:'',
}
},
computed: {
appConfig() {
return this.$store.state.app.appConfig
},
},
onLoad(e) {
// #ifdef MP-WEIXIN
const accountInfo = uni.getAccountInfoSync();
this.appid = accountInfo.miniProgram.appId;
// #endif
if(e){
this.query = e;
}
if(e.tenantId){
this.form.tenantId = e.tenantId;
}
//
if (e.q && e.q != "undefined") { //
const qrUrl = decodeURIComponent(e.q) //
//GetWxMiniProgramUrlParam()
e = this.GetWxMiniProgramUrlParam(qrUrl); // json
}
console.log("当前参数",e)
if(e.mode){
this.mode = e.mode;
}
this.getTenantList();
if(e.mode == '1'){ //mode:1
this.form.username = e.user || '';
this.form.password = e.pwd || '';
this.autoLogin()
}else{
userToken = uni.getStorageSync('userToken');
console.log("userToken", userToken)
if (userToken) {
uni.switchTab({
url: "../tabBar/order"
})
} else {
// this.getCodeImageFn();
}
}
this.usetTypeValue = e.userType == "user" ? "普通用户" : "企业用户";
},
onShow() {
if(this.mode != '1'){
uni.getStorage({
key: 'username',
}).then(res => {
//
if (res.length == 2) {
this.form.username = res[1].data;
}
return uni.getStorage({
key: 'password',
})
}).then(res => {
if (res.length == 2) {
this.form.password = res[1].data;
}
})
}
},
onReady() {
this.$refs.uForm.setRules(this.rules);
},
methods: {
getTenantList(){
uni.request({
url: config.baseUrl + "/auth/tenant/list",
method: "GET",
data: {},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log("res11",res);
if(res.data.code == 200){
let data = res.data.data;
this.tenantEnabled = data.tenantEnabled === undefined ? true : data.tenantEnabled;
if(this.tenantEnabled){
this.tenantList = data.voList || [];
let logo = '';
let title = '';
// #ifdef H5
if(this.query.tenantId){
this.form.tenantId = this.query.tenantId;
data.voList.forEach((item) => {
if (item.tenantId === this.query.tenantId) {
logo = item.logo;
title = item.companyName;
}
});
this.isTenant = false;
} else if (data.voList != null && data.voList.length === 1 && data.voList[0].domain === window.location.host) {
this.form.tenantId = data.voList[0].tenantId;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
this.isTenant = false;
} else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
}
// #endif
// #ifdef MP-WEIXIN
if(this.appid){
let isAppid = true;
data.voList.forEach((item) => {
if (item.appId === this.appid) {
console.log("appId",item)
this.form.tenantId = item.tenantId;
logo = item.logo;
title = item.companyName;
isAppid = false;
}
});
if(isAppid){
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
}else{
this.isTenant = false;
}
}else if (data.voList != null && data.voList.length !== 0) {
this.form.tenantId = data.voList[0].tenantId;
this.activeTenantObj = data.voList[0] ;
logo = data.voList[0].logo;
title = data.voList[0].companyName;
}
// #endif
console.log("title",title,logo)
if(title){
this.appConfig.logo = logo;
this.appConfig.name = title;
}else{
this.appConfig.logo = '';
this.appConfig.name = this.$store.state.app.appConfig;
}
}
}
}
});
},
changeTenant(e){
console.log("e",e[0].value)
this.tenantList.forEach((item) => {
if (item.tenantId == e[0].value) {
this.activeTenantObj = item;
this.form.tenantId = item.tenantId;
this.appConfig.logo = item.logo;
this.appConfig.name = item.companyName;
}
});
},
GetWxMiniProgramUrlParam(url) {
let theRequest = {};
if (url.indexOf("#") != -1) {
const str = url.split("#")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
} else if (url.indexOf("?") != -1) {
const str = url.split("?")[1];
const strs = str.split("&");
for (let i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
}
return theRequest;
},
//
goWxLogin(){
uni.reLaunch({
url: './login'
});
},
goPolicy() {
uni.navigateTo({
url: '/pages/tabBar/my/userPolicy'
})
},
goForgotPasswordFn() {
uni.navigateTo({
url: `./forgotPassword?userType=${this.usetTypeValue=="普通用户"?"user":"company"}`
})
},
//
getCodeImageFn() {
this.$get("/captchaImage").then((res) => {
console.log(res, "resss");
this.captchaData = res;
})
},
//
autoLogin(){
uni.request({
url: config.baseUrl + "/login",
method: "POST",
data: {
username: this.form.username,
password: this.form.password,
},
header: {
UserType: this.usetTypeValue == "普通用户" ? "PERSONAL" : "TENANT",
},
success: (res) => {
console.log(res);
if (res.data.token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.token);
uni.setStorage({
key: 'userType',
data: this.usetTypeValue,
}).then(res => {
return uni.setStorage({
key: 'username',
data: this.form.username,
})
}).then(res => {
return uni.setStorage({
key: 'password',
data: this.form.password,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/order"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCodeImageFn();
}
}
});
},
submit() {
if(!this.protocolStatus){
this.$refs.uToast.show({
title: '请先阅读并同意用户协议',
})
}else{
this.$refs.uForm.validate(valid => {
if (valid) {
uni.request({
url: config.baseUrl + "/auth/login",
method: "POST",
data: {
...this.form,
clientId: config.clientId,
},
header: {
Clientid: config.clientId
},
success: (res) => {
console.log(res);
if (res.data.code == 200 && res.data.data.access_token) {
this.$refs.uToast.show({
title: '登录成功',
type: 'success',
})
this.$store.dispatch('setLogin', res.data.data.access_token);
uni.setStorage({
key: 'userType',
data: this.usetTypeValue,
}).then(res => {
return uni.setStorage({
key: 'username',
data: this.form.username,
})
}).then(res => {
return uni.setStorage({
key: 'password',
data: this.form.password,
})
}).then(res => {
setTimeout(() => {
if (this.usetTypeValue == "普通用户") {
uni.reLaunch({
url: "../oneselfUser/index"
})
} else {
uni.switchTab({
url: "../tabBar/order"
})
}
}, 1000)
})
} else {
this.$u.toast(res.data.msg)
this.form.code = "";
// this.getCodeImageFn();
}
}
});
} else {
console.log('验证失败');
}
});
}
}
}
}
</script>
</style>

204
pages/product/detail.vue Normal file
View File

@ -0,0 +1,204 @@
<template>
<view class="container">
<!-- 商品图片 -->
<image
:src="productInfo.imageUrl"
mode="aspectFill"
class="product-image"
@click="lookPic(productInfo.imageUrl)"
></image>
<!-- 分类标签 -->
<view class="category-tags">
<u-tag
v-if="categoryName"
:text="categoryName"
type="primary"
mode="light"
></u-tag>
</view>
<!-- 商品信息 -->
<view class="product-info">
<view class="product-title">{{ productInfo.name }}</view>
<view class="price-box">
<text class="current-price">¥{{ (productInfo.price / 100).toFixed(2) }}</text>
<text class="original-price">¥{{ (productInfo.listPrice / 100).toFixed(2) }}</text>
</view>
<view class="stock">库存: {{ productInfo.stock }}</view>
<view class="description">{{ productInfo.description || '' }}</view>
</view>
<!-- 底部购买按钮 -->
<view class="btn-box">
<!-- <button class="buy-button" @click="handleBuy">立即购买</button> -->
<u-button type="primary" :loading="buttonLoading" @click="handleBuy">立即购买</u-button>
</view>
</view>
</template>
<script>
export default {
data() {
return {
productInfo: {
id: '',
name: '',
price: 0,
listPrice: 0,
stock: 0,
description: '',
imageUrl: '',
categoryId: ''
},
mall_product_category:[],
buttonLoading:false,
}
},
computed: {
// categoryId
categoryName() {
if (this.productInfo.categoryId!='' || !this.mall_product_category.length) return '';
const category = this.mall_product_category.find(item =>
item.dictValue == this.productInfo.categoryId
);
return category ? category.dictLabel : '';
}
},
onLoad(option) {
this.getDictDataList('mall_product_category');
if (option.id) {
this.getProductDetail(option.id)
}
},
methods: {
//
getDictDataList(type){
this.$api.getDictList(type).then((res)=>{
if(res.code===200){
this[type] = res.data || [];
}
})
},
getProductDetail(id) {
this.$api.productApi.getProductDetail(id).then((res)=>{
console.log("获取商品详情",res)
if(res.code == 200){
this.productInfo = res.data;
} else {
uni.showToast({
title: '获取商品详情失败',
icon: 'none'
})
}
}).catch((error)=>{
uni.showToast({
title: '获取商品详情失败',
icon: 'none'
})
})
},
lookPic(url){
uni.previewImage({
current: '', // http
urls: [url] // http
});
},
handleBuy() {
//
uni.showToast({
title: '正在开发中...',
icon: 'none'
})
}
}
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: #f8f8f8;
padding-bottom: 120rpx; //
}
.product-image {
width: 100%;
height: 750rpx;
background-color: #fff;
}
.category-tags {
padding: 16rpx 30rpx;
background-color: #fff;
display: flex;
flex-wrap: wrap;
gap: 10rpx;
}
.product-info {
background-color: #fff;
padding: 30rpx;
margin-bottom: 20rpx;
}
.product-title {
font-size: 32rpx;
color: #333;
font-weight: bold;
margin-bottom: 20rpx;
}
.price-box {
display: flex;
align-items: baseline;
margin-bottom: 16rpx;
.current-price {
font-size: 40rpx;
color: #ff5500;
font-weight: bold;
margin-right: 16rpx;
}
.original-price {
font-size: 28rpx;
color: #999;
text-decoration: line-through;
}
}
.stock {
font-size: 26rpx;
color: #666;
margin-bottom: 20rpx;
}
.description {
font-size: 28rpx;
color: #666;
line-height: 1.6;
}
.btn-box {
display: flex;
justify-content: space-around;
align-items: center;
height: 120rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
background: #fff;
z-index: 999;
button{
width: 680rpx;
height: 85rpx;
border-radius: 10rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
</style>

243
pages/tabBar/product.vue Normal file
View File

@ -0,0 +1,243 @@
<template>
<view class="container">
<view class="header-box">
<!-- 搜索框 -->
<view class="search-box">
<u-search
v-model="searchValue"
placeholder="搜索商品"
:show-action="false"
@custom="onSearchFn"
@search="onSearchFn"
></u-search>
</view>
<!-- 分类标签 -->
<u-tabs
:list="tabList"
:current="tabCurrent"
name="dictLabel"
@change="tabChange"
:is-scroll="false"
item-style="padding-left: 15px; padding-right: 15px; height: 34px;"
></u-tabs>
</view>
<!-- 商品列表 -->
<mescroll-body
ref="mescrollRef"
top="186rpx"
@init="mescrollInit"
@down="downCallback"
@up="upCallback"
:up="upOption"
>
<view class="product-grid">
<view
class="product-item"
v-for="(item, index) in productList"
:key="item.id"
@click="goDetail(item)"
>
<image
:src="item.imageUrl"
mode="aspectFill"
class="product-image"
></image>
<view class="product-info">
<text class="product-name u-line-2">{{ item.name }}</text>
<view class="price-box">
<text class="current-price">¥{{ (item.price / 100).toFixed(2) }}</text>
<text class="original-price">¥{{ (item.listPrice / 100).toFixed(2) }}</text>
</view>
</view>
</view>
</view>
</mescroll-body>
</view>
</template>
<script>
import MescrollMixin from "@/components/mescroll-uni/mescroll-mixins.js";
export default {
data() {
return {
upOption:{
page:{
num : 0 ,
size : 12 ,
time : null
},
noMoreSize: 4,
empty:{
use : true ,
tip: '~ 商品列表为空 ~',
fixed: true,
top: "200rpx",
},
bgColor:"#f5f5f5"
},
searchValue: '',
tabCurrent: 0,
tabList: [], // tab
productList: [],
mescroll: null,
pageNum: 1,
pageSize: 10,
currentCategory: '' // code
}
},
mixins:[MescrollMixin],
onLoad() {
this.getDictDataList('mall_product_category');
},
methods: {
//
getDictDataList(type){
this.$api.getDictList(type).then((res)=>{
if(res.code===200){
this[type] = res.data || [];
if(type == 'mall_product_category'){
this.tabList = [{ dictLabel: '全部',dictValue: '' },...res.data]
}
}
})
},
//
upCallback(page) {
// this.getProductList(mescroll)
let pageNum = page.num; // , 1
let pageSize = page.size; // , 10
let obj = {
pageNum:pageNum,
pageSize:pageSize,
publishStatus:1,
name:this.searchValue,
categoryId:this.currentCategory,
orderByColumn: 'createTime',
isAsc: 'desc',
}
this.$api.productApi.getProductList(obj).then((res)=>{
console.log("当前商品列表",res)
if (res.rows && res.rows.length>0) {
// ()
let curPageData = res.rows;
// (26,8,curPageLen=8)
let curPageLen = curPageData && curPageData.length;
//
console.log(curPageLen,res.total);
if(pageNum == 1){
this.productList = []; //
// this.getUnreadNewIdList(); //
// this.getUnreadNewNum();
}
this.productList = this.productList.concat(curPageData); //
this.mescroll.endBySize(curPageLen, res.total); //
this.loading = false;
} else{
this.productList = [];
this.mescroll.endErr();
this.mescroll.showEmpty();
this.loading = false;
// this.mescroll.endUpScroll(true)
}
}).catch(()=>{
this.$u.toast('服务器开小差了呢,请您稍后再试')
this.productList = [];
//,
this.mescroll.endErr();
this.mescroll.showEmpty();
this.loading = false;
})
},
//
onSearchFn(){
this.mescroll.resetUpScroll();
},
//
tabChange(index) {
this.tabCurrent = index
this.currentCategory = this.tabList[index].dictValue;
this.mescroll.resetUpScroll()
},
//
goDetail(item) {
uni.navigateTo({
url: `/pages/product/detail?id=${item.id}`
})
}
}
}
</script>
<style lang="scss" scoped>
.container {
min-height: 100vh;
background-color: #f5f5f5;
.header-box{
position: fixed;
left: 0;
top: var(--window-top);
width: 100%;
z-index: 999;
background-color: #fff;
}
.search-box {
padding: 20rpx;
background-color: #fff;
}
}
.product-grid {
padding: 20rpx;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
}
.product-item {
background-color: #fff;
border-radius: 12rpx;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
.product-image {
width: 100%;
height: 345rpx;
background-color: #f8f8f8;
}
.product-info {
padding: 16rpx;
}
.product-name {
font-size: 28rpx;
color: #333;
line-height: 1.4;
margin-bottom: 12rpx;
height: 80rpx;
}
.price-box {
display: flex;
align-items: baseline;
.current-price {
font-size: 32rpx;
color: #ff5500;
font-weight: bold;
margin-right: 12rpx;
}
.original-price {
font-size: 24rpx;
color: #999;
text-decoration: line-through;
}
}
}
</style>

View File

@ -1,192 +1,415 @@
/* @font-face {
font-family: "diconfont";
src: url('//at.alicdn.com/t/c/font_4601750_didlrvj3tlw.woff2?t=1733898191649') format('woff2'),
url('//at.alicdn.com/t/c/font_4601750_didlrvj3tlw.woff?t=1733898191649') format('woff'),
url('//at.alicdn.com/t/c/font_4601750_didlrvj3tlw.ttf?t=1733898191649') format('truetype');
} */
@font-face {
font-family: "diconfont";
src: url('//static.drgyen.com/app/hc-app-power/font/iconfont.woff2?t=1733898191649') format('woff2'),
url('//static.drgyen.com/app/hc-app-power/font/iconfont.woff?t=1733898191649') format('woff'),
url('//static.drgyen.com/app/hc-app-power/font/iconfont.ttf?t=1733898191649') format('truetype');
font-family: "iconfont"; /* Project id 4669262 */
src: url('//at.alicdn.com/t/c/font_4669262_u9rbl9p25qn.woff2?t=1740103284583') format('woff2'),
url('//at.alicdn.com/t/c/font_4669262_u9rbl9p25qn.woff?t=1740103284583') format('woff'),
url('//at.alicdn.com/t/c/font_4669262_u9rbl9p25qn.ttf?t=1740103284583') format('truetype'),
url('//at.alicdn.com/t/c/font_4669262_u9rbl9p25qn.svg?t=1740103284583#iconfont') format('svg');
}
.diconfont {
font-family: "diconfont" !important;
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.dicon-saoyisao2:before {
.icon-shouji:before {
content: "\e653";
}
.icon-weixin1:before {
content: "\e661";
}
.icon-suo:before {
content: "\e662";
}
.icon-my-task:before {
content: "\e718";
}
.icon-finish:before {
content: "\e618";
}
.dicon-mti-qiehuan:before {
content: "\e73e";
.icon-model:before {
content: "\e74a";
}
.dicon-shebei_shebeizu:before {
content: "\e616";
.icon-category:before {
content: "\e65d";
}
.dicon-icon_dianliang:before {
content: "\e776";
.icon-waiting:before {
content: "\e65e";
}
.dicon-icon_dianya:before {
content: "\e777";
.icon-workflow:before {
content: "\e600";
}
.dicon-icon_zongliang:before {
content: "\e778";
.icon-my-copy:before {
content: "\e65f";
}
.dicon-icon_fenzha:before {
content: "\e779";
.icon-topiam:before {
content: "\e660";
}
.dicon-icon_jinribaojing:before {
content: "\e77a";
.icon-caret-back:before {
content: "\e64a";
}
.dicon-icon_hezha:before {
content: "\e77b";
.icon-caret-forward:before {
content: "\e61e";
}
.dicon-icon_wendu:before {
content: "\e77c";
.icon-example:before {
content: "\e64f";
}
.dicon-icon_dianliu:before {
content: "\e77d";
.icon-email:before {
content: "\e650";
}
.dicon-icon_xiugai:before {
content: "\e77e";
.icon-drag:before {
content: "\e651";
}
.dicon-icon_saoma:before {
content: "\e77f";
.icon-edit:before {
content: "\e652";
}
.dicon-icon_weibaojilu:before {
content: "\e780";
.icon-checkbox:before {
content: "\e654";
}
.dicon-icon_gengduo:before {
content: "\e781";
.icon-documentation:before {
content: "\e655";
}
.dicon-duanxin:before {
.icon-color:before {
content: "\e656";
}
.icon-clipboard:before {
content: "\e657";
}
.icon-druid:before {
content: "\e658";
}
.icon-cascader:before {
content: "\e659";
}
.icon-company:before {
content: "\e65a";
}
.icon-code:before {
content: "\e65b";
}
.icon-chart:before {
content: "\e65c";
}
.icon-component:before {
content: "\e64d";
}
.icon-date-range:before {
content: "\e64e";
}
.icon-list:before {
content: "\e63a";
}
.icon-logininfor:before {
content: "\e63b";
}
.icon-github:before {
content: "\e63c";
}
.icon-guide:before {
content: "\e63d";
}
.icon-message:before {
content: "\e63e";
}
.dicon-zuoji:before {
.icon-lock:before {
content: "\e63f";
}
.icon-link:before {
content: "\e640";
}
.icon-eye-open:before {
content: "\e641";
}
.icon-international:before {
content: "\e642";
}
.icon-exit-fullscreen:before {
content: "\e643";
}
.dicon-fenhezhajingshi:before {
content: "\e6cd";
.icon-gitee:before {
content: "\e644";
}
.dicon-dingwei:before {
.icon-excel:before {
content: "\e645";
}
.icon-date:before {
content: "\e646";
}
.icon-dashboard:before {
content: "\e647";
}
.icon-dict:before {
content: "\e648";
}
.icon-fullscreen:before {
content: "\e649";
}
.icon-eye:before {
content: "\e64b";
}
.icon-education:before {
content: "\e64c";
}
.icon-search:before {
content: "\e624";
}
.icon-slider:before {
content: "\e625";
}
.icon-rate:before {
content: "\e626";
}
.icon-input:before {
content: "\e627";
}
.icon-shopping:before {
content: "\e628";
}
.icon-post:before {
content: "\e629";
}
.icon-redis-list:before {
content: "\e62a";
}
.icon-select:before {
content: "\e62b";
}
.icon-nested:before {
content: "\e62c";
}
.icon-people:before {
content: "\e62d";
}
.icon-question:before {
content: "\e62e";
}
.icon-number:before {
content: "\e62f";
}
.icon-radio:before {
content: "\e630";
}
.icon-pdf:before {
content: "\e631";
}
.icon-download:before {
content: "\e632";
}
.icon-phone:before {
content: "\e633";
}
.icon-password:before {
content: "\e634";
}
.icon-language:before {
content: "\e635";
}
.icon-money:before {
content: "\e636";
}
.icon-monitor:before {
content: "\e637";
}
.icon-job:before {
content: "\e638";
}
.icon-log:before {
content: "\e639";
}
.icon-user:before {
content: "\e60b";
}
.icon-build:before {
content: "\e60c";
}
.icon-tool:before {
content: "\e60d";
}
.icon-system:before {
content: "\e60e";
}
.icon-star:before {
content: "\e60f";
}
.icon-peoples:before {
content: "\e611";
}
.icon-icon:before {
content: "\e612";
}
.icon-upload:before {
content: "\e613";
}
.icon-validCode:before {
content: "\e614";
}
.icon-tree-table:before {
content: "\e615";
}
.icon-table:before {
content: "\e616";
}
.icon-theme:before {
content: "\e617";
}
.dicon-bangzhu:before {
content: "\e70f";
.icon-time-range:before {
content: "\e619";
}
.dicon-mima1:before {
content: "\e668";
.icon-swagger:before {
content: "\e61a";
}
.dicon-xiaoxi:before {
.icon-row:before {
content: "\e61b";
}
.icon-server:before {
content: "\e61c";
}
.icon-qq:before {
content: "\e61d";
}
.icon-skill:before {
content: "\e61f";
}
.icon-textarea:before {
content: "\e620";
}
.icon-form:before {
content: "\e621";
}
.icon-tab:before {
content: "\e622";
}
.icon-online:before {
content: "\e623";
}
.icon-a-404:before {
content: "\e602";
}
.icon-size:before {
content: "\e603";
}
.icon-bug:before {
content: "\e604";
}
.dicon-you:before {
content: "\e68b";
.icon-switch:before {
content: "\e605";
}
.dicon-icon_weizhi:before {
content: "\e770";
.icon-button:before {
content: "\e606";
}
.dicon-icon_banbenhao:before {
content: "\e763";
.icon-redis:before {
content: "\e607";
}
.dicon-icon_yongnengfenxi:before {
content: "\e764";
.icon-zip:before {
content: "\e608";
}
.dicon-icon_bianji:before {
content: "\e765";
.icon-wechat:before {
content: "\e609";
}
.dicon-icon_dingshiqi:before {
content: "\e766";
.icon-tree:before {
content: "\e60a";
}
.dicon-icon_dingwei:before {
content: "\e767";
}
.dicon-icon_guanyu:before {
content: "\e768";
}
.dicon-icon_gongcheng:before {
content: "\e769";
}
.dicon-icon_mulu:before {
content: "\e76a";
}
.dicon-icon_gaojingjilu:before {
content: "\e76b";
}
.dicon-icon_shishi:before {
content: "\e76c";
}
.dicon-icon_liandongpeizhi:before {
content: "\e76d";
}
.dicon-icon_shijian:before {
content: "\e76e";
}
.dicon-icon_weibao:before {
content: "\e76f";
}
.dicon-icon_jiance:before {
content: "\e75d";
}
.dicon-icon_xiaofang:before {
content: "\e75e";
}
.dicon-icon_yongqi:before {
content: "\e75f";
}
.dicon-icon_yongdian:before {
content: "\e760";
}
.dicon-icon_shipin:before {
content: "\e761";
}
.dicon-icon_yongshui:before {
content: "\e762";
.icon-time:before {
content: "\e601";
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -17,7 +17,14 @@ const auth = {
state.hasLogin = false;
state.userInfo = {};
state.userToken = {};
uni.clearStorageSync();
// uni.clearStorageSync();
const resStorage = uni.getStorageInfoSync();
console.log("获取到缓存信息",resStorage)
resStorage.keys.forEach((item)=>{
if(item!="username" && item!="password" && item!="phonenumber"){
uni.removeStorageSync(item);
}
})
},
},
actions:{