16 Commits 5f79ff54fc ... e15ecad019

Author SHA1 Message Date
  陈雪 e15ecad019 ✨ refactor(commands): 更新 get_category 函数的状态参数类型,简化代码结构 1 day ago
  陈雪 1ef098a96b Merge branch 'cx_dev' 1 day ago
  陈雪 5829556374 Merge remote-tracking branch 'origin/lyz_dev' 1 day ago
  Mcal 99f3290d12 ✨ feat(Payment): 添加支付抽屉组件,优化订单支付流程 1 day ago
  Mcal 0b65092fed Merge branch 'wl_dev' of http://1.94.207.143:3000/chongqing/store-project into lyz_dev 1 day ago
  陈雪 db423f451c ✨ feat(i18n): 更新 $t 函数以支持可选参数,增强国际化功能 2 days ago
  陈雪 78fa67dd0e Merge branch 'cx_dev' 2 days ago
  陈雪 9a31eb337c Merge remote-tracking branch 'origin/wl_dev' 3 days ago
  陈雪 8f86233585 Merge remote-tracking branch 'origin/lyz_dev' 3 days ago
  PIWALIN 6fb957e3b8 1 3 days ago
  PIWALIN fd80067dda feat:商品弹窗 3 days ago
  Mcal b9f9ccb597 ✨ feat(Order): 优化订单页面布局,调整表格样式并改善分页组件位置 3 days ago
  Mcal bb8d3e4c9e ✨ feat(Layout): 添加页面切换动画效果,优化用户体验;隐藏滚动条 3 days ago
  Mcal 98730ff743 ✨ feat(Menu): 优化路由激活状态判断逻辑,支持多级路径匹配 4 days ago
  Mcal 0d46e4dcfd ✨ feat(Menu): 优化菜单组件,添加点击导航功能并修复选中状态逻辑 4 days ago
  Mcal 0575daf06b ✨ feat: 更新无产品组件,添加图片和文本属性;优化订单页面布局,增加空状态显示 4 days ago

BIN
public/imgs/menu-cooker4.png


+ 2 - 4
src-tauri/src/commands/mod.rs

@@ -1,12 +1,10 @@
-use tauri::State;
-
 use crate::{
-    AppState, CmdResult,
+    CmdResult, CmdState,
     service::category::{Category, CategoryWithSpu},
 };
 
 #[tauri::command]
-pub async fn get_category(app_state: State<'_, AppState>) -> CmdResult<Vec<CategoryWithSpu>> {
+pub async fn get_category(app_state: CmdState<'_>) -> CmdResult<Vec<CategoryWithSpu>> {
     let category = Category::new(app_state.conn.clone());
     let categories = category.get_category_commodity().await;
     match categories {

+ 3 - 1
src-tauri/src/lib.rs

@@ -5,10 +5,12 @@ mod service;
 use sea_orm::{ConnectionTrait, DatabaseConnection, Statement, TransactionTrait};
 use std::fs::{self, File};
 use std::sync::Arc;
+use tauri::State;
 use tauri::{AppHandle, Manager, path::BaseDirectory};
 
+type CmdState<'a> = State<'a, AppState>;
 type CmdResult<T> = Result<T, String>;
-// 添加 AppState 结构体
+
 #[derive(Default)]
 pub struct AppState {
     pub conn: Arc<DatabaseConnection>,

+ 152 - 0
src/assets/img/orderList/暂无支付记录.svg

@@ -0,0 +1,152 @@
+<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M221.907 124.32C198.938 85.1335 213.007 61.7723 204.573 47.4795C196.14 33.1867 110.67 27.3604 45.9633 96.9904C-16.1935 163.876 39.7499 242.628 106.964 264.929C168.481 285.339 268.184 265.189 275.75 192.113C278.712 163.507 244.876 163.507 221.907 124.32Z" fill="url(#paint0_linear_1121_95317)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M221.907 124.32C198.938 85.1335 213.007 61.7723 204.573 47.4795C196.14 33.1867 110.67 27.3604 45.9633 96.9904C-16.1935 163.876 39.7499 242.628 106.964 264.929C168.481 285.339 268.184 265.189 275.75 192.113C278.712 163.507 244.876 163.507 221.907 124.32Z" fill="#F67F20"/>
+<mask id="mask0_1121_95317" style="mask-type:luminance" maskUnits="userSpaceOnUse" x="19" y="38" width="257" height="235">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M221.907 124.32C198.938 85.1335 213.007 61.7723 204.573 47.4795C196.14 33.1867 110.67 27.3604 45.9633 96.9904C-16.1935 163.876 39.7499 242.628 106.964 264.929C168.481 285.339 268.184 265.189 275.75 192.113C278.712 163.507 244.876 163.507 221.907 124.32Z" fill="white"/>
+</mask>
+<g mask="url(#mask0_1121_95317)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M75.8912 66.2383C75.8912 66.2383 116.049 169.805 95.9699 277.091C75.8912 384.377 -56.5622 132.909 55.9459 75.0192C56.9071 75.0192 75.8912 66.2383 75.8912 66.2383Z" fill="#F67F20"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M34.2008 110.402C34.2008 110.402 72.3668 125.348 95.9699 262.672C84.6403 285.051 -14.9862 195.485 25.5806 122.083L34.2008 110.402Z" fill="#F67F20"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M245.9 147.035C245.9 147.035 222.988 179.526 230.625 270C230.625 270 330.755 200.22 253.283 152.667L245.9 147.035Z" fill="#F67F20"/>
+<circle cx="257.813" cy="205.312" r="6.5625" fill="url(#paint1_linear_1121_95317)"/>
+<circle cx="257.813" cy="205.312" r="6.5625" fill="url(#paint2_linear_1121_95317)"/>
+<g filter="url(#filter0_i_1121_95317)">
+<circle cx="172.501" cy="67.5" r="9.375" fill="url(#paint3_linear_1121_95317)"/>
+<circle cx="172.501" cy="67.5" r="9.375" fill="url(#paint4_linear_1121_95317)"/>
+</g>
+<g filter="url(#filter1_i_1121_95317)">
+<circle cx="76.876" cy="101.25" r="11.25" fill="url(#paint5_linear_1121_95317)"/>
+<circle cx="76.876" cy="101.25" r="11.25" fill="url(#paint6_linear_1121_95317)"/>
+</g>
+</g>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M217.152 161.562C217.152 161.562 235.931 173.666 219.179 191.762C202.428 209.858 186.066 238.715 180.216 248.969C174.367 259.222 164.972 244.574 164.972 244.574L202.102 165.254L217.152 161.562Z" fill="url(#paint7_linear_1121_95317)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M187.511 153.379C187.511 153.379 212.624 159.197 217.152 161.561C217.152 161.561 201.484 165.903 195.348 191.842C189.211 217.781 177.904 251.563 161.451 248.809C144.998 246.056 139.835 221.064 162.735 185.298C175.042 166.075 187.511 153.379 187.511 153.379Z" fill="url(#paint8_linear_1121_95317)"/>
+<g filter="url(#filter2_i_1121_95317)">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M132.362 90C132.362 90 195.257 120.852 213.392 116.169C220.369 114.367 203.004 135.343 174.617 168.675C146.23 202.006 141.05 241.289 158.346 247.921C158.346 247.921 121.097 237.598 106.161 233.86C91.2254 230.123 64.9407 226.121 69.8426 198.75C74.7445 171.379 94.8215 134.756 109.109 120.032C123.397 105.308 130.393 98.098 132.362 90Z" fill="url(#paint9_linear_1121_95317)"/>
+</g>
+<path d="M127.54 113.426L187.591 133.541L186.4 137.097L126.349 116.982L127.54 113.426Z" fill="url(#paint10_linear_1121_95317)"/>
+<path d="M115.543 141.166L167.434 159.406L166.191 162.944L114.3 144.704L115.543 141.166Z" fill="url(#paint11_linear_1121_95317)"/>
+<path d="M108.911 159.393L156.483 174.918L155.319 178.483L107.747 162.958L108.911 159.393Z" fill="url(#paint12_linear_1121_95317)"/>
+<path d="M100.094 178.553L146.5 192.244L145.439 195.841L99.0332 182.149L100.094 178.553Z" fill="url(#paint13_linear_1121_95317)"/>
+<path d="M91.0279 201.543L141.403 216.568L140.331 220.162L89.9561 205.137L91.0279 201.543Z" fill="url(#paint14_linear_1121_95317)"/>
+<ellipse opacity="0.202962" cx="127.867" cy="180.171" rx="33.75" ry="42.1875" transform="rotate(53 127.867 180.171)" fill="url(#paint15_linear_1121_95317)"/>
+<ellipse cx="106.5" cy="164.806" rx="33.75" ry="47.8125" transform="rotate(53 106.5 164.806)" fill="#F67F20"/>
+<path d="M79.4774 191.631C80.8097 189.412 83.6891 188.692 85.9089 190.025C88.0361 191.301 88.7854 193.999 87.6716 196.175L87.5157 196.456L78.4134 211.622C77.0811 213.841 74.2017 214.561 71.982 213.228C69.8548 211.952 69.1054 209.254 70.2192 207.078L70.3751 206.797L79.4774 191.631Z" fill="url(#paint16_linear_1121_95317)"/>
+<path d="M64.5454 207.644C67.2355 203.22 73.0026 201.815 77.4266 204.505C81.7277 207.12 83.1758 212.644 80.7809 217.014L80.5662 217.386L60.6943 250.066C58.0043 254.49 52.2372 255.896 47.8132 253.206C43.5121 250.591 42.064 245.067 44.4589 240.696L44.6736 240.325L64.5454 207.644Z" fill="url(#paint17_linear_1121_95317)"/>
+<ellipse cx="100.875" cy="159.181" rx="33.75" ry="47.8125" transform="rotate(53 100.875 159.181)" fill="url(#paint18_linear_1121_95317)"/>
+<ellipse cx="100.112" cy="158.664" rx="25.3125" ry="40.3125" transform="rotate(53 100.112 158.664)" fill="url(#paint19_linear_1121_95317)"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M84.8783 138.448C102.659 125.05 123.894 123.239 132.307 134.403C133.786 136.366 134.77 138.599 135.291 141.019C125.634 133.046 106.645 135.66 90.5033 147.823C75.8498 158.866 68.1149 174.332 70.5565 185.68C69.5763 184.872 68.6921 183.954 67.9168 182.925C59.5036 171.76 67.0975 151.847 84.8783 138.448Z" fill="#F67F20"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M132.307 134.403L132.529 134.712C122.631 127.585 104.29 130.397 88.6283 142.198C71.8768 154.822 64.1669 173.226 70.3655 184.651C70.4197 184.998 70.4835 185.341 70.5565 185.68C69.5763 184.872 68.6921 183.954 67.9168 182.925C59.5036 171.76 67.0975 151.847 84.8783 138.448C102.659 125.05 123.894 123.239 132.307 134.403Z" fill="#F67F20"/>
+<defs>
+<filter id="filter0_i_1121_95317" x="163.126" y="58.125" width="18.75" height="18.75" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="1.5"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.2 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1121_95317"/>
+</filter>
+<filter id="filter1_i_1121_95317" x="65.626" y="90" width="22.5" height="22.5" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset/>
+<feGaussianBlur stdDeviation="3"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.2 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1121_95317"/>
+</filter>
+<filter id="filter2_i_1121_95317" x="68.2422" y="90" width="146.691" height="157.922" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
+<feFlood flood-opacity="0" result="BackgroundImageFix"/>
+<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
+<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
+<feOffset dx="-1"/>
+<feGaussianBlur stdDeviation="1.5"/>
+<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
+<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.5 0"/>
+<feBlend mode="normal" in2="shape" result="effect1_innerShadow_1121_95317"/>
+</filter>
+<linearGradient id="paint0_linear_1121_95317" x1="19.0176" y1="38.4551" x2="19.0176" y2="272.445" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FE8C2E"/>
+<stop offset="1" stop-color="#FE9743"/>
+</linearGradient>
+<linearGradient id="paint1_linear_1121_95317" x1="264.376" y1="205.313" x2="251.251" y2="205.313" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FF821B"/>
+<stop offset="1" stop-color="#FC811C"/>
+</linearGradient>
+<linearGradient id="paint2_linear_1121_95317" x1="254.407" y1="213.997" x2="254.407" y2="196.628" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint3_linear_1121_95317" x1="181.876" y1="67.5" x2="163.126" y2="67.5" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FF821B"/>
+<stop offset="1" stop-color="#FC811C"/>
+</linearGradient>
+<linearGradient id="paint4_linear_1121_95317" x1="167.634" y1="79.9068" x2="167.634" y2="55.0932" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint5_linear_1121_95317" x1="88.126" y1="101.25" x2="65.626" y2="101.25" gradientUnits="userSpaceOnUse">
+<stop stop-color="#FF821B"/>
+<stop offset="1" stop-color="#FC811C"/>
+</linearGradient>
+<linearGradient id="paint6_linear_1121_95317" x1="71.0355" y1="116.138" x2="71.0355" y2="86.3619" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint7_linear_1121_95317" x1="179.903" y1="268.007" x2="179.903" y2="146.747" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="0.54" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint8_linear_1121_95317" x1="164.094" y1="264.424" x2="164.094" y2="137.923" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint9_linear_1121_95317" x1="104.27" y1="273.456" x2="104.27" y2="64.465" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="0.43" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint10_linear_1121_95317" x1="141.073" y1="140.924" x2="141.073" y2="109.598" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint11_linear_1121_95317" x1="127.075" y1="166.466" x2="127.075" y2="137.645" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint12_linear_1121_95317" x1="119.464" y1="181.57" x2="119.464" y2="156.306" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint13_linear_1121_95317" x1="110.445" y1="198.636" x2="110.445" y2="175.757" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint14_linear_1121_95317" x1="102.325" y1="223.172" x2="102.325" y2="198.532" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint15_linear_1121_95317" x1="113.448" y1="180.33" x2="163.566" y2="155.882" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint16_linear_1121_95317" x1="87.1877" y1="207.189" x2="75.0002" y2="195.002" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint17_linear_1121_95317" x1="82.5004" y1="208.126" x2="40.3129" y2="242.813" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint18_linear_1121_95317" x1="83.3531" y1="222.456" x2="83.3531" y2="95.9068" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+<linearGradient id="paint19_linear_1121_95317" x1="86.9706" y1="212.013" x2="86.9706" y2="105.315" gradientUnits="userSpaceOnUse">
+<stop stop-color="#F67F20"/>
+<stop offset="1" stop-color="white"/>
+</linearGradient>
+</defs>
+</svg>

+ 17 - 2
src/components/noProduct.vue

@@ -1,10 +1,25 @@
 <template>
   <div class="w-full h-[80%] flex flex-col items-center justify-center">
-    <img class="w-[45%]" src="/imgs/noFoods.svg" alt="" />
-    <div class="text-[15px] font-semibold">{{ t('menu.noProducts') }}</div>
+    <img class="w-[25%]" :src="img" alt="" />
+    <div class="text-[15px] font-semibold">{{ text }}</div>
   </div>
 </template>
 <script setup>
 import { useI18n } from 'vue-i18n'
+import { defineProps, watch } from 'vue'
 const { t } = useI18n()
+const props = defineProps({
+  img: {
+    type: String,
+    default: '@/assets/imgs/noFoods.svg',
+  },
+  text: {
+    type: String,
+    default: '还没添加菜品哦',
+  },
+})
+console.log(props)
+watch(()=>props.text, (newVal, oldVal) => {
+  console.log('text changed', newVal, oldVal)
+})
 </script>

+ 16 - 20
src/components/titleFood.vue

@@ -1,25 +1,21 @@
 <!-- 标题 -->
 <template>
-    <div :style="{ fontSize: fontSize,}" class="title">
-      <slot></slot>
-    </div>
-  </template>
-  <script>
-  export default {
-    name: 'Title',
-    props: {
-      fontSize: {
-        type: String,
-        default: '24px',  // 默认字体大小
-      }
-    }
-  }
-  </script>
-  <style scoped>
- .title{
+  <div :style="{ fontSize: fontSize }" class="title">
+    <slot></slot>
+  </div>
+</template>
+<script setup>
+  const props = defineProps({
+    fontSize: {
+      type: String,
+      default: '24px', // 默认字体大小
+    },
+  })
+</script>
+<style scoped>
+  .title {
     height: 50px;
     line-height: 50px;
     font-weight: 600;
- }
-  </style>
-  
+  }
+</style>

+ 13 - 2
src/hook/i18n.ts

@@ -1,12 +1,23 @@
 import { reactive, ref, toRefs, watchEffect } from 'vue'
 import { useI18n, UseI18nOptions } from 'vue-i18n'
 
+type OptionalLastN<
+  T extends any[],
+  N extends number,
+  Acc extends any[] = [],
+> = T['length'] extends N
+  ? [...T, ...Acc]
+  : T extends [...infer Rest, infer Last]
+  ? OptionalLastN<Rest, N, [Last?, ...Acc]>
+  : Acc
+
 export function useStoreI18n(options?: UseI18nOptions) {
   const { t, locale } = useI18n(options)
+
   const keyMap = reactive<Record<string, string>>({})
-  function $t(key: string) {
+  function $t(...[key, ...options]: OptionalLastN<Parameters<typeof t>, 1>) {
     watchEffect(() => {
-      if (locale.value) keyMap[key] = t(key)
+      if (locale.value) keyMap[key] = t(key, ...options)
     })
     return toRefs(keyMap)[key]
   }

+ 52 - 0
src/views/goods/components/BaseButton.vue

@@ -0,0 +1,52 @@
+<template>
+  <button  :class="['btn', btnClass]" @click="handleClick">
+    {{ text }}
+  </button>
+</template>
+<script setup>
+  const props = defineProps({
+    btnClass: {
+      type: String,
+      required: true,
+    },
+    onClick: {
+      type: Function,
+      required: true,
+    },
+    text: {
+      type: String,
+      required: true,
+    },
+  })
+  const handleClick = () => {
+    props.onClick();
+  };
+</script>
+<style scoped lang="scss">
+  .btn {
+    padding: 10px 24px;
+    border-radius: 8px;
+    display: flex;
+    align-items: center;
+    transition: background-color 0.2s;
+    white-space: nowrap;
+    cursor: pointer;
+    color: white;
+  }
+
+  .btn-orange {
+    background-color: #fb923c;
+  }
+
+  .btn-yellow {
+    background-color: #facc15;
+  }
+
+  .btn-orange:hover {
+    background-color: #f97316;
+  }
+
+  .btn-yellow:hover {
+    background-color: #fbbf24;
+  }
+</style>

+ 28 - 36
src/views/goods/components/goods-drawer.vue

@@ -6,13 +6,7 @@
       </template>
 
       <template #default>
-        <el-form
-          :model="formData"
-          :rules="rules"
-          ref="formRef"
-          label-width="150px"
-          class="upload-wrapper"
-        >
+        <el-form  :model="formData" :rules="rules" ref="formRef" label-width="150px" class="upload-wrapper">
           <!-- 第一排 -->
           <div class="upload-section">
             <div class="upload_img">
@@ -45,7 +39,7 @@
               <el-form-item prop="productName">
                 <el-input
                   type="text"
-                  v-model="formData.productName"
+                  v-model="table.name"
                   autocomplete="off"
                   placeholder="Please enter the product name"
                 />
@@ -74,7 +68,7 @@
               <el-form-item prop="price">
                 <el-input
                   type="text"
-                  v-model="formData.price"
+                  v-model="table.price"
                   autocomplete="off"
                   placeholder="Please enter the commodity price"
                 />
@@ -85,7 +79,7 @@
               <el-form-item prop="keywords">
                 <el-input
                   type="text"
-                  v-model="formData.keywords"
+                  v-model="table.sales"
                   autocomplete="off"
                   placeholder="Please enter keywords"
                 />
@@ -118,17 +112,8 @@
 
       <template #footer>
         <div style="display: flex; justify-content: space-between">
-          <el-button style="width: 220px; height: 44px" type="primary" @click="cancelClick" plain>
-            Cancel
-          </el-button>
-          <el-button
-            style="width: 408px; height: 44px; background: #f67f20; color: #fff"
-            type="primary"
-            @click="handleSubmit"
-            plain
-          >
-            Save
-          </el-button>
+          <el-button style="width: 220px; height: 44px" type="primary" @click="cancelClick" plain> Cancel</el-button>
+          <el-button style="width: 408px; height: 44px; background: #f67f20; color: #fff" type="primary" @click="handleSubmit" plain >Save</el-button>
         </div>
       </template>
     </el-drawer>
@@ -139,11 +124,19 @@
 <script setup>
   import { ref,reactive } from 'vue'
   import showRadio from "./show-radio.vue"
+  const props =defineProps({
+    table:{
+      type:Object,
+      required:true
+    },
+    type:{
+      type:Boolean,
+      required:true
+    }
+  })
   const show = defineModel('show')
-  const isShow=ref(false)
-  const cancelClick = () => {
-    show.value = false
-  }
+  const isShow=ref(false) //复选框
+  
   const formData = ref({
     productName: '',
     category: '',
@@ -184,20 +177,15 @@
   const handleChange = (file, fileList) => {
     console.log('File changed:', file)
   }
-
+  // 关闭弹窗
+  const cancelClick = () => {
+    show.value = false
+  }
+  // 确定
   const handleSubmit = () => {
-    // const formRef = ref('')
-    // formRef.value.validate((valid) => {
-    //   if (valid) {
-    //     console.log('Form Submitted:', formData.value)
-    //   } else {
-    //     console.log('Form validation failed')
-    //   }
-    // })
     console.log('Form Submitted:', formData.value)
-
   }
-
+  //  单选框选择事件
   const radioShow=(end)=>{
     isShow.value=true
     if(end === '2'){
@@ -206,12 +194,16 @@
       isShow.value=false
     }
   }
+  console.log(props,'propsprops');
 </script>
 
 <style lang="scss" scoped>
   :deep(.el-drawer__header) {
     margin-bottom: 0px !important;
   }
+  :deep(.el-drawer__body::-webkit-scrollbar ){
+    display: none;
+  }
   .food_title {
     height: 56px;
     font-size: 24px;

+ 219 - 3
src/views/goods/components/show-radio.vue

@@ -1,7 +1,223 @@
 <template>
-  <div>111111111111111111111</div>
+  <div class="multi-center">
+    <!-- 1 -->
+    <div class="container">
+      <Title fontSize="16px">Multi specification parameters</Title>
+      <el-divider />
+      <div class="button-container">
+        <BaseButton btnClass="btn-orange" :onClick="handleAddSpec" text="Add new specifications" />
+        <BaseButton btnClass="btn-yellow" :onClick="handleGenerate" text="Generate immediately" />
+      </div>
+      <el-form :model="formData" ref="formRef" class="spec-form">
+        <div v-for="(spec, index) in specifications" :key="index" class="specification-row">
+          <div class="specification-item">
+            <div class="specification-label">{{ `Specifications ${index + 1}` }}</div>
+            <el-form-item>
+              <el-input
+                v-model="spec.name"
+                placeholder="Enter specification name"
+                required
+              ></el-input>
+            </el-form-item>
+          </div>
+          <div class="specification-item">
+            <div class="specification-label">{{ `Specification value ${index + 1}` }}</div>
+            <el-form-item>
+              <el-input v-model="spec.value" placeholder="Enter value" required></el-input>
+            </el-form-item>
+          </div>
+          <div class="specification-item" style="margin-top: 30px">
+            <el-button style="background: #fb923c; color: #fff" @click="saveSpec(index)" class="save-btn"> Save</el-button>
+            <el-button style="background: #fff; color: #fb923c" @click="cancelSpec(index)" class="cancel-btn">Cancel</el-button>
+          </div>
+        </div>
+      </el-form>
+    </div>
+
+    <!-- 2 -->
+    <div class="container">
+      <Title fontSize="16px">Multi specification parameters</Title>
+      <el-divider />
+      <div class="button-container">
+        <BaseButton btnClass="btn-orange" :onClick="handleMemory" text="Add new specifications" />
+        <BaseButton btnClass="btn-yellow" :onClick="MemoryImmediately" text="Generate immediately" />
+      </div>
+        <div class="h-[80px]" v-for="(spec,index) in memoryList" :key="index">
+          <div class="specification-label">{{ `Memory ${index + 1}` }}</div>
+          <div class="flex">
+            <div class="flex w-[400px] 	justify-between">
+              <el-input style="width: 60px;" v-model="spec.name" ></el-input>
+              <el-input style="width: 60px;" v-model="spec.value"></el-input>
+              <el-input style="width: 60px;" v-model="spec.weight"></el-input>
+              <el-input style="width: 180px" v-model="spec.center" placeholder="Please enter attributes" ></el-input>
+            </div>
+            <div style="margin: 2px 0px 0px 10px">
+              <el-button style="background: #fb923c; color: #fff" @click="memoryAdd(spec)" class="save-btn">Add</el-button>
+            </div>
+          </div>
+        </div>
+    </div>
+
+    <!-- 3 -->
+    <div class="container">
+      <Title fontSize="16px">Multi specification parameters</Title>
+      <el-divider />
+      <div class="button-container">
+        <BaseButton btnClass="btn-orange" :onClick="xxxxx" text="Add new specifications" />
+        <BaseButton btnClass="btn-yellow" :onClick="ccccc" text="Generate immediately" />
+      </div>
+        <div class="specificationAdd h-[80px]">
+          <div class="specification-label">Memory</div>
+          <div class="flex">
+            <div class="flex w-[340px] 	justify-between">
+              <el-input style="width: 60px;" ></el-input>
+              <el-input style="width: 60px;" ></el-input>
+              <el-input style="width: 180px;" placeholder="Please enter attributes" ></el-input>
+            </div>
+            <div style="margin: 2px 0px 0px 10px">
+              <el-button style="background: #fb923c; color: #fff" @click="saveSpec(index)" class="save-btn">Add</el-button>
+            </div>
+          </div>
+        </div>
+        <el-form  class="spec-form">
+        <div class="specification-row mt-[5px]">
+          <div class="specification-item">
+            <div class="specification-label">Specifications</div>
+            <el-form-item>
+              <el-input  placeholder="Enter specification name" required></el-input>
+            </el-form-item>
+          </div>
+          <div class="specification-item">
+            <div class="specification-label">Specifications</div>
+            <el-form-item>
+              <el-input  placeholder="Enter value" required></el-input>
+            </el-form-item>
+          </div>
+          <div class="specification-item" style="margin-top: 30px">
+            <el-button style="background: #fb923c; color: #fff" @click="saveSpec(index)" class="save-btn"> Save</el-button>
+            <el-button  style="background: #fff; color: #fb923c" @click="cancelSpec(index)" class="cancel-btn"> Cancel</el-button>
+          </div>
+        </div>
+        </el-form>
+    </div>
+
+     <!-- 4 -->
+     <div class="container mb-[25px]">
+      <Title fontSize="16px">Multi specification parameters</Title>
+      <el-divider />
+      <div class="button-container">
+        <BaseButton btnClass="btn-orange" :onClick="xxx" text="Add new specifications" />
+        <BaseButton btnClass="btn-yellow" :onClick="ccc" text="Generate immediately" />
+      </div>
+        <div class="specificationAdd h-[80px]">
+          <div class="specification-label">Memory</div>
+          <div class="flex">
+            <div class="flex w-[400px] 	justify-between">
+              <el-input style="width: 60px;" ></el-input>
+              <el-input style="width: 60px;" ></el-input>
+              <el-input style="width: 60px;" ></el-input>
+              <el-input style="width: 180px;" placeholder="Please enter attributes" ></el-input>
+            </div>
+            <div style="margin: 2px 0px 0px 10px">
+              <el-button style="background: #fb923c; color: #fff" @click="saveSpec(index)" class="save-btn">Add</el-button>
+            </div>
+          </div>
+        </div>
+    </div>
+
+    <el-table :data="tableData" :cell-style="{ textAlign: 'center' }"
+    :header-cell-style="{ textAlign: 'center' }">
+        <el-table-column prop="memory" label="memory" width="130" />
+        <el-table-column prop="color" label="color" width="130" />
+        <el-table-column prop="price" label="price" width="300" >
+            <template #default="scope">
+              <el-input
+              v-model="scope.price"
+              placeholder="Please enter the selling price"
+              :formatter="(value) => `$ ${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
+              :parser="(value) => value.replace(/\$\s?|(,*)/g, '')"
+            />
+          </template>
+        </el-table-column>
+        <el-table-column label="Operation">
+          <template #default="scope">
+             <el-button  @click="deleteVariant(scope.row)" type="text" size="small">Delete</el-button>
+          </template>
+        </el-table-column>
+     </el-table>
+
+ </div>
 </template>
 
-<script setup></script>
+<script setup>
+  import Title from '@/components/titleFood.vue'
+  import BaseButton from './BaseButton.vue'
+  import { ref } from 'vue'
+  const formData = ref({})
+  const specifications = ref([ { name: '', value: '' }])
+  const memoryList = ref([ { name: '', value: '',weight:'', center:"",}])
+  const tableData =ref([
+    { memory: '8GB', color: 'Black', price: '' },
+    { memory: '16GB', color: 'White', price: '' },
+  ])
+  // specification 新增
+  const handleAddSpec = () => {
+    console.log('新增')
+    specifications.value.push({ name: '', value: '' })
+  }
+  const handleGenerate = () => {
+    console.log('specifications生成完成')
+  }
+  const saveSpec = (index) => {
+    console.log('保存', index)
+  }
+  const cancelSpec = (index) => {
+    console.log('取消', index)
+    specifications.value.splice(index, 1)
+  }
+  // Memory 添加规格
+ const handleMemory=()=>{
+  console.log("memoryList新增");
+  memoryList.value.push({ name: '', value: '',weight:'', center:"",})
+ }
+ const MemoryImmediately=()=>{
+  console.log('memoryList立即生产',memoryList.value);
+ }
+ const memoryAdd=(spec)=>{
+  console.log("memoryList添加完成",spec);
+ }
+
+//  表格删除
+const deleteVariant=(index)=>{
+  tableData.value.splice(index, 1);
+}
+</script>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+  :deep(.el-divider--horizontal) {
+    margin: 0 0 12px 0;
+  }
+  .container {
+    width: 100%;
+  }
+  .scroll::-webkit-scrollbar {
+    display: none;
+  }
+  .button-container {
+    display: flex;
+    gap: 16px;
+  }
+  .specification-row {
+    display: flex;
+    gap: 16px;
+    align-items: center;
+  }
+  .specification-label {
+    margin: 12px 0px;
+  }
+  .el-table {
+  --el-table-header-bg-color: #f8f9fa;
+  --el-table-border-color: #e5e7eb;
+  --el-table-header-text-color: #4b5563;
+}
+</style>

+ 46 - 18
src/views/goods/index.vue

@@ -15,9 +15,11 @@
         <el-option label="Offline" value="offline" />
       </el-select>
       <el-button type="danger" class="btn-reset" @click="Reset_Btn">Reset</el-button>
-      <el-button type="danger" class="btn-new"   @click="show = true">New Product</el-button>
+      <el-button type="danger" class="btn-new"   @click="Add_Btn">New Product</el-button>
     </div>
-    <el-table :data="productList" style="width: 100%">
+    <!-- table表格 -->
+    <el-table :data="tableList" style="width: 100%" :cell-style="{ textAlign: 'center' }"
+    :header-cell-style="{ textAlign: 'center' }" >
       <el-table-column prop="id" label="Id" />
       <el-table-column label="Product Image">
         <template #default="scope">
@@ -39,25 +41,43 @@
       <el-table-column prop="time" label="Time" />
       <el-table-column label="Operation">
         <template #default="scope">
-          <el-button type="primary" text>Edit</el-button>
-          <el-button type="danger" text>Delete</el-button>
+           <el-button type="primary" text @click="editBtn(scope)">Edit</el-button>
+          <el-button type="danger" @click="deleteBtn" text>Delete</el-button>
         </template>
       </el-table-column>
     </el-table>
-    <GoodsDrawer v-model:show="show"></GoodsDrawer>
+    <!-- Pagination -->
+    <div class="fixed bottom-5 right-5 flex items-center justify-between">
+      <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 30, 40, 50]"
+        :total="total" layout="prev, pager, next, sizes" />
+    </div>
+    <GoodsDrawer v-model:show="show" :table="currentRow" :type="isSwitch" ></GoodsDrawer>
   </div>
 </template>
 <script setup>
   import { ref } from 'vue'
-import GoodsDrawer from './components/goods-drawer.vue'
+  import GoodsDrawer from './components/goods-drawer.vue'
+
   const show = ref(false)
   const searchText = ref('')
-  const selectedCategory = ref('')
-  const selectedStatus = ref('')
+  const selectedCategory = ref('')   // 下拉框数据
+  const selectedStatus = ref('')    // 下拉框数据
+  const currentRow=ref([])     
+  const isSwitch = ref('add');      // 默认是新增操作
+  const currentPage = ref(1);
+  const pageSize = ref(10);
+  const total = ref(600);
+
+  // 重置
   const Reset_Btn=()=>{
    console.log('重置');
   }
-  const productList = ref([
+  // 新增
+  const Add_Btn=()=>{
+    isSwitch.value = 'add'; 
+    show.value = true
+  }
+  const tableList = ref([
     {
       id: '00010',
       image: 'https://ai-public.mastergo.com/ai/img_res/a59d5d07e117eb6d961215c66250fdd2.jpg',
@@ -95,6 +115,18 @@ import GoodsDrawer from './components/goods-drawer.vue'
       time: '2024-12-15 15:22:11',
     },
   ])
+  const editBtn=(scope)=>{
+    // console.log('编辑',scope.row);
+    currentRow.value = scope.row
+    isSwitch.value = 'edit'; // 设置为编辑模式
+    show.value = true
+  }
+  const deleteBtn=()=>{
+    console.log('删除');
+  }
+  const getList = () => {
+  // 请求分页数据的逻辑
+};
 </script>
 <style scoped lang="scss">
   .container {
@@ -145,13 +177,9 @@ import GoodsDrawer from './components/goods-drawer.vue'
     object-fit: cover;
   }
 
-  :deep(.el-table) {
-    --el-table-border-color: #f0f0f0;
-    --el-table-header-bg-color: #fafafa;
-    --el-table-row-hover-bg-color: #f5f5f5;
-  }
-
-  :deep(.el-table .el-table__row:nth-child(even)) {
-    background-color: #fafafa;
-  }
+  .el-table {
+  --el-table-header-bg-color: #f8f9fa;
+  --el-table-border-color: #e5e7eb;
+  --el-table-header-text-color: #4b5563;
+}
 </style>

+ 17 - 16
src/views/layout/components/Menu.vue

@@ -1,39 +1,40 @@
 <template>
-  <div class="flex flex-col items-center">
+  <div class="flex flex-col items-center cursor-pointer" @click="navigateToRoute">
     <div
       class="rounded-[20px] flex items-center justify-center w-[45px] h-[45px]"
-      :class="[props.info.slected ? 'active' : '']"
+      :class="[isActive ? 'active' : '']"
     >
       <img :src="props.info?.img" class="w-full h-full" />
     </div>
     <div
       class="text-center text-[12px] w-[75px]"
-      :class="[props.info.slected ? 'font-semibold' : '']"
+      :class="[isActive ? 'font-semibold' : '']"
     >
       {{ t(props.info.name) }}
     </div>
   </div>
 </template>
 <script setup>
-import { watch } from 'vue'
+import { watch, computed } from 'vue'
 import router from '../../../router'
 import { useI18n } from 'vue-i18n'
+import { useRoute } from 'vue-router'
+
 const { t, locale } = useI18n()
 const props = defineProps({
   info: { type: Object, required: true },
 })
-watch(
-  () => props,
-  () => {
-    if (props.info.slected) {
-      router.push(props.info.path)
-    }
-  },
-  { deep: true },
-)
-const changeLanguage = (lang) => {
-  locale.value = lang
+const route = useRoute()
+
+const isActive = computed(() => {
+  //根据第一个/后面的字符串判断是否是当前路由
+  return route.path.split('/')[1] === props.info.path.split('/')[1]
+})
+
+const navigateToRoute = () => {
+  router.push(props.info.path)
 }
+
 </script>
 <style scoped>
 .active {
@@ -41,4 +42,4 @@ const changeLanguage = (lang) => {
   background: #f67f20;
   box-shadow: 0px 12.864px 38.593px 0px rgba(234, 124, 105, 0.32);
 }
-</style>
+</style>    

+ 20 - 2
src/views/layout/index.vue

@@ -6,7 +6,9 @@
                 <Menu @click="handleClick(item)" v-for="item in menus" :info="item" />
             </div>
             <div class=" flex-1 overflow-y-auto">
+              <Transition name="slide-right" >
                 <router-view />
+              </Transition>
             </div>
         </div>
     </div>
@@ -21,7 +23,7 @@ import Header from './components/Header.vue'
 import menuCooker1 from '/imgs/menu-cooker1.png'
 import menuCooker2 from '/imgs/menu-cooker2.png'
 import menuCooker3 from '/imgs/menu-cooker3.png'
-// import menuCooker3 from '/imgs/menu-cooker3.png'
+import menuCooker4 from '/imgs/menu-cooker4.png'
 
 import { useStoreI18n } from '@/hook/i18n'
 const { t, locale } = useI18n()
@@ -42,7 +44,7 @@ const menus = ref([
   },
   {
     name: $t('sidebar.goods'),
-    img: menuCooker3,
+    img: menuCooker4,
     key: 4,
     path: '/goods',
   },
@@ -63,6 +65,18 @@ function handleClick(m) {
 }
 </script>
 <style scoped lang="scss">
+.slide-right-enter-active,
+.slide-right-leave-active {
+  transition: all 0.5s ease;
+}
+.slide-right-enter-from {
+  opacity: 0;
+  transform: translateX(100%);
+}
+.slide-right-leave-to {
+  opacity: 0;
+  transform: translateX(-100%);
+}
 .main {
   width: 100%;
   height: 100vh;
@@ -80,4 +94,8 @@ function handleClick(m) {
     }
   }
 }
+// 隐藏滚动条
+::-webkit-scrollbar {
+  display: none;
+}
 </style>

+ 112 - 0
src/views/menu/components/pay-drawer.vue

@@ -0,0 +1,112 @@
+<template>
+    <div>
+        <!-- 触发抽屉的按钮,这里简单示例 -->
+        <el-drawer v-model="show" :show-close="false" direction="rtl" size="60%">
+            <div class="grid grid-cols-2 h-screen">
+                <div class="border-r border-gray-100 mr-5 h-full flex flex-col">
+                    <h3 class="p-3 text-2xl ">Confirmation</h3>
+                    <order type="pay" class="h-[calc(100vh-60px)]" ></order>
+                </div>
+                <div class="bg-white rounded-lg pr-5 flex flex-col h-full">
+                    <div class="flex-1">
+                        <div class="mb-8">
+                            <h1 class="text-2xl font-semibold mb-1">A1-Payment</h1>
+                            <p class="text-gray-500 text-sm">3 Payment Methods Available</p>
+                        </div>
+
+                        <div class="space-y-4 mb-8">
+                            <div class="flex justify-between items-center">
+                                <span class="text-gray-600">Service Charge</span>
+                                <span class="font-medium">$ 12.00</span>
+                            </div>
+                            <div class="flex justify-between items-center">
+                                <span class="text-gray-600">Sub Total</span>
+                                <span class="font-medium">$ 100.00</span>
+                            </div>
+                        </div>
+
+                        <div class="mb-8">
+                            <p class="text-gray-600 mb-4">Payment Method</p>
+                            <div class="grid grid-cols-3 gap-4">
+                                <button v-for="method in paymentMethods" :key="method.id"
+                                    @click="selectPaymentMethod(method.id)" :class="[
+                                        'flex flex-col items-center justify-center p-4 rounded-lg border transition-all duration-200 !rounded-button whitespace-nowrap',
+                                        selectedMethod === method.id ? 'border-orange-500 bg-orange-50' : 'border-gray-200 hover:border-orange-300'
+                                    ]">
+                                    <i
+                                        :class="['text-xl mb-2', method.icon, selectedMethod === method.id ? 'text-orange-500' : 'text-gray-400']"></i>
+                                    <span
+                                        :class="['text-sm', selectedMethod === method.id ? 'text-orange-500' : 'text-gray-600']">{{
+                                            method.name }}</span>
+                                </button>
+                            </div>
+                        </div>
+
+                        <div class="mb-12">
+                            <p class="text-gray-600 mb-4">Tip</p>
+                            <div class="flex items-center relative">
+                                <span class="text-gray-400 mr-2 absolute top-1/2 right-0 -translate-y-1/2">$</span>
+                                <input type="text" v-model="tipAmount"
+                                    class="w-full p-3 rounded-lg border-gray-200 border focus:border-orange-500 focus:ring-0 text-gray-700"
+                                    placeholder="Enter tip amount">
+                            </div>
+                        </div>
+                    </div>
+                    <div class="grid grid-cols-5 gap-3 mb-3 box-border ">
+                        <button
+                            class="col-span-2 px-6 py-3 border border-orange-500 text-orange-500 rounded-lg hover:bg-orange-50 transition-colors !rounded-button whitespace-nowrap">
+                            Registration
+                        </button>
+                        <button
+                            class="col-span-3 px-6 py-3 bg-orange-500 text-white rounded-lg hover:bg-orange-600 transition-colors !rounded-button whitespace-nowrap">
+                            Confirm Payment
+                        </button>
+                    </div>
+                </div>
+            </div>
+
+        </el-drawer>
+    </div>
+</template>
+
+<script setup>
+import { ref } from 'vue';
+import { ElDrawer } from 'element-plus';
+import order from './rightOrder/components/order.vue'
+
+const show = defineModel("show")
+const paymentMethods = [
+    { id: 1, name: 'Credit Card', icon: 'fas fa-credit-card' },
+    { id: 2, name: 'PayPal', icon: 'fab fa-paypal' },
+    { id: 3, name: 'Cash', icon: 'fas fa-money-bill' }
+];
+
+const selectedMethod = ref(1);
+const tipAmount = ref('');
+
+const selectPaymentMethod = (id) => {
+    selectedMethod.value = id;
+};
+</script>
+
+<style scoped>
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+    -webkit-appearance: none;
+    margin: 0;
+}
+
+input[type="number"] {
+    -moz-appearance: textfield;
+}
+
+:deep(.el-drawer__header) {
+    margin: 0;
+    padding: 0;
+}
+
+:deep(.el-drawer__body) {
+    margin: 0;
+    padding: 0;
+}
+</style>

+ 8 - 4
src/views/menu/components/rightOrder/components/order.vue

@@ -48,13 +48,13 @@
           </div>
         </div>
 
-        <div class="border-t border-gray-100 pt-4">
-          <div class="mb-4">
+        <div class="border-t border-gray-100 pt-4" >
+          <div class="mb-4" v-show="type!='pay'">
             <h3 class="font-medium mb-2">Order Notes</h3>
             <p class="text-gray-600 text-sm">No Chili, No Cilantro</p>
           </div>
 
-          <div class="flex items-center justify-between pt-4 border-t border-gray-100">
+          <div class="flex items-center justify-between pt-4  border-gray-100">
             <span class="font-medium">Total</span>
             <span class="text-sm font-medium">${{ total.toFixed(2) }}</span>
           </div>
@@ -75,7 +75,11 @@ interface OrderItem {
   quantity: number
   image: string
 }
-
+const props = defineProps({
+  type:{
+    default:'detail'
+  }
+})
 const orderItems = ref<OrderItem[]>([
   {
     name: 'Spicy Seasoned Seafood',

+ 2 - 2
src/views/menu/components/rightOrder/rightOrder.vue

@@ -16,6 +16,7 @@
           Registration
         </button>
         <button
+          @click="emits('showPayDrawer')"
           class="rounded text-sm py-3 px-6 bg-white border border-gray-200 text-gray-700 !rounded-button whitespace-nowrap hover:bg-gray-50 transition-colors"
         >
           Kitchen Receipt
@@ -34,8 +35,7 @@
 <script lang="ts" setup>
 import noProduct from '@/components/noProduct.vue'
 import order from './components/order.vue'
-import { emit } from '@tauri-apps/api/event';
-const emits= defineEmits(['showDeskDrawer'])
+const emits= defineEmits(['showDeskDrawer','showPayDrawer'])
 
 </script>
 

+ 81 - 13
src/views/menu/index.vue

@@ -8,6 +8,7 @@
               class="flex-1 h-full pr-[10px] flex items-center justify-between cursor-pointer overflow-hidden"
             >
               <div
+                @click="handleArrow(-1)"
                 class="text-[#999] shrink-0 flex items-center justify-center h-[34px] w-[44px] border border-[#e6e6e6] rounded-[12px]"
               >
                 <el-icon>
@@ -21,14 +22,17 @@
               >
                 <div ref="" class="flex flex-nowrap items-center">
                   <div
-                    v-for="item in products"
-                    class="flex items-center shrink-0 mr-[20px] h-[34px]"
+                    @click="selectMenu(index)"
+                    v-for="(item, index) in products"
+                    class="flex items-center p-2 shrink-0 mr-[20px] h-[34px]"
+                    :class="[currentIndex == index ? 'active' : '']"
                   >
                     {{ item.name }}
                   </div>
                 </div>
               </div>
               <div
+                @click="handleArrow(1)"
                 class="text-[#999] shrink-0 flex items-center justify-center h-[34px] w-[44px] border border-[#e6e6e6] rounded-[12px]"
               >
                 <el-icon>
@@ -39,7 +43,7 @@
           </div>
           <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
             <div
-              v-for="product in products"
+              v-for="(product, index) in products"
               :key="product.id"
               @click="show = true"
               class="bg-white rounded-xl shadow-sm transition-transform"
@@ -67,28 +71,26 @@
       </div>
     </div>
     <div class="w-[500px] h-full overflow-hidden border-l border-gray-200">
-      <rightOrder @showDeskDrawer="catgroyClick"></rightOrder>
+      <rightOrder @showDeskDrawer="catgroyClick" @showPayDrawer="onPay"></rightOrder>
     </div>
     <OrderDrawer v-model:show="show" />
     <deskDrawer v-model:show="deskShow" />
+    <payDrawer v-model:show="payShow" />
   </div>
 </template>
-<script lang="ts" setup>
+<script setup>
   import { ref, onMounted, nextTick } from 'vue'
-  import { CategoryService } from '@/service/CategoryService'
   import { useI18n } from 'vue-i18n'
   import { ArrowRight, ArrowLeft } from '@element-plus/icons-vue'
   import rightOrder from './components/rightOrder/rightOrder.vue'
   import OrderDrawer from './components/order-drawer.vue'
   import deskDrawer from './components/desk-drawer.vue'
+  import payDrawer from './components/pay-drawer.vue'
   const { t } = useI18n()
-  const scrollRef = ref(null)
 
   const show = ref(false)
 
-  onMounted(() => {
-    CategoryService.getAll()
-  })
+  onMounted(() => {})
 
   const products = ref([
     {
@@ -146,20 +148,86 @@
   const catgroyClick = () => {
     deskShow.value = true
   }
+
+  const scrollRef = ref(null)
+  const currentIndex = ref(0)
+  let positions = []
+
+  const recalculatePositions = () => {
+    const flexContainer = scrollRef.value?.firstElementChild
+    if (!flexContainer) return []
+
+    const items = Array.from(flexContainer.children)
+    let total = 0
+
+    return items.map((item, index) => {
+      const style = window.getComputedStyle(item)
+      const margin = index < items.length - 1 ? parseFloat(style.marginRight) : 0
+      const start = total
+      total += item.offsetWidth + margin
+      return { start, end: total - margin }
+    })
+  }
+
+  const scrollToIndex = (index) => {
+    if (!scrollRef.value) return
+
+    const containerWidth = scrollRef.value.offsetWidth
+    const target = positions[index]
+
+    if (!target) return
+
+    const scrollPos = Math.max(
+      0,
+      Math.min(
+        target.start - (containerWidth - (target.end - target.start)) / 2,
+        scrollRef.value.scrollWidth - containerWidth,
+      ),
+    )
+
+    scrollRef.value.scrollTo({
+      left: scrollPos,
+      behavior: 'smooth',
+    })
+  }
+
+  const handleArrow = (direction) => {
+    positions = recalculatePositions()
+    currentIndex.value = Math.max(0, Math.min(currentIndex.value + direction, positions.length - 1))
+    scrollToIndex(currentIndex.value)
+  }
+
+  const selectMenu = (index) => {
+    currentIndex.value = index
+    scrollToIndex(index)
+  }
+
+  //pay
+  const payShow = ref(false)
+  const onPay = () => {
+    payShow.value = true
+  }
 </script>
 <style scoped>
+  .active {
+    background-color: #f67f20;
+    color: white;
+    border-radius: 5px;
+  }
   ::-webkit-scrollbar-thumb {
     background-color: red;
   }
+
   /* 隐藏整个滚动条 */
   ::-webkit-scrollbar {
     display: none;
   }
 
   /* 或者仅隐藏滚动条的轨道,保留滑块可操作性,但视觉上不显示滚动条 */
-  ::-webkit-scrollbar-track {
-    display: none;
-  }
+  /* ::-webkit-scrollbar-track {
+  display: none;
+} */
+
   .text-container {
     width: 100%;
     overflow: hidden;

+ 12 - 8
src/views/order/index.vue

@@ -1,8 +1,8 @@
 <!-- 代码已包含 CSS:使用 TailwindCSS , 安装 TailwindCSS 后方可看到布局样式效果 -->
 
 <template>
-  <div class=" bg-gray-50 p-8 bg-white">
-    <div class="mx-auto w-full">
+  <div class=" bg-gray-50 box-border p-8 bg-white h-full ">
+    <div class="mx-auto h-full w-full flex flex-col">
       <!-- Search Area -->
       <div class="mb-6 flex items-center gap-4">
         <el-input v-model="searchKeyword" placeholder="Enter Keywords To Search" class="!rounded-button">
@@ -31,7 +31,8 @@
 
       <!-- Table -->
       <!-- 内容居中 -->
-      <el-table :data="tableData" class="w-full" :cell-style="{ textAlign: 'center' }"
+      <Empty v-if="tableData.length==0" class="flex-1" img="/src/assets/img/orderList/暂无支付记录.svg" text="No order information available at the moment"></Empty>
+      <el-table v-else :data="tableData" class="w-full flex-1 " :cell-style="{ textAlign: 'center'}"
         :header-cell-style="{ textAlign: 'center' }">
         <el-table-column prop="orderNumber" label="Order Number" width="120" />
         <el-table-column prop="employeeId" label="Employee ID" width="120" />
@@ -52,14 +53,13 @@
           </template>
         </el-table-column>
       </el-table>
-
-
-    </div>
-    <!-- Pagination -->
-    <div class="fixed bottom-5 right-5 flex items-center justify-between">
+    <div class="flex items-center justify-end mt-2">
       <el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 30, 40, 50]"
         :total="total" layout="prev, pager, next, sizes" />
     </div>
+
+    </div>
+
   </div>
 </template>
 
@@ -67,6 +67,7 @@
 import { ref } from 'vue';
 import { Search } from '@element-plus/icons-vue';
 import { useRouter } from 'vue-router';
+import Empty from '@/components/noProduct.vue';
 const router = useRouter();
 
 const searchKeyword = ref('');
@@ -166,4 +167,7 @@ const handleDetails = (row) => {
   --el-color-info:white;
   --el-input-border-color:#f67f20;
 }
+:deep(.el-table .cell){
+  white-space: nowrap;
+}
 </style>