hyx_brand
hyx 2 months ago
parent 19862dc69d
commit 6afa988017

@ -15,7 +15,7 @@
</el-container>
</div>
<div v-else class="loading-container">
<el-loading-spinner />
<el-icon class="is-loading"><Loading /></el-icon>
<p>正在初始化...</p>
</div>
</template>
@ -23,6 +23,7 @@
<script setup>
import { computed } from 'vue'
import { useStore } from 'vuex'
import { Loading } from '@element-plus/icons-vue'
import HeaderBar from './components/HeaderBar.vue'
const store = useStore()

@ -92,6 +92,13 @@ watch(() => store.state.sessionInitialized, async (newVal) => {
}
})
//
watch(() => store.getters.isAuthenticated, async (newVal) => {
if (newVal && store.state.sessionInitialized) {
await fetchUserInfo()
}
})
//
async function fetchUserInfo() {
try {

@ -17,9 +17,17 @@ app.use(ElementPlus)
app.use(store)
app.use(router)
// 初始化会话
store.dispatch('initSession')
// 初始化会话并挂载应用
async function initializeApp() {
try {
await store.dispatch('initSession')
} catch (error) {
console.error('会话初始化失败:', error)
} finally {
app.mount('#app')
}
}
app.mount('#app')
initializeApp()
window.store = store

@ -101,7 +101,7 @@ const router = createRouter({
})
// 路由守卫
router.beforeEach((to, from, next) => {
router.beforeEach(async (to, from, next) => {
// 等待会话初始化完成
if (!store.state.sessionInitialized) {
return next()

@ -1,12 +1,13 @@
import { createStore } from 'vuex'
import service from '../utils/request'
import service from '../utils/request'
import { safeGetItem, safeSetItem, safeRemoveItem } from '../utils/storage'
export default createStore({
state: {
user: JSON.parse(sessionStorage.getItem('user')) || null,
balance: JSON.parse(sessionStorage.getItem('balance')) || 0,
vipLevel: JSON.parse(sessionStorage.getItem('vipLevel')) || 0,
borrowedBooks: JSON.parse(sessionStorage.getItem('borrowedBooks')) || [],
user: safeGetItem('user', null),
balance: safeGetItem('balance', 0),
vipLevel: safeGetItem('vipLevel', 0),
borrowedBooks: safeGetItem('borrowedBooks', []),
sessionInitialized: false
},
getters: {
@ -14,71 +15,115 @@ export default createStore({
isAdmin: state => state.user?.admin || false
},
mutations: {
setUser(state, user) {
const admin = user.admin === 1;
const userData = {
...user,
admin
};
setUser(state, user) {
const admin = user.admin === 1;
const userData = {
...user,
admin
};
state.user = user
sessionStorage.setItem('user', JSON.stringify(user))
state.user = userData
safeSetItem('user', userData)
},
setBalanceAndVip(state, { balance, vip }) {
state.balance = balance
state.vipLevel = vip
sessionStorage.setItem('balance', JSON.stringify(balance))
sessionStorage.setItem('vipLevel', JSON.stringify(vip))
safeSetItem('balance', balance)
safeSetItem('vipLevel', vip)
},
setBorrowedBooks(state, books) {
state.borrowedBooks = books
sessionStorage.setItem('borrowedBooks', JSON.stringify(books))
safeSetItem('borrowedBooks', books)
},
clearUser(state) {
state.user = null
state.balance = 0
state.vipLevel = 0
state.borrowedBooks = []
sessionStorage.removeItem('user')
sessionStorage.removeItem('balance')
sessionStorage.removeItem('vipLevel')
sessionStorage.removeItem('borrowedBooks')
safeRemoveItem('user')
safeRemoveItem('balance')
safeRemoveItem('vipLevel')
safeRemoveItem('borrowedBooks')
// 不清除sessionInitialized保持应用状态
},
removeBorrowedBook(state, title) {
state.borrowedBooks = state.borrowedBooks.filter(book => book.title !== title)
safeSetItem('borrowedBooks', state.borrowedBooks)
},
setSessionInitialized(state, value) {
state.sessionInitialized = value
}
},
actions: {
async initSession({ commit, dispatch }) {
async initSession({ commit, dispatch, state }) {
try {
// 静默获取用户信息
const userData = await service.get('/user/getinfo', {
silent: true // 避免未登录时显示错误
})
if (userData && userData.username) {
const admin = userData.admin === 1;
commit('setUser', {
username: userData.username,
pic: userData.pic || '',
admin
})
// 获取关联信息
// 首先检查本地是否有保存的用户信息
const savedUser = safeGetItem('user', null)
if (savedUser) {
try {
await dispatch('fetchBalanceAndVip')
} catch (balanceError) {
console.warn('获取余额信息失败:', balanceError)
const userData = savedUser
if (userData && userData.username) {
// 验证服务器端会话是否仍然有效
const serverUserData = await service.get('/user/getinfo', {
silent: true // 避免未登录时显示错误
})
if (serverUserData && serverUserData.username) {
// 服务器会话有效,更新用户信息
const admin = serverUserData.admin === 1;
commit('setUser', {
username: serverUserData.username,
pic: serverUserData.pic || '',
admin
})
// 获取关联信息
try {
await dispatch('fetchBalanceAndVip')
} catch (balanceError) {
console.warn('获取余额信息失败:', balanceError)
}
try {
await dispatch('fetchBorrowedBooks')
} catch (booksError) {
console.warn('获取借阅书籍失败:', booksError)
}
} else {
// 服务器会话无效,清除本地数据
commit('clearUser')
}
}
} catch (parseError) {
console.error('解析保存的用户信息失败:', parseError)
commit('clearUser')
}
} else {
// 没有保存的用户信息,尝试静默获取
const userData = await service.get('/user/getinfo', {
silent: true
})
try {
await dispatch('fetchBorrowedBooks')
} catch (booksError) {
console.warn('获取借阅书籍失败:', booksError)
if (userData && userData.username) {
const admin = userData.admin === 1;
commit('setUser', {
username: userData.username,
pic: userData.pic || '',
admin
})
// 获取关联信息
try {
await dispatch('fetchBalanceAndVip')
} catch (balanceError) {
console.warn('获取余额信息失败:', balanceError)
}
try {
await dispatch('fetchBorrowedBooks')
} catch (booksError) {
console.warn('获取借阅书籍失败:', booksError)
}
}
}
} catch (error) {
@ -130,16 +175,16 @@ export default createStore({
// 获取关联信息
try {
await dispatch('fetchBalanceAndVip')
} catch (balanceError) {
console.error('获取余额信息失败:', balanceError)
}
try {
await dispatch('fetchBorrowedBooks')
} catch (booksError) {
console.error('获取借阅书籍失败:', booksError)
}
await dispatch('fetchBalanceAndVip')
} catch (balanceError) {
console.error('获取余额信息失败:', balanceError)
}
try {
await dispatch('fetchBorrowedBooks')
} catch (booksError) {
console.error('获取借阅书籍失败:', booksError)
}
return userData
} catch (error) {
@ -199,10 +244,16 @@ export default createStore({
return { code: 200, message: '已退出登录' }
},
// 查询个人借书记录
// 查询个人借书记录 - 符合接口文档1.6
async fetchBorrowRecords() {
const response = await service.get('/user/findone')
return response.data
// 根据接口文档1.6,管理员返回数组,普通用户返回单个对象
if (response.data && response.data.code === 200) {
return response.data
} else {
throw new Error(response.data?.message || '获取借阅记录失败')
}
},
// 获取当前用户已借书籍
@ -249,7 +300,7 @@ async returnBook({ dispatch }, { title }) {
}
},
// 查询全部书籍 - 符合接口文档
// 查询全部书籍 - 符合接口文档2.2
async fetchBooks(_, params = {}) {
const config = {
params: {
@ -260,24 +311,21 @@ async returnBook({ dispatch }, { title }) {
}
const response = await service.get('/api/select', config)
console.log('请求书籍:', route.params.title)
console.log('API响应:', response)
// 处理不同响应格式
// 根据接口文档2.2,直接返回数组
let list = []
let total = 0
if (Array.isArray(response)) {
list = response
total = response.length
} else if (Array.isArray(response.data)) {
if (Array.isArray(response.data)) {
list = response.data
total = response.data.length
} else if (response.data && Array.isArray(response.data.data)) {
list = response.data.data
total = response.data.total || response.data.data.length
} else if (response.data && Array.isArray(response.data.list)) {
list = response.data.list
total = response.data.total || response.data.list.length
} else if (Array.isArray(response)) {
list = response
total = response.length
} else {
console.warn('API返回格式不符合预期:', response)
list = []
total = 0
}
return {
@ -318,14 +366,18 @@ async returnBook({ dispatch }, { title }) {
return response.data
},
// 管理员删除书籍
// 管理员删除书籍 - 符合接口文档
async deleteBook(_, { title }) {
const response = await service.post('/user/delete',
`title=${encodeURIComponent(title)}`,
{ headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
)
return response.data
if (response.data && response.data.code === 200) {
return response.data
} else {
throw new Error(response.data?.message || '删除书籍失败')
}
},
// 本周热租榜 - 符合接口文档

@ -0,0 +1,43 @@
// 安全地解析JSON字符串
export function safeParseJSON(str, defaultValue = null) {
if (!str) return defaultValue
try {
return JSON.parse(str)
} catch (error) {
console.error('JSON解析失败:', error)
return defaultValue
}
}
// 安全地存储数据到sessionStorage
export function safeSetItem(key, value) {
try {
sessionStorage.setItem(key, JSON.stringify(value))
return true
} catch (error) {
console.error('存储数据失败:', error)
return false
}
}
// 安全地从sessionStorage获取数据
export function safeGetItem(key, defaultValue = null) {
try {
const item = sessionStorage.getItem(key)
return item ? JSON.parse(item) : defaultValue
} catch (error) {
console.error('获取数据失败:', error)
return defaultValue
}
}
// 安全地从sessionStorage删除数据
export function safeRemoveItem(key) {
try {
sessionStorage.removeItem(key)
return true
} catch (error) {
console.error('删除数据失败:', error)
return false
}
}

@ -70,7 +70,6 @@
import { ElMessage } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/date'
import axios from 'axios'
const store = useStore()
const records = ref([])
@ -106,28 +105,28 @@
const fetchAllRecords = async () => {
try {
loading.value = true
const params = {
page: currentPage.value,
pageSize: pageSize.value,
sort: sortType.value,
username: searchUsername.value
}
const response = await axios.get('/user/findone', { params })
if (response.data.code === 200) {
records.value = response.data.data.list
total.value = response.data.data.total
// 1.6/user/findone
const response = await store.dispatch('fetchBorrowRecords')
if (response.code === 200) {
//
if (Array.isArray(response.data)) {
records.value = response.data
total.value = response.data.length
} else {
// 使
records.value = presetRecords
total.value = presetRecords.length
}
} else {
//使
// 使
records.value = presetRecords
total.value = presetRecords.length
}
} catch (error) {
console.error('获取借阅记录失败:', error)
ElMessage.error('接口调用失败,使用预设数据')
ElMessage.error('获取借阅记录失败,使用预设数据')
records.value = presetRecords
total.value = presetRecords.length

@ -74,11 +74,12 @@
<script setup>
import { ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Plus } from '@element-plus/icons-vue'
import axios from 'axios'
const router = useRouter()
const store = useStore()
const books = ref([])
const loading = ref(false)
const total = ref(0)
@ -90,6 +91,31 @@
await fetchBooks()
})
// const fetchBooks = async () => {
// try {
// loading.value = true
// const params = {
// page: currentPage.value,
// pageSize: pageSize.value,
// keyword: searchKeyword.value
// }
// const response = await axios.get('/api/select', { params })
// if (response.data.code === 200) {
// books.value = response.data.data.list
// total.value = response.data.data.total
// } else {
// ElMessage.error('')
// total.value = books.value.length
// }
// } catch (error) {
// console.error(':', error)
// ElMessage.error('')
// } finally {
// loading.value = false
// }
// }
const fetchBooks = async () => {
try {
loading.value = true
@ -99,22 +125,23 @@
keyword: searchKeyword.value
}
const response = await axios.get('/api/select', { params })
if (response.data.code === 200) {
books.value = response.data.data.list
total.value = response.data.data.total
} else {
ElMessage.error('获取图书列表失败')
total.value = books.value.length
}
const response = await store.dispatch('fetchBooks', params)
books.value = response.data.list
total.value = response.data.total
} catch (error) {
console.error('获取图书列表失败:', error)
ElMessage.error('获取图书列表失败')
console.error('获取书籍列表失败:', error)
ElMessage.error('获取书籍列表失败,使用预设数据')
books.value = [
{ id: 1, title: '三体', url: 'https://picsum.photos/id/24/200/300', money: 5, number: 12, state: '正常', content: '科幻' },
{ id: 2, title: '人类简史', url: 'https://picsum.photos/id/25/200/300', money: 4, number: 10, state: '正常', content: '历史' },
{ id: 3, title: '百年孤独', url: 'https://picsum.photos/id/26/200/300', money: 6, number: 0, state: '维护中', content: '文学' },
]
total.value = books.value.length
} finally {
loading.value = false
}
}
const handlePageChange = (page) => {
currentPage.value = page
fetchBooks()
@ -136,7 +163,7 @@
}
)
await axios.delete(`/api/select/${book.id}`)
await store.dispatch('deleteBook', { title: book.title })
ElMessage.success('删除成功')
fetchBooks()
} catch (error) {

@ -59,7 +59,7 @@ const store = useStore()
const book = ref(null)
const loading = ref(true)
const isAdmin = computed(() => store.getters.isAdmin)
const isAdmin = computed(() => store.state.user?.admin || false)
onMounted(async () => {
await fetchBook()

@ -15,7 +15,7 @@
<el-button
type="primary"
@click="goToAddBook"
v-if="isAdmin"
v-if="user && user.admin"
class="add-button">
<el-icon><Plus /></el-icon>
添加书籍
@ -75,15 +75,13 @@ import { ElMessage } from 'element-plus'
const store = useStore()
const router = useRouter()
const isAdmin = computed(() => store.state.user?.admin || false)
const books = ref([])
const searchKeyword = ref('')
const currentPage = ref(1)
const pageSize = ref(12)
const total = ref(0)
const isAdmin = computed(() => store.getters.isAdmin)
onMounted(() => {
fetchBooks()
})

Loading…
Cancel
Save