Przeglądaj źródła

简单实现了单个商店界面,修改localStorage为sessionStorage

chillqi 2 lat temu
rodzic
commit
77acf511b3

+ 1 - 0
components.d.ts

@@ -9,6 +9,7 @@ declare module 'vue' {
   export interface GlobalComponents {
     AllStore: typeof import('./src/components/AllStore.vue')['default']
     DropFile: typeof import('./src/components/DropFile.vue')['default']
+    ElButton: typeof import('element-plus/es')['ElButton']
     ElCard: typeof import('element-plus/es')['ElCard']
     ElForm: typeof import('element-plus/es')['ElForm']
     ElFormItem: typeof import('element-plus/es')['ElFormItem']

+ 3 - 2
src/api/product.ts

@@ -1,9 +1,10 @@
 import {axios} from '../utils/request'
-import {PRODUCT_MODULE} from './_prefix'
+import {PRODUCT_MODULE, STORE_MODULE} from './_prefix'
 
 // 创建商店
 export const createProduct = payload => {
-    return axios.post(`${PRODUCT_MODULE}/create`, payload)
+    return axios.post(`${PRODUCT_MODULE}/`, payload,
+        {headers: {'Content-Type': 'application/json'}})
         .then(res => {
             return res;
         })

+ 1 - 2
src/api/store.ts

@@ -3,9 +3,8 @@ import {STORE_MODULE} from './_prefix'
 
 // 创建商店
 export const createStore = payload => {
-    console.log(payload)
     return axios.post(`${STORE_MODULE}/`, payload,
-        {headers: {'Content-Type': 'application/json','token': localStorage.getItem('token')}})
+        {headers: {'Content-Type': 'application/json'}})
         .then(res => {
             return res;
         })

+ 1 - 1
src/components/Header.vue

@@ -19,7 +19,7 @@ function logout() {
         center: true
       }
   ).then(() => {
-    localStorage.setItem('token', '')
+    sessionStorage.setItem('token', '')
     router.push({path: "/login"})
   }).catch(() => {
     // do nothing

+ 2 - 2
src/components/Login.vue

@@ -37,9 +37,9 @@
           // const token = res.result;
           // document.cookie = `token=${token}`
 
-          // token塞入localStorage中
+          // token塞入sessionStorage中
           const token = res.result
-          localStorage.setItem('token', token)
+          sessionStorage.setItem('token', token)
 
           // 路由跳转
           router.push({ path: "/allStore" })

+ 6 - 1
src/router/index.ts

@@ -34,6 +34,11 @@ const router = createRouter({
                 name: 'storeDetail',
                 component: () => import('../views/portal/StoreDetail.vue'),
             },
+            {
+                path: '/staff/createProduct/:storeId',
+                name: 'createProduct',
+                component: () => import('../views/staff/CreateProduct.vue'),
+            },
         ]
     }, {
         path: '/manager/createStore',
@@ -42,7 +47,7 @@ const router = createRouter({
 })
 
 router.beforeEach((to, from, next) => {
-    const role = localStorage.getItem('token');
+    const role = sessionStorage.getItem('token');
 
     console.log(role);
 

+ 2 - 2
src/utils/request.ts

@@ -5,13 +5,13 @@ const service = axios.create({
 });
 
 function hasToken() {
-    return !(localStorage.getItem('token') == '')
+    return !(sessionStorage.getItem('token') == '')
 }
 
 service.interceptors.request.use(
     config => {
         if(hasToken()) {
-            config.headers['token'] = localStorage.getItem('token')
+            config.headers['token'] = sessionStorage.getItem('token')
         }
         return config
     },

+ 41 - 26
src/views/portal/StoreDetail.vue

@@ -6,49 +6,64 @@ import {ref} from "vue";
 
 const router = useRouter();
 const storeId = router.currentRoute.value.params.storeId;
-let storeVO = ref([]);
-let id = ref('')
+let storeVO = ref()
+let id = ref(0)
 let name = ref('')
 let logoUrl = ref('')
-let rating = ref('')
-let number = ref('')
+let rating = ref(0)
+let number = ref(0)
 let location = ref('')
 
 getStoreDetail();
 
 function getStoreDetail() {
   getStoreById(storeId).then(res => {
-    storeVO.value = res.result;
-    console.log(storeVO.value);
-    id = storeVO.value.id
-    name = storeVO.value.name
-    logoUrl = storeVO.value.logoUrl
-    rating = storeVO.value.rating
-    number = storeVO.value.number
-    location = storeVO.value.location
+    storeVO.value = res.result
+    id.value = storeVO.value.id
+    name.value = storeVO.value.name
+    logoUrl.value = storeVO.value.logoUrl
+    rating.value = storeVO.value.rating
+    number.value = storeVO.value.number
+    location.value = storeVO.value.location
   })
 }
 
+function toCreateProduct() {
+  router.push("/staff/createProduct/" + storeId);
+}
+
 </script>
 
 <template>
-  <el-image class="logo-image" :src="logoUrl"/>
-  <el-row style="font-size: 20px">
-    {{ name }}
-  </el-row>
-  <el-row style="font-size: 10px">
-    评分人数: {{ number }}
-  </el-row>
-  <el-row style="font-size: 10px">
-    评分: {{ rating }}
-  </el-row>
-  <el-row style="font-size: 10px">
-    地址: {{ location }}
-  </el-row>
+  <div class="store-detail-main">
+    <el-image class="logo-image" :src="logoUrl"/>
+    <el-row style="font-size: 20px">
+      {{ name }}
+    </el-row>
+    <el-row style="font-size: 10px">
+      评分人数: {{ number }}
+    </el-row>
+    <el-row style="font-size: 10px">
+      评分: {{ rating }}
+    </el-row>
+    <el-row style="font-size: 10px">
+      地址: {{ location }}
+    </el-row>
+    <el-button class="create-product-button" type="primary" plain
+               @click="toCreateProduct()" >新增商品</el-button>
+  </div>
 </template>
 
 <style scoped>
+.store-detail-main {
+  margin-left: 50px;
+}
+
 .logo-image {
-  height: 120px;
+  width: 30%;
+}
+
+.create-product-button {
+  margin-top: 20px;
 }
 </style>

+ 200 - 0
src/views/staff/CreateProduct.vue

@@ -0,0 +1,200 @@
+<script setup lang="ts">
+import {useRouter} from "vue-router";
+import {ref, computed} from "vue";
+import {createProduct} from "../../api/product.ts";
+import {uploadImage} from "../../api/image.ts";
+
+const router = useRouter();
+const storeId = router.currentRoute.value.params.storeId;
+const name = ref('')
+const category = ref('')
+const price = ref()
+const photoUrlList = ref([])
+
+const hasNameInput = computed(() => name.value != '')
+const hasCategoryInput = computed(() => category.value != '')
+const hasPriceInput = computed(() => price.value != '')
+const nameLegal = hasNameInput
+const categoryLegal = hasCategoryInput
+const priceLegal = hasPriceInput
+
+const isDragging = ref(false)
+const files = ref([])
+const fileInputRef = ref(null)
+
+function onChange() {
+  files.value = [...fileInputRef.value.files]
+}
+
+function dragover(e) {
+  e.preventDefault()
+  isDragging.value = true
+}
+
+function dragleave() {
+  isDragging.value = false
+}
+
+function drop(e) {
+  e.preventDefault()
+  fileInputRef.value.files = e.dataTransfer.files
+  onChange()
+  isDragging.value = false
+}
+
+function generateURL(file) {
+  let formData = new FormData();
+  formData.append('file', file);
+  uploadImage(formData).then(res => {
+    photoUrlList.value.push(res.result);
+    console.log(photoUrlList.value)
+  });
+
+  let fileSrc = URL.createObjectURL(file);
+  setTimeout(() => {
+    URL.revokeObjectURL(fileSrc);
+  }, 1000);
+
+  return fileSrc;
+}
+
+function remove(i) {
+  files.value.splice(i, 1);
+  console.log(photoUrlList.value)
+}
+
+const createDisabled = computed(() => {
+  return !(nameLegal.value && categoryLegal.value && priceLegal.value && files.value);
+})
+
+function handleCreateProduct() {
+  const payload = {
+    storeId: storeId,
+    name: name.value,
+    category: category.value,
+    price: price.value,
+    photoUrlList: photoUrlList.value
+  };
+  createProduct(payload).then(res => {
+    console.log(res);
+  })
+}
+
+</script>
+
+<template>
+  <div class="flex flex-col items-center justify-center px-6 py-6 space-y-10">
+
+    <span class="flex items-center text-2xl font-semibold text-gray-900">
+      Blue Whale Shopping Online
+    </span>
+
+    <el-card class="w-full bg-white rounded-lg shadow-md md:mt-0 sm:max-w-md xl:p-0">
+
+      <div class="p-6 space-y-4 md:space-y-6 sm:p-8">
+
+        <h1 class="text-2xl font-bold leading-tight tracking-tight text-gray-900">
+          添加商品
+        </h1>
+
+        <el-form class="space-y-4 md:space-y-6">
+
+          <el-form-item>
+            <label for="name" class="inline-block mb-2 text-sm font-medium text-gray-900">商品名</label>
+            <input id="name" v-model="name"
+                   required
+                   class="bg-gray-50 border border-gray-300 text-gray-900 focus:outline-primary-600 sm:text-sm rounded-lg block w-full p-2.5"
+                   placeholder="请输入商品名">
+          </el-form-item>
+
+          <el-form-item class="mb-0">
+            <label for="category" class="block mb-2 text-sm font-medium text-gray-900">品类</label>
+            <select id="category"
+                    v-model="category"
+                    class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5">
+              <option disabled value="" selected>请选择品类</option>
+              <option value="FOOD">食品</option>
+              <option value="CLOTHES">服饰</option>
+              <option value="FURNITURE">家具</option>
+              <option value="ELECTRONICS">电子产品</option>
+              <option value="ENTERTAINMENT">娱乐</option>
+              <option value="SPORTS">体育产品</option>
+              <option value="LUXURY">奢侈品</option>
+            </select>
+          </el-form-item>
+
+          <el-form-item>
+            <label for="location" class="inline-block mb-2 text-sm font-medium text-gray-900">商品单价</label>
+            <input id="location" v-model="price"
+                   required
+                   class="bg-gray-50 border border-gray-300 text-gray-900 focus:outline-primary-600 sm:text-sm rounded-lg block w-full p-2.5"
+                   placeholder="请输入商品单价,单位(元)">
+          </el-form-item>
+
+          <el-form-item>
+            <label for="logoUrl" class="inline-block mb-2 text-sm font-medium text-gray-900">商品图片</label>
+            <div class="main">
+              <div
+                  class="dropzone-container"
+                  @dragover="dragover"
+                  @dragleave="dragleave"
+                  @drop="drop"
+              >
+                <input
+                    type="file"
+                    multiple
+                    name="file"
+                    id="fileInput"
+                    class="hidden-input"
+                    @change="onChange"
+                    ref="fileInputRef"
+                    accept=".pdf,.jpg,.jpeg,.png"
+                />
+
+                <label for="fileInput" class="file-label">
+                  <div v-if="isDragging">释放以将文件放到此处。</div>
+                  <div v-else>将文件拖到此处或单击此处上传。</div>
+                </label>
+
+                <div class="preview-container mt-4" v-if="files.length">
+                  <div v-for="file in files" :key="file.name" class="preview-card">
+                    <div>
+                      <img class="preview-img" :src="generateURL(file)"/>
+                      <p>
+                        {{ file.name }}
+                      </p>
+                    </div>
+                    <div>
+                      <button
+                          class="ml-2"
+                          type="button"
+                          @click="remove(files.indexOf(file))"
+                          title="Remove file"
+                      >
+                        <b>×</b>
+                      </button>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </el-form-item>
+
+          <el-form-item>
+            <button @click.prevent="handleCreateProduct()"
+                    :disabled="createDisabled"
+                    class="block my-3 w-full text-white bg-primary-600 hover:bg-primary-700 focus:ring-4 focus:outline-none focus:ring-primary-300 font-medium rounded-lg text-sm px-5 py-3 text-center disabled:bg-primary-100">
+              添加
+            </button>
+          </el-form-item>
+        </el-form>
+      </div>
+    </el-card>
+  </div>
+
+
+</template>
+
+<style scoped>
+
+</style>