完成基本的商城首页
This commit is contained in:
parent
80c158ec7b
commit
1cb44d63a7
|
|
@ -27,3 +27,7 @@ export const useThirdLoginApi = (data: any) => {
|
||||||
export const useLogoutApi = () => {
|
export const useLogoutApi = () => {
|
||||||
return service.post('/sys/auth/logout')
|
return service.post('/sys/auth/logout')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const userRegisterApi = (data: any) => {
|
||||||
|
return service.post('/sys/auth/register', data)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import service from '@/utils/request'
|
import service from '@/utils/request'
|
||||||
|
|
||||||
export const useT_bookApi = (id: number) => {
|
export const getBookDetails = (id: string) => {
|
||||||
return service.get('/maku/t_book/' + id)
|
return service.get('/maku/t_book/' + id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -11,3 +11,30 @@ export const useT_bookSubmitApi = (dataForm: any) => {
|
||||||
return service.post('/maku/t_book', dataForm)
|
return service.post('/maku/t_book', dataForm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 获取图书列表大全
|
||||||
|
* */
|
||||||
|
export const bookList = () => {
|
||||||
|
return service.get('maku/t_book/list')
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 搜索图书
|
||||||
|
* */
|
||||||
|
export const bookSearchList = (name: string) => {
|
||||||
|
return service.get('/maku/t_book/list/search?name=' + name)
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface bookEntity {
|
||||||
|
id: number
|
||||||
|
bookName: string
|
||||||
|
author: string
|
||||||
|
price: number
|
||||||
|
bookCover: string
|
||||||
|
introduction: string
|
||||||
|
description: string
|
||||||
|
store: number
|
||||||
|
createTime: string
|
||||||
|
updateTime: string
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ export default {
|
||||||
logoText: 'Maku Admin',
|
logoText: 'Maku Admin',
|
||||||
miniLogoText: 'MAKU',
|
miniLogoText: 'MAKU',
|
||||||
username: 'Username',
|
username: 'Username',
|
||||||
|
register: 'Register',
|
||||||
password: 'Password',
|
password: 'Password',
|
||||||
captcha: 'Captcha',
|
captcha: 'Captcha',
|
||||||
mobileSignIn: 'Mobile SignIn',
|
mobileSignIn: 'Mobile SignIn',
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ export default {
|
||||||
captcha: '验证码',
|
captcha: '验证码',
|
||||||
signIn: '登录',
|
signIn: '登录',
|
||||||
mobileSignIn: '手机登录',
|
mobileSignIn: '手机登录',
|
||||||
|
register: '注册',
|
||||||
|
rePassword: '再次输入密码',
|
||||||
mobile: '手机号',
|
mobile: '手机号',
|
||||||
signOut: '退出',
|
signOut: '退出',
|
||||||
profile: '个人中心',
|
profile: '个人中心',
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,22 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { onMounted, ref } from 'vue'
|
||||||
|
import { useRoute, useRouter } from 'vue-router'
|
||||||
|
import { bookEntity, getBookDetails } from '@/api/maku/t_book'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const route = useRoute()
|
||||||
|
const bookInfo = ref<bookEntity>({
|
||||||
|
author: '',
|
||||||
|
bookCover: '',
|
||||||
|
bookName: '',
|
||||||
|
createTime: '',
|
||||||
|
description: '',
|
||||||
|
id: 0,
|
||||||
|
introduction: '',
|
||||||
|
price: 0,
|
||||||
|
store: 0,
|
||||||
|
updateTime: ''
|
||||||
|
})
|
||||||
const commentList = ref([
|
const commentList = ref([
|
||||||
{
|
{
|
||||||
id: 'string',
|
id: 'string',
|
||||||
|
|
@ -33,20 +49,29 @@ const commentList = ref([
|
||||||
children: {}
|
children: {}
|
||||||
}
|
}
|
||||||
])
|
])
|
||||||
|
onMounted(async () => {
|
||||||
|
let id = route.query.id as string
|
||||||
|
if (id) {
|
||||||
|
const { data } = await getBookDetails(id)
|
||||||
|
bookInfo.value = data
|
||||||
|
}
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="details-main">
|
<div class="details-main">
|
||||||
<div class="details-p">
|
<div class="details-p">
|
||||||
<div class="img-show">
|
<div class="img-show">
|
||||||
<img src="https://gw.alicdn.com/imgextra/i3/2215468931119/O1CN019pzVLv1K8Y4vdSOVw_!!2215468931119.jpg" />
|
<img :src="bookInfo.bookCover" alt="" />
|
||||||
</div>
|
</div>
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<h1>纯种银渐层幼猫活体宠物猫英国短毛猫银渐层英短银渐层银渐层猫咪</h1>
|
<h1>{{ bookInfo.bookName }}</h1>
|
||||||
<div class="text-price">
|
<div class="text-price">
|
||||||
<span class="price-unit">¥</span>
|
<span class="price-unit">¥</span>
|
||||||
<span class="price-count">300</span>
|
<span class="price-count">{{ bookInfo.price }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="book-introduction">{{ bookInfo.introduction }}</div>
|
||||||
|
<div class="book-introduction">{{ bookInfo.description }}</div>
|
||||||
<div class="botton-group">
|
<div class="botton-group">
|
||||||
<button class="buy">立刻购买</button>
|
<button class="buy">立刻购买</button>
|
||||||
<button class="shopping-card">加入购物车</button>
|
<button class="shopping-card">加入购物车</button>
|
||||||
|
|
@ -56,7 +81,7 @@ const commentList = ref([
|
||||||
<div style="width: 1000px">
|
<div style="width: 1000px">
|
||||||
<div class="user-comment">用户评论</div>
|
<div class="user-comment">用户评论</div>
|
||||||
<div v-for="item in commentList" :key="item.id" class="user-comment-list">
|
<div v-for="item in commentList" :key="item.id" class="user-comment-list">
|
||||||
<img :src="item.user.avatar" />
|
<img :src="item.user.avatar" alt="" />
|
||||||
<div style="margin-left: 15px">
|
<div style="margin-left: 15px">
|
||||||
<div style="font-size: 18px">{{ item.user.username }}</div>
|
<div style="font-size: 18px">{{ item.user.username }}</div>
|
||||||
<div style="font-size: 25px">{{ item.comment }}</div>
|
<div style="font-size: 25px">{{ item.comment }}</div>
|
||||||
|
|
@ -181,4 +206,9 @@ const commentList = ref([
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.book-introduction {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,42 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { onMounted, ref } from 'vue'
|
||||||
import { useT_bookApi } from "../../../api/maku/t_book";
|
import { useRouter } from 'vue-router'
|
||||||
|
import { bookEntity, bookList, bookSearchList } from '@/api/maku/t_book'
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const books = ref<bookEntity[]>([])
|
||||||
|
|
||||||
const totalBooks = 5; // 假设有5本书
|
const inputSearchValue = ref('')
|
||||||
|
|
||||||
// 创建一个包含所有书籍的数组,初始值为5个空对象
|
onMounted(async () => {
|
||||||
const books = ref(Array(totalBooks).fill({}));
|
const res = await bookList()
|
||||||
|
books.value = res.data
|
||||||
|
})
|
||||||
|
|
||||||
// 定义一个函数,用于根据索引调用对应的API获取书籍信息
|
const handleSearch = async () => {
|
||||||
function getBook(index: number) {
|
const res = await bookSearchList(inputSearchValue.value)
|
||||||
useT_bookApi(index + 1).then(res => {
|
books.value = res.data
|
||||||
books.value[index] = res.data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用循环调用获取书籍信息的函数
|
|
||||||
for (let i = 0; i < totalBooks; i++) {
|
|
||||||
getBook(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="search-suggest-combobox">
|
<div class="search-suggest-combobox">
|
||||||
<div class="input-search">
|
<div class="input-search">
|
||||||
<input placeholder="马嘉祺" />
|
<input v-model="inputSearchValue" placeholder="马嘉祺" />
|
||||||
<button >搜索</button>
|
<button @click="handleSearch">搜索</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="screen-outer">
|
<div class="screen-outer">
|
||||||
<div class="tb-pick-content-item" v-for="book in books" :key="book.id">
|
<div v-for="item in books" :key="item.id" class="tb-pick-content-item" @click="router.push(`/book/details?id=${item.id}`)">
|
||||||
<div class="img-wrapper">
|
<div class="img-wrapper">
|
||||||
<img :src="book.bookCover" style="width:100%; height:120%;" alt="Book Cover">
|
<img :src="item.bookCover" style="width: 100%; height: 120%" alt="Book Cover" />
|
||||||
</div>
|
</div>
|
||||||
<div class="info-wrapper">{{ book.bookName }}</div>
|
<div class="info-wrapper">{{ item.bookName }}</div>
|
||||||
<div class="price-wrapper">
|
<div class="price-wrapper">
|
||||||
<span class="price-unit">¥</span>
|
<span class="price-unit">¥</span>
|
||||||
<span class="price-value">{{ book.price }}</span>
|
<span class="price-value">{{ item.price }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|
@ -84,8 +80,7 @@ for (let i = 0; i < totalBooks; i++) {
|
||||||
}
|
}
|
||||||
|
|
||||||
.screen-outer {
|
.screen-outer {
|
||||||
|
transform: translate(10px);
|
||||||
transform:translate(10px);
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
width: 1552px;
|
width: 1552px;
|
||||||
margin: 30px auto;
|
margin: 30px auto;
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,8 @@ const loginFormRef = ref()
|
||||||
const captchaBase64 = ref()
|
const captchaBase64 = ref()
|
||||||
|
|
||||||
const loginForm = reactive({
|
const loginForm = reactive({
|
||||||
username: constant.env.PROD ? '' : 'admin',
|
username: constant.env.PROD ? '' : '',
|
||||||
password: constant.env.PROD ? '' : 'admin',
|
password: constant.env.PROD ? '' : '',
|
||||||
key: '',
|
key: '',
|
||||||
captcha: ''
|
captcha: ''
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,10 @@
|
||||||
<div class="login-form">
|
<div class="login-form">
|
||||||
<div class="login-title">
|
<div class="login-title">
|
||||||
<el-button link :class="loginType === 'account' ? 'account' : ''" @click="loginSwitch('account')">{{ $t('app.signIn') }}</el-button>
|
<el-button link :class="loginType === 'account' ? 'account' : ''" @click="loginSwitch('account')">{{ $t('app.signIn') }}</el-button>
|
||||||
<el-button link :class="loginType === 'mobile' ? 'account' : ''" @click="loginSwitch('mobile')">{{ $t('app.mobileSignIn') }}</el-button>
|
<el-button link :class="loginType === 'register' ? 'account' : ''" @click="loginSwitch('register')">{{ $t('app.register') }}</el-button>
|
||||||
</div>
|
</div>
|
||||||
<account v-if="loginType === 'account'" />
|
<account v-if="loginType === 'account'" />
|
||||||
<mobile v-if="loginType === 'mobile'" />
|
<register v-if="loginType === 'register'" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -23,6 +23,7 @@ import { ref } from 'vue'
|
||||||
import Account from './account.vue'
|
import Account from './account.vue'
|
||||||
import Mobile from './mobile.vue'
|
import Mobile from './mobile.vue'
|
||||||
import Third from './third.vue'
|
import Third from './third.vue'
|
||||||
|
import Register from '@/views/login/register.vue'
|
||||||
|
|
||||||
// 登录类型
|
// 登录类型
|
||||||
const loginType = ref('account')
|
const loginType = ref('account')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
<template>
|
||||||
|
<el-form ref="registerFormRef" :model="registerForm" :rules="registerRules" @keyup.enter="onRegister">
|
||||||
|
<el-form-item prop="username">
|
||||||
|
<el-input v-model="registerForm.username" :prefix-icon="User" :placeholder="$t('app.username')"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="password">
|
||||||
|
<el-input v-model="registerForm.password" :prefix-icon="Lock" show-password :placeholder="$t('app.password')"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item prop="rePassword">
|
||||||
|
<el-input v-model="registerForm.rePassword" :prefix-icon="Lock" show-password :placeholder="$t('app.rePassword')"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item class="register-button">
|
||||||
|
<el-button type="primary" @click="onRegister()">{{ $t('app.signIn') }}</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, reactive, onMounted } from 'vue'
|
||||||
|
import { User, Lock } from '@element-plus/icons-vue'
|
||||||
|
import { useUserStore } from '@/store/modules/user'
|
||||||
|
import { useCaptchaApi, useCaptchaEnabledApi, userRegisterApi } from '@/api/auth'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import constant from '@/utils/constant'
|
||||||
|
import { sm2Encrypt } from '@/utils/smCrypto'
|
||||||
|
import { ElNotification } from 'element-plus'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const router = useRouter()
|
||||||
|
const { t } = useI18n()
|
||||||
|
const registerFormRef = ref()
|
||||||
|
const captchaBase64 = ref()
|
||||||
|
|
||||||
|
const registerForm = reactive({
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
rePassword: ''
|
||||||
|
})
|
||||||
|
|
||||||
|
const registerRules = ref({
|
||||||
|
username: [{ required: true, message: t('required'), trigger: 'blur' }],
|
||||||
|
password: [{ required: true, message: t('required'), trigger: 'blur' }],
|
||||||
|
rePassword: [{ required: true, message: t('required'), trigger: 'blur' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
// 是否显示验证码
|
||||||
|
const captchaVisible = ref(false)
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
onCaptchaEnabled()
|
||||||
|
})
|
||||||
|
|
||||||
|
const onCaptchaEnabled = async () => {
|
||||||
|
const { data } = await useCaptchaEnabledApi()
|
||||||
|
captchaVisible.value = data
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
await onCaptcha()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCaptcha = async () => {
|
||||||
|
const { data } = await useCaptchaApi()
|
||||||
|
if (data.enabled) {
|
||||||
|
captchaVisible.value = true
|
||||||
|
}
|
||||||
|
captchaBase64.value = data.image
|
||||||
|
}
|
||||||
|
|
||||||
|
const onRegister = () => {
|
||||||
|
registerFormRef.value.validate((valid: boolean) => {
|
||||||
|
if (!valid) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registerForm.password != registerForm.rePassword) {
|
||||||
|
ElNotification({
|
||||||
|
title: '两次输入的密码不一样!',
|
||||||
|
type: 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新封装登录数据
|
||||||
|
const registerData = {
|
||||||
|
username: registerForm.username,
|
||||||
|
password: sm2Encrypt(registerForm.password)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO:用户注册接口的调用
|
||||||
|
|
||||||
|
// 用户注册
|
||||||
|
// userRegisterApi(registerData).then(res => {
|
||||||
|
// ElNotification({
|
||||||
|
// title: '注册成功!!!',
|
||||||
|
// type: 'success'
|
||||||
|
// })
|
||||||
|
// })
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.register-captcha {
|
||||||
|
:deep(.el-input) {
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-captcha img {
|
||||||
|
width: 150px;
|
||||||
|
height: 40px;
|
||||||
|
margin: 5px 0 0 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.register-button {
|
||||||
|
:deep(.el-button--primary) {
|
||||||
|
margin-top: 10px;
|
||||||
|
width: 100%;
|
||||||
|
height: 45px;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in New Issue
Block a user