zjs_project 2 周之前
父節點
當前提交
fe200b0b94
共有 8 個文件被更改,包括 288 次插入91 次删除
  1. 10 2
      src/api/orders.ts
  2. 9 2
      src/permission.ts
  3. 10 1
      src/stores/modules/user.ts
  4. 30 0
      src/utils/auth.ts
  5. 11 9
      src/utils/cache.ts
  6. 25 6
      src/utils/request/index.ts
  7. 1 1
      src/views/account/login.vue
  8. 192 70
      src/views/orders/list.vue

+ 10 - 2
src/api/orders.ts

@@ -1,9 +1,17 @@
 import request from '@/utils/request'
 
-export function ordersList(params?: any) {
+export function ordersList(params ?: any) {
     return request.get({ url: '/orders/list', params })
 }
 
-export function getOrdersCurrent(params?: any) {
+export function getOrdersCurrent(params ?: any) {
     return request.get({ url: '/orders/current', params })
 }
+// 获取订单详情
+export function getOrderDetail(params ?: any) {
+    return request.get({ url: '/orders/dish', params })
+    // return request({
+    //     url: `/order/dish/${id}`,
+    //     method: 'get'
+    // })
+}

+ 9 - 2
src/permission.ts

@@ -26,6 +26,7 @@ router.beforeEach(async (to, from, next) => {
     document.title = to.meta.title ?? config.title
     const userStore = useUserStore()
     const tabsStore = useTabsStore()
+    console.warn("***userStore***",userStore.token,to.path)
     if (whiteList.includes(to.path)) {
         // 在免登录白名单,直接进入
         next()
@@ -68,14 +69,20 @@ router.beforeEach(async (to, from, next) => {
                     // 动态添加可访问路由表
                     router.addRoute(route)
                 })
+                console.warn("***userStore1***",to.path)
                 next({ ...to, replace: true })
             } catch (err) {
+                console.warn("***userStore2***",err)
                 clearAuthInfo()
-                next({ path: loginPath, query: { redirect: to.fullPath } })
+                next(PageEnum.ERROR_403)
+                // window.close();
+                // next({ path: loginPath, query: { redirect: to.fullPath } })
             }
         }
     } else {
-        next({ path: loginPath, query: { redirect: to.fullPath } })
+        console.warn("***userStore-没有token***")
+        next(PageEnum.ERROR_403)
+        // next({ path: loginPath, query: { redirect: to.fullPath } })
     }
 })
 

+ 10 - 1
src/stores/modules/user.ts

@@ -5,9 +5,12 @@ import { getUserInfo, login, logout, getMenu } from '@/api/user'
 import router, { filterAsyncRoutes } from '@/router'
 import { TOKEN_KEY } from '@/enums/cacheEnums'
 import { PageEnum } from '@/enums/pageEnum'
-import { clearAuthInfo, getToken } from '@/utils/auth'
+import { clearAuthInfo, getHouseId, getToken, getBrandId, getUserId} from '@/utils/auth'
 export interface UserState {
     token: string
+    houseId: string
+    brandId: string
+    userId: string
     userInfo: Record<string, any>
     routes: RouteRecordRaw[]
     menu: any[]
@@ -18,6 +21,9 @@ const useUserStore = defineStore({
     id: 'user',
     state: (): UserState => ({
         token: getToken() || '',
+        houseId: getHouseId() || '',
+        brandId: getBrandId() || '',
+        userId: getUserId() || '',
         // 用户信息
         userInfo: {},
         // 路由
@@ -30,6 +36,9 @@ const useUserStore = defineStore({
     actions: {
         resetState() {
             this.token = ''
+            this.houseId = ''
+            this.brandId = ''
+            this.userId = ''
             this.userInfo = {}
             this.perms = []
         },

+ 30 - 0
src/utils/auth.ts

@@ -3,16 +3,46 @@ import { resetRouter } from '@/router'
 import useTabsStore from '@/stores/modules/multipleTabs'
 import useUserStore from '@/stores/modules/user'
 import cache from './cache'
+import {
+    ElMessage,
+    ElMessageBox,
+    ElNotification,
+    ElLoading,
+    type ElMessageBoxOptions
+} from 'element-plus'
 
 export function getToken() {
     return cache.get(TOKEN_KEY)
 }
 
+export function getBrandId() {
+    return cache.get("brandId")
+}
+
+export function getHouseId() {
+    return cache.get("houseId")
+}
+
+export function getUserId() {
+    return cache.get("userId")
+}
 export function clearAuthInfo() {
     const userStore = useUserStore()
     const tabsStore = useTabsStore()
     userStore.resetState()
     tabsStore.$reset()
     cache.remove(TOKEN_KEY)
+    cache.remove("brandId")
+    cache.remove("houseId")
+    cache.remove("userId")
     resetRouter()
+    console.warn("***clearAuthInfo***")
+    // 确认窗体
+    ElMessageBox.confirm("已经在其他地方登录", '温馨提示', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+    }).then(() => {
+        window.close();
+    })
 }

+ 11 - 9
src/utils/cache.ts

@@ -21,15 +21,17 @@ const cache = {
         key = this.getKey(key)
         try {
             const data = window.localStorage.getItem(key)
-            if (!data) {
-                return null
-            }
-            const { value, expire } = JSON.parse(data)
-            if (expire && expire < this.time()) {
-                window.localStorage.removeItem(key)
-                return null
-            }
-            return value
+            // console.warn("**get-key0****",key,data)
+            // if (!data) {
+            //     return null
+            // }
+            // const { value, expire } = JSON.parse(data)
+            // if (expire && expire < this.time()) {
+            //     window.localStorage.removeItem(key)
+            //     return null
+            // }
+            // console.warn("**get-key****",key,data)
+            return data
         } catch (e) {
             return null
         }

+ 25 - 6
src/utils/request/index.ts

@@ -3,7 +3,7 @@ import configs from '@/config'
 import { Axios } from './axios'
 import { ContentTypeEnum, RequestCodeEnum, RequestMethodsEnum } from '@/enums/requestEnums'
 import type { AxiosHooks } from './type'
-import { clearAuthInfo, getToken } from '../auth'
+import { clearAuthInfo, getToken,getUserId,getBrandId,getHouseId } from '../auth'
 import feedback from '../feedback'
 import NProgress from 'nprogress'
 import { AxiosError, type AxiosRequestConfig } from 'axios'
@@ -17,12 +17,17 @@ const axiosHooks: AxiosHooks = {
         const { withToken, isParamsToData } = config.requestOptions
         const params = config.params || {}
         const headers = config.headers || {}
-
+        const userId = getUserId();
+        const brandId = getBrandId();
+        const houseId = getHouseId();
+        headers['userId'] = userId || ""
+        headers['brandId'] = brandId || ""
+        headers['houseId'] = houseId || ""
         // 添加token
         if (withToken) {
-            const token = getToken()
-            headers['like-admin'] = token
-            headers['token'] = token
+            const token = getToken();
+            headers['like-admin'] = token || ""
+            headers['token'] = token || ""
         }
         // POST请求下如果无data,则将params视为data
         if (
@@ -31,8 +36,18 @@ const axiosHooks: AxiosHooks = {
             config.method?.toUpperCase() === RequestMethodsEnum.POST
         ) {
             config.data = params
+            config.data.brandId = brandId
+            config.data.houseId = houseId
             config.params = {}
         }
+        // 如果是GET请求,将brandId和houseId添加到params中
+        if (config.method?.toLowerCase() === 'get') {
+            config.params = {
+                ...config.params,
+                brandId: brandId,
+                houseId: houseId
+            }
+        }
         config.headers = headers
         return config
     },
@@ -78,7 +93,8 @@ const axiosHooks: AxiosHooks = {
             case RequestCodeEnum.TOKEN_EMPTY:
             case RequestCodeEnum.QUIT:
                 clearAuthInfo()
-                router.push(PageEnum.LOGIN)
+                // window.close();
+                // router.push(PageEnum.LOGIN)
                 return Promise.reject()
 
             default:
@@ -90,6 +106,9 @@ const axiosHooks: AxiosHooks = {
         if (error.code !== AxiosError.ERR_CANCELED) {
             error.message && feedback.msgError(error.message)
         }
+        if (error.response.status === RequestCodeEnum.QUIT) {
+            clearAuthInfo()
+        }
         return Promise.reject(error)
     }
 }

+ 1 - 1
src/views/account/login.vue

@@ -152,7 +152,7 @@ const { isLock, lockFn: lockLogin } = useLockFn(handleLogin)
 
 onMounted(() => {
     const value = cache.get(ACCOUNT_KEY)
-    getLoginCaptcha()
+    // getLoginCaptcha()
     if (value?.remember) {
         remAccount.value = value.remember
         formData.account = value.account

+ 192 - 70
src/views/orders/list.vue

@@ -18,24 +18,12 @@
                     </el-select>
                 </el-form-item>
                 <el-form-item label="创建时间" class="w-[280px]">
-                    <el-date-picker
-                        v-model="createTime"
-                        @change="setCreateTime"
-                        type="datetimerange"
-                        range-separator="-"
-                        start-placeholder="开始时间"
-                        end-placeholder="结束时间"
-                    />
+                    <el-date-picker v-model="createTime" @change="setCreateTime" type="datetimerange"
+                        range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" />
                 </el-form-item>
                 <el-form-item label="结账时间" class="w-[280px]">
-                    <el-date-picker
-                        v-model="checkoutTime"
-                        @change="setCheckoutTime"
-                        type="datetimerange"
-                        range-separator="-"
-                        start-placeholder="开始时间"
-                        end-placeholder="结束时间"
-                    />
+                    <el-date-picker v-model="checkoutTime" @change="setCheckoutTime" type="datetimerange"
+                        range-separator="-" start-placeholder="开始时间" end-placeholder="结束时间" />
                 </el-form-item>
                 <el-form-item class="w-[280px]">
                     <el-button type="primary" @click="resetPage">查询</el-button>
@@ -44,36 +32,65 @@
             </el-form>
         </el-card>
         <el-card class="!border-none mt-4" shadow="never">
-            <el-table v-loading="pager.loading" :data="pager.lists">
+            <el-table v-loading="pager.loading" :data="pager.lists" row-key="id" :expand-row-keys="expandRowKeys">
+                <el-table-column type="expand">
+                    <template #default="{ row }">
+                        <div class="order-detail-wrapper" v-loading="!orderDetails[row.id]">
+                            <template v-if="orderDetails[row.id]">
+                                <div class="detail-header">
+                                    <span>订单详情</span>
+                                    <span class="time">下单时间:{{ timeFormat(orderDetails[row.id].createTime) }}</span>
+                                </div>
+                                <el-table :data="orderDetails[row.id].dishes" border class="detail-table">
+                                    <el-table-column label="菜品图片" width="120" align="center">
+                                        <template #default="{ row }">
+                                            <el-image :src="row.image" :preview-src-list="[row.image]"
+                                                class="dish-image" fit="cover" />
+                                        </template>
+                                    </el-table-column>
+                                    <el-table-column prop="name" label="菜品名称" />
+                                    <el-table-column prop="amount" label="单价">
+                                        <template #default="{ row }">
+                                            ¥{{ row.amount }}
+                                        </template>
+                                    </el-table-column>
+                                    <el-table-column prop="number" label="数量" width="120" align="center" />
+                                    <el-table-column label="小计" width="120" align="right">
+                                        <template #default="{ row }">
+                                            ¥{{ row.amount * row.number}}
+                                        </template>
+                                    </el-table-column>
+                                </el-table>
+                                <div class="detail-footer">
+                                    <div class="total-info">
+                                        <span>共 {{ getTotalCount(orderDetails[row.id].dishes) }} 件商品</span>
+                                        <span class="total-price">
+                                            订单总价:<em>¥{{ orderDetails[row.id].amount}}</em>
+                                        </span>
+                                    </div>
+                                </div>
+                            </template>
+                        </div>
+                    </template>
+                </el-table-column>
                 <el-table-column type="index" min-width="80" />
-                <el-table-column
-                    label="订单号"
-                    prop="number"
-                    show-overflow-tooltip
-                ></el-table-column>
+                <el-table-column label="订单号" prop="number" show-overflow-tooltip></el-table-column>
                 <el-table-column label="订单金额" prop="amount"></el-table-column>
                 <el-table-column label="桌号" prop="deskName"></el-table-column>
                 <el-table-column label="备注" prop="remark"></el-table-column>
-                <el-table-column
-                    label="类型"
-                    prop="type"
-                    :formatter="(row) => (row.type == 0 ? '后台点单' : '扫码点单')"
-                ></el-table-column>
-                <el-table-column
-                    label="状态"
-                    prop="status"
-                    :formatter="
+                <el-table-column label="类型" prop="type"
+                    :formatter="(row) => (row.type == 0 ? '后台点单' : '扫码点单')"></el-table-column>
+                <el-table-column label="状态" prop="status" :formatter="
                         (row) =>
                             row.status == 2 ? '已完成' : row.status == 0 ? '待下单' : '待结账'
-                    "
-                ></el-table-column>
+                    "></el-table-column>
                 <el-table-column label="结账时间" prop="checkoutTime"></el-table-column>
                 <el-table-column label="创建时间" prop="createTime"></el-table-column>
-                <el-table-column label="操作" width="120" fixed="right"
-                    ><template #default="{ row }">
-                        <el-button type="primary" link :v-text="row.id"> 查看已点菜品 </el-button>
-                    </template></el-table-column
-                >
+                <el-table-column label="操作" width="120" fixed="right">
+                    <template #default="{ row }">
+                        <el-button type="primary" link @click="showDetail(row)">查看已点菜品</el-button>
+                    </template>
+                </el-table-column>
             </el-table>
             <div class="flex justify-end mt-4">
                 <pagination v-model="pager" @change="getLists" />
@@ -83,37 +100,142 @@
 </template>
 
 <script setup lang="ts">
-import { ordersList } from '@/api/orders'
-import { usePaging } from '@/hooks/usePaging'
-
-const createTime = ref()
-const checkoutTime = ref()
-const queryParams = reactive({
-    type: '',
-    status: '',
-    checkoutTime: '',
-    createTime: ''
-})
-const { pager, getLists, resetPage, resetParams } = usePaging({
-    fetchFun: ordersList,
-    params: queryParams
-})
-const setCreateTime = (v: any) => {
-    queryParams.createTime =
-        Math.round(v[0].getTime() / 1000).toString() +
-        ',' +
-        Math.round(v[1].getTime() / 1000).toString()
-}
-const setCheckoutTime = (v: any) => {
-    queryParams.checkoutTime =
-        Math.round(v[0].getTime() / 1000).toString() +
-        ',' +
-        Math.round(v[1].getTime() / 1000).toString()
-}
-// watch(queryParams, (newV, oldV) => {
-//     console.log(JSON.stringify(newV))
-// })
-getLists()
+    import { ordersList, getOrderDetail } from '@/api/orders'
+    import { usePaging } from '@/hooks/usePaging'
+    import { timeFormat } from '@/utils/util'
+    import feedback from '@/utils/feedback'
+    // import Money from '@/utils/money'
+
+    const createTime = ref()
+    const checkoutTime = ref()
+    const queryParams = reactive({
+        type: '',
+        status: '',
+        checkoutTime: '',
+        createTime: ''
+    })
+    const { pager, getLists, resetPage, resetParams } = usePaging({
+        fetchFun: ordersList,
+        params: queryParams
+    })
+    const setCreateTime = (v : any) => {
+        queryParams.createTime =
+            Math.round(v[0].getTime() / 1000).toString() +
+            ',' +
+            Math.round(v[1].getTime() / 1000).toString()
+    }
+    const setCheckoutTime = (v : any) => {
+        queryParams.checkoutTime =
+            Math.round(v[0].getTime() / 1000).toString() +
+            ',' +
+            Math.round(v[1].getTime() / 1000).toString()
+    }
+    // watch(queryParams, (newV, oldV) => {
+    //     console.log(JSON.stringify(newV))
+    // })
+
+    const expandRowKeys = ref<string[]>([])
+    const orderDetails = ref<Record<string, any>>({})
+
+    // 展示订单详情
+    const showDetail = async (row : any) => {
+        try {
+            // 如果已经加载过该订单详情,直接展开
+            if (orderDetails.value[row.id]) {
+                expandRowKeys.value = [row.id]
+                return
+            }
+
+            // 调用获取订单详情接口
+            const res = await getOrderDetail({id:row.id})
+            console.warn("***getOrderDetail***",res)
+            if (res) {
+                // 定义正确的类型
+                let orderDetail: Record<string, any> = {};
+                orderDetail.id = res.orderItem.id;
+                orderDetail.amount = res.orderItem.amount;//总价
+                orderDetail.createTime = res.orderItem.createTime + "000";
+                orderDetail.dishes = res.orderDishList;
+                // 保存订单详情
+                orderDetails.value[row.id] = orderDetail
+                // 展开当前行
+                expandRowKeys.value = [row.id]
+            } else {
+                feedback.msgError('获取订单详情失败111')
+            }
+        } catch (error) {
+            console.error('获取订单详情失败:', error)
+            feedback.msgError('获取订单详情失败')
+        }
+    }
+
+    // 计算商品总数
+    const getTotalCount = (dishes : any[]) => {
+        return dishes.reduce((total, dish) => total + dish.count, 0)
+    }
+    // 计算订单总价
+    // const getTotalPrice = (dishes: any[]) => {
+    //     return dishes.reduce((total, dish) => {
+    //         return Money.add(total, Money.multiply(dish.price, dish.count))
+    //     }, 0)
+    // }
+
+    getLists()
 </script>
 
-<style></style>
+<style lang="scss" scoped>
+    .order-detail-wrapper {
+        padding: 20px;
+        background: #f8f8f8;
+
+        .detail-header {
+            margin-bottom: 20px;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+
+            span {
+                font-size: 14px;
+                color: #333;
+
+                &.time {
+                    color: #999;
+                }
+            }
+        }
+
+        .detail-table {
+            margin-bottom: 20px;
+
+            :deep(.dish-image) {
+                width: 60px;
+                height: 60px;
+                border-radius: 4px;
+            }
+        }
+
+        .detail-footer {
+            display: flex;
+            justify-content: flex-end;
+
+            .total-info {
+                text-align: right;
+
+                span {
+                    margin-left: 20px;
+                    font-size: 14px;
+                    color: #666;
+
+                    &.total-price {
+                        em {
+                            font-style: normal;
+                            font-size: 16px;
+                            color: #f56c6c;
+                            font-weight: bold;
+                        }
+                    }
+                }
+            }
+        }
+    }
+</style>