From deb5baea0b833c619cddc85f5409137fade95dca Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 06 一月 2026 10:52:46 +0800
Subject: [PATCH] 二级套餐包改造: 1.封装公用组件
---
/dev/null | 43 ----
src/views/basicData/customerFile/index.vue | 88 +++-----
src/views/salesManagement/salesLedger/index.vue | 10
src/components/Dialog/FileListDialog.vue | 164 ++++++++++++++++
src/components/Dialog/FormDialog.vue | 73 +++++++
src/components/Dialog/ImportDialog.vue | 172 +++++++++++++++++
6 files changed, 451 insertions(+), 99 deletions(-)
diff --git a/src/components/Dialog/FileListDialog.vue b/src/components/Dialog/FileListDialog.vue
new file mode 100644
index 0000000..ea269d7
--- /dev/null
+++ b/src/components/Dialog/FileListDialog.vue
@@ -0,0 +1,164 @@
+<template>
+ <el-dialog
+ v-model="dialogVisible"
+ :title="title"
+ :width="width"
+ :before-close="handleClose"
+ >
+ <el-table :data="tableData" border :height="tableHeight">
+ <el-table-column
+ :label="nameColumnLabel"
+ :prop="nameColumnProp"
+ :min-width="nameColumnMinWidth"
+ show-overflow-tooltip
+ />
+ <el-table-column
+ v-if="showActions"
+ fixed="right"
+ label="鎿嶄綔"
+ :width="actionColumnWidth"
+ align="center"
+ >
+ <template #default="scope">
+ <el-button
+ v-if="showDownload"
+ link
+ type="primary"
+ size="small"
+ @click="handleDownload(scope.row)"
+ >
+ 涓嬭浇
+ </el-button>
+ <el-button
+ v-if="showPreview"
+ link
+ type="primary"
+ size="small"
+ @click="handlePreview(scope.row)"
+ >
+ 棰勮
+ </el-button>
+ <slot name="actions" :row="scope.row"></slot>
+ </template>
+ </el-table-column>
+ <slot name="columns"></slot>
+ </el-table>
+ </el-dialog>
+ <filePreview v-if="showPreview" ref="filePreviewRef" />
+</template>
+
+<script setup>
+import { ref, computed, getCurrentInstance } from 'vue'
+import filePreview from '@/components/filePreview/index.vue'
+
+const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ title: {
+ type: String,
+ default: '闄勪欢'
+ },
+ width: {
+ type: String,
+ default: '40%'
+ },
+ tableHeight: {
+ type: String,
+ default: '40vh'
+ },
+ nameColumnLabel: {
+ type: String,
+ default: '闄勪欢鍚嶇О'
+ },
+ nameColumnProp: {
+ type: String,
+ default: 'name'
+ },
+ nameColumnMinWidth: {
+ type: [String, Number],
+ default: 400
+ },
+ actionColumnWidth: {
+ type: [String, Number],
+ default: 100
+ },
+ showActions: {
+ type: Boolean,
+ default: true
+ },
+ showDownload: {
+ type: Boolean,
+ default: true
+ },
+ showPreview: {
+ type: Boolean,
+ default: true
+ },
+ urlField: {
+ type: String,
+ default: 'url'
+ },
+ downloadMethod: {
+ type: Function,
+ default: null
+ },
+ previewMethod: {
+ type: Function,
+ default: null
+ }
+})
+
+const emit = defineEmits(['update:modelValue', 'close', 'download', 'preview'])
+
+const { proxy } = getCurrentInstance()
+const filePreviewRef = ref(null)
+
+const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: (val) => emit('update:modelValue', val)
+})
+
+const tableData = ref([])
+
+const handleClose = () => {
+ emit('close')
+ dialogVisible.value = false
+}
+
+const handleDownload = (row) => {
+ if (props.downloadMethod) {
+ props.downloadMethod(row)
+ } else {
+ // 榛樿涓嬭浇鏂规硶
+ proxy.$download.name(row[props.urlField])
+ }
+ emit('download', row)
+}
+
+const handlePreview = (row) => {
+ if (props.previewMethod) {
+ props.previewMethod(row)
+ } else {
+ // 榛樿棰勮鏂规硶
+ if (filePreviewRef.value) {
+ filePreviewRef.value.open(row[props.urlField])
+ }
+ }
+ emit('preview', row)
+}
+
+const open = (list) => {
+ dialogVisible.value = true
+ tableData.value = list || []
+}
+
+defineExpose({
+ open
+})
+</script>
+
+<style scoped>
+</style>
+
diff --git a/src/components/Dialog/FormDialog.vue b/src/components/Dialog/FormDialog.vue
new file mode 100644
index 0000000..5e21b1d
--- /dev/null
+++ b/src/components/Dialog/FormDialog.vue
@@ -0,0 +1,73 @@
+<template>
+ <el-dialog
+ v-model="dialogVisible"
+ :title="computedTitle"
+ :width="width"
+ @close="handleClose"
+ >
+ <slot></slot>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleConfirm">纭</el-button>
+ <el-button @click="handleCancel">鍙栨秷</el-button>
+ </div>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+
+const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ title: {
+ type: [String, Function],
+ default: ''
+ },
+ operationType: {
+ type: String,
+ default: ''
+ },
+ width: {
+ type: String,
+ default: '70%'
+ }
+})
+
+const emit = defineEmits(['update:modelValue', 'close', 'confirm', 'cancel'])
+
+const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: (val) => emit('update:modelValue', val)
+})
+
+const computedTitle = computed(() => {
+ if (typeof props.title === 'function') {
+ return props.title(props.operationType)
+ }
+ return props.title
+})
+
+const handleClose = () => {
+ emit('close')
+}
+
+const handleConfirm = () => {
+ emit('confirm')
+}
+
+const handleCancel = () => {
+ emit('cancel')
+ dialogVisible.value = false
+}
+</script>
+
+<style scoped>
+.dialog-footer {
+ text-align: center;
+}
+</style>
+
diff --git a/src/components/Dialog/ImportDialog.vue b/src/components/Dialog/ImportDialog.vue
new file mode 100644
index 0000000..5b126dc
--- /dev/null
+++ b/src/components/Dialog/ImportDialog.vue
@@ -0,0 +1,172 @@
+<template>
+ <el-dialog
+ :title="title"
+ v-model="dialogVisible"
+ :width="width"
+ :append-to-body="appendToBody"
+ @close="handleClose"
+ >
+ <el-upload
+ ref="uploadRef"
+ :limit="limit"
+ :accept="accept"
+ :headers="headers"
+ :action="action"
+ :disabled="disabled"
+ :before-upload="beforeUpload"
+ :on-progress="onProgress"
+ :on-success="onSuccess"
+ :on-error="onError"
+ :on-change="onChange"
+ :auto-upload="autoUpload"
+ drag
+ >
+ <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
+ <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
+ <template #tip>
+ <div class="el-upload__tip text-center">
+ <span>{{ tipText }}</span>
+ <el-link
+ v-if="showDownloadTemplate"
+ type="primary"
+ :underline="false"
+ style="font-size: 12px; vertical-align: baseline; margin-left: 5px;"
+ @click="handleDownloadTemplate"
+ >涓嬭浇妯℃澘</el-link
+ >
+ </div>
+ </template>
+ </el-upload>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="handleConfirm">纭� 瀹�</el-button>
+ <el-button @click="handleCancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+</template>
+
+<script setup>
+import { computed, ref } from 'vue'
+import { UploadFilled } from '@element-plus/icons-vue'
+
+const props = defineProps({
+ modelValue: {
+ type: Boolean,
+ default: false
+ },
+ title: {
+ type: String,
+ default: '瀵煎叆'
+ },
+ width: {
+ type: String,
+ default: '400px'
+ },
+ appendToBody: {
+ type: Boolean,
+ default: true
+ },
+ limit: {
+ type: Number,
+ default: 1
+ },
+ accept: {
+ type: String,
+ default: '.xlsx, .xls'
+ },
+ headers: {
+ type: Object,
+ default: () => ({})
+ },
+ action: {
+ type: String,
+ required: true
+ },
+ disabled: {
+ type: Boolean,
+ default: false
+ },
+ autoUpload: {
+ type: Boolean,
+ default: false
+ },
+ tipText: {
+ type: String,
+ default: '浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�'
+ },
+ showDownloadTemplate: {
+ type: Boolean,
+ default: true
+ },
+ beforeUpload: {
+ type: Function,
+ default: null
+ },
+ onProgress: {
+ type: Function,
+ default: null
+ },
+ onSuccess: {
+ type: Function,
+ default: null
+ },
+ onError: {
+ type: Function,
+ default: null
+ },
+ onChange: {
+ type: Function,
+ default: null
+ }
+})
+
+const emit = defineEmits(['update:modelValue', 'close', 'confirm', 'cancel', 'download-template'])
+
+const dialogVisible = computed({
+ get: () => props.modelValue,
+ set: (val) => emit('update:modelValue', val)
+})
+
+const uploadRef = ref(null)
+
+const handleClose = () => {
+ emit('close')
+}
+
+const handleConfirm = () => {
+ emit('confirm')
+}
+
+const submit = () => {
+ if (uploadRef.value) {
+ uploadRef.value.submit()
+ }
+}
+
+const handleCancel = () => {
+ emit('cancel')
+ dialogVisible.value = false
+}
+
+const handleDownloadTemplate = () => {
+ emit('download-template')
+}
+
+defineExpose({
+ uploadRef,
+ submit,
+ clearFiles: () => {
+ if (uploadRef.value) {
+ uploadRef.value.clearFiles()
+ }
+ }
+})
+</script>
+
+<style scoped>
+.dialog-footer {
+ text-align: center;
+}
+</style>
+
diff --git a/src/views/basicData/customerFile/index.vue b/src/views/basicData/customerFile/index.vue
index 0f39e25..1552587 100644
--- a/src/views/basicData/customerFile/index.vue
+++ b/src/views/basicData/customerFile/index.vue
@@ -47,11 +47,14 @@
@pagination="pagination"
></PIMTable>
</div>
- <el-dialog
+ <FormDialog
v-model="dialogFormVisible"
- :title="operationType === 'add' ? '鏂板瀹㈡埛淇℃伅' : '缂栬緫瀹㈡埛淇℃伅'"
+ :title="(type) => type === 'add' ? '鏂板瀹㈡埛淇℃伅' : '缂栬緫瀹㈡埛淇℃伅'"
+ :operation-type="operationType"
width="70%"
@close="closeDia"
+ @confirm="submitForm"
+ @cancel="closeDia"
>
<el-form
:model="form"
@@ -193,63 +196,31 @@
</el-col>
</el-row>
</el-form>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitForm">纭</el-button>
- <el-button @click="closeDia">鍙栨秷</el-button>
- </div>
- </template>
- </el-dialog>
+ </FormDialog>
<!-- 鐢ㄦ埛瀵煎叆瀵硅瘽妗� -->
- <el-dialog
- :title="upload.title"
+ <ImportDialog
+ ref="importDialogRef"
v-model="upload.open"
+ :title="upload.title"
width="400px"
- append-to-body
- >
- <el-upload
- ref="uploadRef"
- :limit="1"
- accept=".xlsx, .xls"
- :headers="upload.headers"
- :action="upload.url + '?updateSupport=' + upload.updateSupport"
- :disabled="upload.isUploading"
- :before-upload="upload.beforeUpload"
- :on-progress="upload.onProgress"
- :on-success="upload.onSuccess"
- :on-error="upload.onError"
- :on-change="upload.onChange"
- :auto-upload="false"
- drag
- >
- <el-icon class="el-icon--upload"><upload-filled /></el-icon>
- <div class="el-upload__text">灏嗘枃浠舵嫋鍒版澶勶紝鎴�<em>鐐瑰嚮涓婁紶</em></div>
- <template #tip>
- <div class="el-upload__tip text-center">
- <span>浠呭厑璁稿鍏ls銆亁lsx鏍煎紡鏂囦欢銆�</span>
- <el-link
- type="primary"
- :underline="false"
- style="font-size: 12px; vertical-align: baseline"
- @click="importTemplate"
- >涓嬭浇妯℃澘</el-link
- >
- </div>
- </template>
- </el-upload>
- <template #footer>
- <div class="dialog-footer">
- <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button>
- <el-button @click="upload.open = false">鍙� 娑�</el-button>
- </div>
- </template>
- </el-dialog>
+ :action="upload.url"
+ :headers="upload.headers"
+ :disabled="upload.isUploading"
+ :before-upload="upload.beforeUpload"
+ :on-progress="upload.onProgress"
+ :on-success="upload.onSuccess"
+ :on-error="upload.onError"
+ :on-change="upload.onChange"
+ @confirm="submitFileForm"
+ @cancel="handleImportCancel"
+ @download-template="importTemplate"
+ />
</div>
</template>
<script setup>
import {onMounted, ref} from "vue";
-import { Search } from "@element-plus/icons-vue";
+import { Search, Close } from "@element-plus/icons-vue";
import {
addCustomer,
delCustomer,
@@ -261,6 +232,8 @@
import { userListNoPage } from "@/api/system/user.js";
import useUserStore from "@/store/modules/user";
import { getToken } from "@/utils/auth.js";
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import ImportDialog from "@/components/Dialog/ImportDialog.vue";
const { proxy } = getCurrentInstance();
const userStore = useUserStore();
@@ -338,6 +311,7 @@
const selectedRows = ref([]);
const userList = ref([]);
const tableLoading = ref(false);
+const importDialogRef = ref(null);
const page = reactive({
current: 1,
size: 100,
@@ -426,7 +400,9 @@
if(response.code === 200){
proxy.$modal.msgSuccess("鏂囦欢涓婁紶鎴愬姛");
upload.open = false;
- proxy.$refs["uploadRef"].clearFiles();
+ if (importDialogRef.value) {
+ importDialogRef.value.clearFiles();
+ }
getList();
}else if(response.code === 500){
proxy.$modal.msgError(response.msg);
@@ -484,7 +460,13 @@
/** 鎻愪氦涓婁紶鏂囦欢 */
function submitFileForm() {
upload.isUploading = true;
- proxy.$refs["uploadRef"].submit();
+ if (importDialogRef.value) {
+ importDialogRef.value.submit();
+ }
+}
+/** 鍙栨秷瀵煎叆 */
+function handleImportCancel() {
+ upload.open = false;
}
/** 瀵煎叆鎸夐挳鎿嶄綔 */
function handleImport() {
diff --git a/src/views/salesManagement/salesLedger/fileList.vue b/src/views/salesManagement/salesLedger/fileList.vue
deleted file mode 100644
index da37db2..0000000
--- a/src/views/salesManagement/salesLedger/fileList.vue
+++ /dev/null
@@ -1,43 +0,0 @@
-<template>
- <el-dialog v-model="dialogVisible" title="闄勪欢" width="40%" :before-close="handleClose">
- <el-table :data="tableData" border height="40vh">
- <el-table-column label="闄勪欢鍚嶇О" prop="name" min-width="400" show-overflow-tooltip />
- <el-table-column fixed="right" label="鎿嶄綔" width="100" align="center">
- <template #default="scope">
- <el-button link type="primary" size="small" @click="downLoadFile(scope.row)">涓嬭浇</el-button>
- <el-button link type="primary" size="small" @click="lookFile(scope.row)">棰勮</el-button>
- </template>
- </el-table-column>
- </el-table>
- </el-dialog>
- <filePreview ref="filePreviewRef" />
-</template>
-
-<script setup>
-import { ref } from 'vue'
-import filePreview from '@/components/filePreview/index.vue'
-
-const dialogVisible = ref(false)
-const tableData = ref([])
-const { proxy } = getCurrentInstance();
-const filePreviewRef = ref()
-const handleClose = () => {
- dialogVisible.value = false
-}
-const open = (list) => {
- dialogVisible.value = true
- tableData.value = list
-}
-const downLoadFile = (row) => {
- proxy.$download.name(row.url);
-
-}
-const lookFile = (row) => {
- filePreviewRef.value.open(row.url)
-}
-defineExpose({
- open
-})
-</script>
-
-<style></style>
\ No newline at end of file
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index 94af430..efc365e 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -450,7 +450,7 @@
</div>
</template>
</el-dialog>
- <FileList ref="fileListRef" />
+ <FileListDialog ref="fileListRef" v-model="fileListDialogVisible" />
</div>
</template>
@@ -462,7 +462,7 @@
import {ElMessage, ElMessageBox} from "element-plus";
import useUserStore from "@/store/modules/user";
import { userListNoPage } from "@/api/system/user.js";
-import FileList from "./fileList.vue";
+import FileListDialog from '@/components/Dialog/FileListDialog.vue';
import {
ledgerListPage,
productList,
@@ -1516,9 +1516,13 @@
* @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
*/
const fileListRef = ref(null)
+const fileListDialogVisible = ref(false)
const downLoadFile = (row) => {
getSalesLedgerWithProducts({ id: row.id, type: 1 }).then((res) => {
- fileListRef.value.open(res.salesLedgerFiles)
+ if (fileListRef.value) {
+ fileListRef.value.open(res.salesLedgerFiles)
+ fileListDialogVisible.value = true
+ }
});
}
--
Gitblit v1.9.3