Pārlūkot izejas kodu

feat(product-manage): 添加权限控制并优化导入功能

- 在产品列表页面添加权限控制,只有具有相应权限的用户才能看到和使用导入按钮
- 在编辑抽屉中添加价格相关字段的权限控制
- 新增 hasPermission 工具函数用于统一处理权限判断
- 优化导入按钮组件,使用新的权限控制逻辑
- 更新权限按钮组件,使用新的权限控制逻辑
WanGxC 6 mēneši atpakaļ
vecāks
revīzija
11859d18ce

+ 64 - 74
src/components/ImportButton/index.vue

@@ -1,4 +1,4 @@
-<script setup lang="ts">
+<script lang="ts" setup>
 /**
  * @Name: index.vue
  * @Description: 文件上传
@@ -7,41 +7,32 @@
 import { ButtonProps, genFileId, UploadInstance, UploadRawFile } from 'element-plus';
 import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
 import { uploadFile } from '/@/views/product-manage/product-list/api';
+import { hasPermission } from '/@/utils/hasPermission';
 
-const { data } = BtnPermissionStore();
 
 const attrs = useAttrs() as any;
 const refreshView = inject('refreshView');
 
 const props = defineProps<
-	{
-		uploadFunction: (url: 'URL') => Promise<any>;
-	} & Partial<Omit<ButtonProps, 'disabled' | 'loading' | 'color'>>
+    {
+      uploadFunction: (url: 'URL') => Promise<any>;
+    } & Partial<Omit<ButtonProps, 'disabled' | 'loading' | 'color'>>
 >();
 
-function hasPermission(permissions: string | string[]): boolean {
-	if (typeof permissions === 'string') {
-		return data.includes(permissions);
-	} else if (Array.isArray(permissions)) {
-		return permissions.every((permission) => data.includes(permission));
-	}
-	return false;
-}
-
 const upload = ref<UploadInstance>();
 const upBtnLoading = ref(false);
-const emits = defineEmits(['handel-error']);
+const emits = defineEmits([ 'handel-error' ]);
 
 /**
  * @description 替换文件并上传
  * @param files 文件列表
  */
 function handleExceed(files: any) {
-	upload.value!.clearFiles();
-	const file = files[0] as UploadRawFile;
-	file.uid = genFileId();
-	upload.value!.handleStart(file);
-	upload.value!.submit();
+  upload.value!.clearFiles();
+  const file = files[0] as UploadRawFile;
+  file.uid = genFileId();
+  upload.value!.handleStart(file);
+  upload.value!.submit();
 }
 
 /**
@@ -49,22 +40,22 @@ function handleExceed(files: any) {
  * @param uploadRequest 上传请求
  */
 async function handleCustomUpload(uploadRequest: any) {
-	upBtnLoading.value = true;
-	try {
-		const { file } = uploadRequest;
-		const formData = new FormData();
-		formData.append('file', file);
-		const resp = await uploadFile(formData);
-		const fileUrl = resp.data.url;
-		const response = await props.uploadFunction({ url: fileUrl });
-		handleResponse(response);
-		uploadRequest.onSuccess(response);
-	} catch (error) {
-		console.log('==Error==', error);
-		uploadRequest.onError(error);
-	} finally {
-		upBtnLoading.value = false;
-	}
+  upBtnLoading.value = true;
+  try {
+    const { file } = uploadRequest;
+    const formData = new FormData();
+    formData.append('file', file);
+    const resp = await uploadFile(formData);
+    const fileUrl = resp.data.url;
+    const response = await props.uploadFunction({ url: fileUrl });
+    handleResponse(response);
+    uploadRequest.onSuccess(response);
+  } catch (error) {
+    console.log('==Error==', error);
+    uploadRequest.onError(error);
+  } finally {
+    upBtnLoading.value = false;
+  }
 }
 
 /**
@@ -72,48 +63,47 @@ async function handleCustomUpload(uploadRequest: any) {
  * @param response 后端返回的响应
  */
 function handleResponse(response: any) {
-	if (response.data && response.data.length !== 0){
-		emits('handel-error', response.data);
-		return;
-	}
-	if (response.code === 2000) {
-		ElMessage.success({ message: response.msg, plain: true });
-		if (refreshView) {
-			refreshView();
-		}
-	}
-	 else {
-		ElMessage.error({ message: '上传失败', plain: true });
-	}
+  if (response.data && response.data.length !== 0) {
+    emits('handel-error', response.data);
+    return;
+  }
+  if (response.code === 2000) {
+    ElMessage.success({ message: response.msg, plain: true });
+    if (refreshView) {
+      refreshView();
+    }
+  } else {
+    ElMessage.error({ message: '上传失败', plain: true });
+  }
 }
 </script>
 
 <template>
-	<div>
-		<el-upload
-			ref="upload"
-			action="#"
-			:limit="1"
-			:show-file-list="false"
-			:auto-upload="true"
-			:on-exceed="handleExceed"
-			:http-request="handleCustomUpload"
-			accept=".xls,.xlsx"
-		>
-			<template #trigger>
-				<el-button
-					v-if="attrs.show ? hasPermission(attrs.show) : true"
-					:disabled="attrs.permissions ? !hasPermission(attrs.permissions) : false"
-					:loading="upBtnLoading"
-					:color="attrs.myColor"
-					v-bind="props"
-				>
-					<!--:loading="upBtnLoading" color="#6366f1" v-bind="props">-->
-					<slot></slot>
-				</el-button>
-			</template>
-		</el-upload>
-	</div>
+  <div>
+    <el-upload
+        ref="upload"
+        :auto-upload="true"
+        :http-request="handleCustomUpload"
+        :limit="1"
+        :on-exceed="handleExceed"
+        :show-file-list="false"
+        accept=".xls,.xlsx"
+        action="#"
+    >
+      <template #trigger>
+        <el-button
+            v-if="attrs.show ? hasPermission(attrs.show) : true"
+            :color="attrs.myColor"
+            :disabled="attrs.permissions ? !hasPermission(attrs.permissions) : false"
+            :loading="upBtnLoading"
+            v-bind="props"
+        >
+          <!--:loading="upBtnLoading" color="#6366f1" v-bind="props">-->
+          <slot></slot>
+        </el-button>
+      </template>
+    </el-upload>
+  </div>
 </template>
 
 <style scoped></style>

+ 3 - 12
src/components/PermissionButton/index.vue

@@ -5,27 +5,18 @@
  * @Author: Cheney
  */
 import { ButtonProps } from 'element-plus';
-import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
+import { hasPermission } from '/@/utils/hasPermission';
 
 
-const { data } = BtnPermissionStore();
-
 const attrs = useAttrs() as any;
 
 const props = defineProps<Partial<Omit<ButtonProps, ''>>>();
 
-function hasPermission(permissions: string | string[]): boolean {
-  if (typeof permissions === 'string') {
-    return data.includes(permissions);
-  } else if (Array.isArray(permissions)) {
-    return permissions.every(permission => data.includes(permission));
-  }
-  return false;
-}
+
 </script>
 
 <template>
-  <el-button v-if="attrs.permissions ? hasPermission(attrs.permissions) : true"
+  <el-button v-if="attrs.show ? hasPermission(attrs.show) : true"
              v-bind="props">
     <slot></slot>
   </el-button>

+ 17 - 0
src/utils/hasPermission.ts

@@ -0,0 +1,17 @@
+import { BtnPermissionStore } from '/@/plugin/permission/store.permission';
+
+
+const { data } = BtnPermissionStore();
+
+/**
+ * 判断是否有权限
+ * @param permissions /api/system/menu_button/menu_button_all_permission/ 中是否包含传递进来的值
+ */
+export function hasPermission(permissions: string | string[]): boolean {
+  if (typeof permissions === 'string') {
+    return data.includes(permissions);
+  } else if (Array.isArray(permissions)) {
+    return permissions.every(permission => data.includes(permission));
+  }
+  return false;
+}

+ 4 - 2
src/views/product-manage/product-list/component/DataTable.vue

@@ -20,6 +20,7 @@ import NoticeDialog from '/src/views/product-manage/product-list/component/Notic
 import * as api from '../api';
 import { useResponse } from '/@/utils/useResponse';
 import DownloadError from '/@/views/product-manage/product-list/component/DownloadError.vue';
+import { hasPermission } from '/@/utils/hasPermission';
 
 
 interface Parameter {
@@ -285,7 +286,7 @@ defineExpose({ fetchList });
             </template>
             <el-option label="商品通知模板" value="notice" />
             <el-option label="商品模板" value="product" />
-            <el-option label="指导价格模板" value="price" />
+            <el-option v-if="hasPermission('GuidancePriceTemplate')" label="指导价格模板" value="price" />
           </el-select>
         </div>
         <VerticalDivider class="px-1" style="margin-left: 7px;" />
@@ -295,7 +296,8 @@ defineExpose({ fetchList });
           <i class="bi bi-box-seam mr-3"></i>
           商品导入
         </ImportButton>
-        <ImportButton :icon="Money" :uploadFunction="api.uploadPrice" bg text @handelError="handleError">指导价格导入
+        <ImportButton :icon="Money" :show="'GuidancePriceImport'" :uploadFunction="api.uploadPrice" bg text
+                      @handelError="handleError">指导价格导入
         </ImportButton>
       </div>
     </template>

+ 13 - 9
src/views/product-manage/product-list/component/EditDrawer.vue

@@ -9,6 +9,7 @@ import { ElMessage, FormInstance, FormRules } from 'element-plus';
 import { Close, Finished } from '@element-plus/icons-vue';
 import * as api from '../api';
 import { useResponse } from '/@/utils/useResponse';
+import { hasPermission } from '/@/utils/hasPermission';
 
 
 const shopOptions = <Ref>inject('shopOptions');
@@ -132,15 +133,18 @@ function mappingShopId(val: any) {
             <el-option v-for="item in groupOptions" :label="item.tag" :value="item.tag" />
           </el-select>
         </el-form-item>
-        <el-form-item class="font-medium" label="展示价格:" prop="show_price">
-          <el-input v-model="ruleForm.show_price" />
-        </el-form-item>
-        <el-form-item class="font-medium" label="平时活动售价:" prop="activity_price">
-          <el-input v-model="ruleForm.activity_price" />
-        </el-form-item>
-        <el-form-item class="font-medium" label="最低活动售价:" prop="minimum_price">
-          <el-input v-model="ruleForm.minimum_price" />
-        </el-form-item>
+        <div v-if="hasPermission('PriceEdit')">
+          <el-form-item class="font-medium" label="展示价格:" prop="show_price">
+            <el-input v-model="ruleForm.show_price" />
+          </el-form-item>
+          <el-form-item class="font-medium" label="平时活动售价:" prop="activity_price">
+            <el-input v-model="ruleForm.activity_price" />
+          </el-form-item>
+          <el-form-item class="font-medium" label="最低活动售价:" prop="minimum_price">
+            <el-input v-model="ruleForm.minimum_price" />
+          </el-form-item>
+        </div>
+        
         <el-form-item>
           <el-divider />
           <div class="flex flex-1 justify-end">