From b430f8f2759129e86034d13bb7f4582fbfe708a1 Mon Sep 17 00:00:00 2001
From: zhang_12370 <z2864490065@outlook.com>
Date: 星期二, 01 七月 2025 18:07:45 +0800
Subject: [PATCH] 修改文档管理 开发设备管理模块
---
src/hooks/useFormData.js | 7
src/views/equipment/management/index.vue | 676 ++++++++++++++++++++++++
src/hooks/useModal.js | 41 +
src/components/Table/Pagination.vue | 100 +++
src/api/equipment/management/index.js | 32 +
src/hooks/usePaginationApi.jsx | 16
src/components/Table/PIMTable.vue | 432 +++++++++++++++
src/components/Table/table.vue | 39 +
src/views/equipment/management/mould/managementDialog.vue | 290 ++++++++++
src/utils/index.js | 5
src/views/archiveManagement/index.vue | 11
11 files changed, 1,634 insertions(+), 15 deletions(-)
diff --git a/src/api/equipment/management/index.js b/src/api/equipment/management/index.js
new file mode 100644
index 0000000..f7d7725
--- /dev/null
+++ b/src/api/equipment/management/index.js
@@ -0,0 +1,32 @@
+// 璁惧绠$悊
+import request from '@/utils/request'
+
+// /equipmentManagement/list
+// 鏌ヨ璁惧绠$悊鍒楄〃
+export function getManagementList(query) {
+ return request({
+ url: '/equipmentManagement/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// /equipmentManagement/addOrEditEquipment
+// 娣诲姞鎴栫紪杈戣澶�
+export function addOrEditEquipment(data) {
+ return request({
+ url: '/equipmentManagement/addOrEditEquipment',
+ method: 'post',
+ data
+ })
+}
+
+// /equipmentManagement/delEquipment
+// 鍒犻櫎璁惧
+export function delEquipment(data) {
+ return request({
+ url: '/equipmentManagement/delEquipment',
+ method: 'delete',
+ data
+ })
+}
\ No newline at end of file
diff --git a/src/components/Table/PIMTable.vue b/src/components/Table/PIMTable.vue
new file mode 100644
index 0000000..fb472fb
--- /dev/null
+++ b/src/components/Table/PIMTable.vue
@@ -0,0 +1,432 @@
+<template>
+ <el-table
+ ref="multipleTable"
+ v-loading="tableLoading"
+ :border="border"
+ :data="tableData"
+ :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+ :height="height"
+ :highlight-current-row="highlightCurrentRow"
+ :row-class-name="rowClassName"
+ :row-style="rowStyle"
+ :row-key="rowKey"
+ style="width: 100%"
+ tooltip-effect="dark"
+ :expand-row-keys="expandRowKeys"
+ :show-summary="isShowSummary"
+ :summary-method="summaryMethod"
+ @row-click="rowClick"
+ @current-change="currentChange"
+ @selection-change="handleSelectionChange"
+ @expand-change="expandChange"
+ class="lims-table"
+ >
+ <el-table-column
+ align="center"
+ type="selection"
+ width="55"
+ v-if="isSelection"
+ />
+ <el-table-column align="center" label="搴忓彿" type="index" width="60" />
+
+ <el-table-column
+ v-for="(item, index) in column"
+ :key="index"
+ :column-key="item.columnKey"
+ :filter-method="item.filterHandler"
+ :filter-multiple="item.filterMultiple"
+ :filtered-value="item.filteredValue"
+ :filters="item.filters"
+ :fixed="item.fixed"
+ :label="item.label"
+ :prop="item.prop"
+ show-overflow-tooltip
+ :align="item.align"
+ :sortable="!!item.sortable"
+ :type="item.type"
+ :width="item.width"
+ >
+ <template
+ v-if="item.hasOwnProperty('colunmTemplate')"
+ #[item.colunmTemplate]="scope"
+ >
+ <slot
+ v-if="item.theadSlot"
+ :name="item.theadSlot"
+ :index="scope.$index"
+ :row="scope.row"
+ />
+ </template>
+
+ <template #default="scope">
+ <!-- 鎻掓Ы -->
+ <div v-if="item.dataType == 'slot'">
+ <slot
+ v-if="item.slot"
+ :index="scope.$index"
+ :name="item.slot"
+ :row="scope.row"
+ />
+ </div>
+ <!-- 杩涘害鏉� -->
+ <div v-else-if="item.dataType == 'progress'">
+ <el-progress :percentage="Number(scope.row[item.prop])" />
+ </div>
+ <!-- 鍥剧墖 -->
+ <div v-else-if="item.dataType == 'image'">
+ <img
+ :src="javaApi + '/img/' + scope.row[item.prop]"
+ alt=""
+ style="width: 40px; height: 40px; margin-top: 10px"
+ />
+ </div>
+
+ <!-- tag -->
+ <div v-else-if="item.dataType == 'tag'">
+ <el-tag
+ v-if="
+ typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
+ 'string'
+ "
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(scope.row[item.prop], item.formatType)"
+ >
+ {{ formatters(scope.row[item.prop], item.formatData) }}
+ </el-tag>
+
+ <el-tag
+ v-for="(tag, index) in dataTypeFn(
+ scope.row[item.prop],
+ item.formatData
+ )"
+ v-else-if="
+ typeof dataTypeFn(scope.row[item.prop], item.formatData) ===
+ 'object'
+ "
+ :key="index"
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(tag, item.formatType)"
+ >
+ {{ item.tagGroup ? tag[item.tagGroup.label] ?? tag : tag }}
+ </el-tag>
+
+ <el-tag
+ v-else
+ :title="formatters(scope.row[item.prop], item.formatData)"
+ :type="formatType(scope.row[item.prop], item.formatType)"
+ >
+ {{ formatters(scope.row[item.prop], item.formatData) }}
+ </el-tag>
+ </div>
+
+ <!-- 鎸夐挳 -->
+ <div v-else-if="item.dataType == 'action'">
+ <template v-for="(o, key) in item.operation" :key="key">
+ <el-button
+ v-show="o.type != 'upload'"
+ size="small"
+ v-if="o.showHide ? o.showHide(scope.row) : true"
+ :disabled="o.disabled ? o.disabled(scope.row) : false"
+ :plain="o.plain"
+ type="primary"
+ :style="{
+ color:
+ o.name === '鍒犻櫎' || o.name === 'delete'
+ ? '#f56c6c'
+ : o.color,
+ }"
+ link
+ @click="o.clickFun(scope.row)"
+ :key="key"
+ >
+ {{ o.name }}
+ </el-button>
+ <el-upload
+ :action="
+ javaApi +
+ o.url +
+ '?id=' +
+ (o.uploadIdFun ? o.uploadIdFun(scope.row) : scope.row.id)
+ "
+ ref="uploadRef"
+ size="small"
+ :multiple="o.multiple ? o.multiple : false"
+ :limit="1"
+ :disabled="o.disabled ? o.disabled(scope.row) : false"
+ :accept="
+ o.accept
+ ? o.accept
+ : '.jpg,.jpeg,.png,.gif,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.pdf,.zip,.rar'
+ "
+ v-if="o.type == 'upload'"
+ style="display: inline-block; width: 50px"
+ v-show="o.showHide ? o.showHide(scope.row) : true"
+ :headers="uploadHeader"
+ :before-upload="(file) => beforeUpload(file, scope.$index)"
+ :on-change="
+ (file, fileList) => handleChange(file, fileList, scope.$index)
+ "
+ :on-error="
+ (error, file, fileList) =>
+ onError(error, file, fileList, scope.$index)
+ "
+ :on-success="
+ (response, file, fileList) =>
+ handleSuccessUp(response, file, fileList, scope.$index)
+ "
+ :on-exceed="onExceed"
+ :show-file-list="false"
+ >
+ <el-button
+ :size="o.size ? o.size : 'small'"
+ link
+ type="primary"
+ :disabled="o.disabled ? o.disabled(scope.row) : false"
+ >{{ o.name }}</el-button
+ >
+ </el-upload>
+ </template>
+ </div>
+ <!-- 鍙偣鍑荤殑鏂囧瓧 -->
+ <div
+ v-else-if="item.dataType == 'link'"
+ class="cell link"
+ style="width: 100%"
+ @click="goLink(scope.row, item.linkMethod)"
+ >
+ <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
+ </div>
+ <!-- 榛樿绾睍绀烘暟鎹� -->
+ <div v-else class="cell" style="width: 100%">
+ <span v-if="!item.formatData">{{ scope.row[item.prop] }}</span>
+ <span v-else>{{
+ formatters(scope.row[item.prop], item.formatData)
+ }}</span>
+ </div>
+ </template>
+ </el-table-column>
+ </el-table>
+ <pagination
+ v-if="page.total > 0"
+ :total="page.total"
+ :layout="page.layout"
+ :page="page.current"
+ :limit="page.size"
+ @pagination="paginationSearch"
+ />
+</template>
+
+<script setup>
+import pagination from "./Pagination.vue";
+import { ref, inject, getCurrentInstance } from "vue";
+import { ElMessage } from "element-plus";
+
+// 鑾峰彇鍏ㄥ眬鐨� uploadHeader
+const { proxy } = getCurrentInstance();
+const uploadHeader = proxy.uploadHeader;
+const javaApi = proxy.javaApi;
+
+const emit = defineEmits(["pagination", "expand-change", "selection-change"]);
+
+// Filters
+const typeFn = (val, row) => {
+ return typeof val === "function" ? val(row) : val;
+};
+
+const formatters = (val, format) => {
+ return typeof format === "function" ? format(val) : val;
+};
+
+// Props锛堜娇鐢� defineProps 鐨勯潪 TS 褰㈠紡锛�
+const props = defineProps({
+ tableLoading: {
+ type: Boolean,
+ default: false,
+ },
+ height: {
+ type: [Number, String],
+ default: "calc(100vh - 22em)",
+ },
+ expandRowKeys: {
+ type: Array,
+ default: () => [],
+ },
+ summaryMethod: {
+ type: Function,
+ default: () => {},
+ },
+ rowClick: {
+ type: Function,
+ default: () => {},
+ },
+ currentChange: {
+ type: Function,
+ default: () => {},
+ },
+ border: {
+ type: Boolean,
+ default: true,
+ },
+ isSelection: {
+ type: Boolean,
+ default: false,
+ },
+ isShowSummary: {
+ type: Boolean,
+ default: false,
+ },
+ highlightCurrentRow: {
+ type: Boolean,
+ default: false,
+ },
+ headerCellStyle: {
+ type: Object,
+ default: () => ({}),
+ },
+ column: {
+ type: Array,
+ default: () => [],
+ },
+ rowClassName: {
+ type: Function,
+ default: () => "",
+ },
+ rowStyle: {
+ type: [Object, Function],
+ default: () => ({}),
+ },
+ tableData: {
+ type: Array,
+ default: () => [],
+ },
+ rowKey: {
+ type: String,
+ default: undefined,
+ },
+ page: {
+ type: Object,
+ default: () => ({
+ total: 0,
+ current: 0,
+ size: 10,
+ layout: "total, sizes, prev, pager, next, jumper",
+ }),
+ },
+ total: {
+ type: Number,
+ default: 0,
+ },
+});
+
+// Data
+const uploadRefs = ref([]);
+const currentFiles = ref({});
+const uploadKeys = ref({});
+
+const indexMethod = (index) => {
+ return (props.page.current - 1) * props.page.size + index + 1;
+};
+
+// 鐐瑰嚮 link 浜嬩欢
+const goLink = (row, linkMethod) => {
+ if (!linkMethod) {
+ return ElMessage.warning("璇烽厤缃� link 浜嬩欢");
+ }
+ const parentMethod = getParentMethod(linkMethod);
+ if (typeof parentMethod === "function") {
+ parentMethod(row);
+ } else {
+ console.warn(`鐖剁粍浠朵腑鏈壘鍒版柟娉�: ${linkMethod}`);
+ }
+};
+
+// 鑾峰彇鐖剁粍浠舵柟娉曪紙绀轰緥瀹炵幇锛�
+const getParentMethod = (methodName) => {
+ const parentMethods = inject("parentMethods", {});
+ return parentMethods[methodName];
+};
+
+const dataTypeFn = (val, format) => {
+ if (typeof format === "function") {
+ return format(val);
+ } else return val;
+};
+
+const formatType = (val, format) => {
+ if (typeof format === "function") {
+ return format(val);
+ } else return "";
+};
+
+// 鏂囦欢鍙樺寲澶勭悊
+const handleChange = (file, fileList, index) => {
+ if (fileList.length > 1) {
+ const earliestFile = fileList[0];
+ uploadRefs.value[index]?.handleRemove(earliestFile);
+ }
+ currentFiles.value[index] = file;
+};
+
+// 鏂囦欢涓婁紶鍓嶆牎楠�
+const beforeUpload = (rawFile, index) => {
+ currentFiles.value[index] = {};
+ if (rawfile.size > 1024 * 1024 * 10 * 10) {
+ ElMessage.error("涓婁紶鏂囦欢涓嶈秴杩�10M");
+ return false;
+ }
+ return true;
+};
+
+// 涓婁紶鎴愬姛
+const handleSuccessUp = (response, file, fileList, index) => {
+ if (response.code == 200) {
+ if (uploadRefs[index]) {
+ uploadRefs[index].clearFiles();
+ }
+ currentFiles[index] = file;
+ ElMessage.success("涓婁紶鎴愬姛");
+ resetUploadComponent(index);
+ } else {
+ ElMessage.error(response.message);
+ }
+};
+
+const resetUploadComponent = (index) => {
+ uploadKeys[index] = Date.now();
+};
+
+// 涓婁紶澶辫触
+const onError = (error, file, fileList, index) => {
+ ElMessage.error("鏂囦欢涓婁紶澶辫触锛岃閲嶈瘯");
+ if (uploadRefs.value[index]) {
+ uploadRefs.value[index].clearFiles();
+ }
+};
+
+// 鏂囦欢鏁伴噺瓒呴檺鎻愮ず
+const onExceed = () => {
+ ElMessage.warning("瓒呭嚭鏂囦欢涓暟");
+};
+
+const paginationSearch = ({ page, limit }) => {
+ emit("pagination", { page: page, limit: limit });
+};
+
+const expandChange = (row, expandedRows) => {
+ emit("expand-change", row, expandedRows);
+};
+
+const handleSelectionChange = (newSelection) => {
+ emit("selection-change", newSelection);
+};
+</script>
+
+<style scoped lang="scss">
+.cell {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ padding-right: 0 !important;
+ padding-left: 0 !important;
+}
+</style>
diff --git a/src/components/Table/Pagination.vue b/src/components/Table/Pagination.vue
new file mode 100644
index 0000000..7639e64
--- /dev/null
+++ b/src/components/Table/Pagination.vue
@@ -0,0 +1,100 @@
+<template>
+ <div :class="{ hidden }" class="pagination-container">
+ <el-pagination
+ :background="background"
+ v-model:current-page="currentPage"
+ v-model:page-size="pageSize"
+ :layout="layout"
+ :page-sizes="pageSizes"
+ :pager-count="pagerCount"
+ :total="total"
+ v-bind="$attrs"
+ @size-change="handleSizeChange"
+ @current-change="handleCurrentChange"
+ />
+ </div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+import { scrollTo } from '@/utils/scroll-to'
+
+const props = defineProps({
+ total: {
+ type: Number,
+ required: true
+ },
+ page: {
+ type: Number,
+ default: 1
+ },
+ limit: {
+ type: Number,
+ default: 20
+ },
+ pageSizes: {
+ type: Array,
+ default: () => [10, 20, 30, 50, 100]
+ },
+ pagerCount: {
+ type: Number,
+ default: () => (document.body.clientWidth < 992 ? 5 : 7)
+ },
+ layout: {
+ type: String,
+ default: 'total, sizes, prev, pager, next, jumper'
+ },
+ background: {
+ type: Boolean,
+ default: true
+ },
+ autoScroll: {
+ type: Boolean,
+ default: true
+ },
+ hidden: {
+ type: Boolean,
+ default: false
+ }
+})
+
+const emit = defineEmits(['update:page', 'update:limit', 'pagination'])
+
+const currentPage = computed({
+ get: () => props.page,
+ set: (val) => emit('update:page', val)
+})
+
+const pageSize = computed({
+ get: () => props.limit,
+ set: (val) => emit('update:limit', val)
+})
+
+const handleSizeChange = (val) => {
+ if (currentPage.value * val > props.total) {
+ currentPage.value = 1
+ }
+ emit('pagination', { page: currentPage.value, limit: val })
+ if (props.autoScroll) {
+ scrollTo(0, 800)
+ }
+}
+
+const handleCurrentChange = (val) => {
+ emit('pagination', { page: val, limit: pageSize.value })
+ if (props.autoScroll) {
+ scrollTo(0, 800)
+ }
+}
+</script>
+
+<style scoped>
+.pagination-container {
+ background: #fff;
+ padding: 16px 0;
+ margin-top: 0;
+}
+.pagination-container.hidden {
+ display: none;
+}
+</style>
\ No newline at end of file
diff --git a/src/components/Table/table.vue b/src/components/Table/table.vue
new file mode 100644
index 0000000..01509b1
--- /dev/null
+++ b/src/components/Table/table.vue
@@ -0,0 +1,39 @@
+<template>
+ <el-table :data="tableData" :column="columnss" style="width: 100%">
+ <el-table-column type="index" width="50">
+ <template #default="scope">
+ {{ getRowIndex(scope.$index) }}
+ </template>
+ </el-table-column>
+ <el-table-column
+ v-for="(item, index) in columnss"
+ :key="index"
+ :prop="item.prop"
+ :label="item.label"
+ :align="item.align || 'center'"
+ :min-width="item.minWidth || '100px'"
+ :width="item.width"
+ :fixed="item.fixed || false"
+ :show-overflow-tooltip="showOverflowTooltip || true"
+ >
+ </el-table-column>
+ </el-table>
+</template>
+<script setup>
+import { ref, onMounted, watch, nextTick } from "vue";
+
+const props = defineProps({
+ tableData: {
+ type: Array,
+ default: () => [],
+ },
+ columnss: {
+ type: Array,
+ default: () => [],
+ },
+});
+const getRowIndex = (index) => {
+ return index + 1;
+};
+</script>
+<style scoped></style>
diff --git a/src/hooks/useFormData.js b/src/hooks/useFormData.js
index 325e981..e065382 100644
--- a/src/hooks/useFormData.js
+++ b/src/hooks/useFormData.js
@@ -4,7 +4,8 @@
*/
import { ref, reactive, computed, nextTick } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
-import { clone } from "lodash";
+import { deepClone } from "@/utils/index.js"
+
/**
* 鍒涘缓琛ㄥ崟鏁版嵁绠$悊鍔熻兘
@@ -324,8 +325,8 @@
}
// 鍚戝悗鍏煎鐨勯粯璁ゅ鍑�
-export default function useFormDataSimple(initData) {
- const form = reactive(clone(initData, true));
+export default function useFormDatas(initData) {
+ const form = reactive(deepClone(initData, true));
function resetForm() {
const initData2 = JSON.parse(JSON.stringify(initData));
diff --git a/src/hooks/useModal.js b/src/hooks/useModal.js
new file mode 100644
index 0000000..0d443a1
--- /dev/null
+++ b/src/hooks/useModal.js
@@ -0,0 +1,41 @@
+import { ref } from "vue";
+export function useModal(options) {
+ const id = ref();
+ const visible = ref(false);
+ const loading = ref(false);
+ const modalOptions = ref({});
+
+ const openModal = (e) => {
+ id.value = e;
+ modalOptions.value = {
+ title: e ? `淇敼${options.title}` : `鏂板${options.title}`,
+ content: "纭畾鎵ц姝ゆ搷浣滃悧锛�",
+ confirmText: "纭畾",
+ cancelText: "鍙栨秷",
+ };
+ visible.value = true;
+ };
+
+ // 鍏抽棴妯℃�佹
+ const closeModal = () => {
+ visible.value = false;
+ loading.value = false;
+ };
+
+ // 纭鎿嶄綔
+ const handleConfirm = async (callback) => {
+ loading.value = true;
+ callback();
+ closeModal();
+ };
+
+ return {
+ id,
+ visible,
+ loading,
+ modalOptions,
+ openModal,
+ closeModal,
+ handleConfirm,
+ };
+}
diff --git a/src/hooks/usePaginationApi.jsx b/src/hooks/usePaginationApi.jsx
index aa995b0..749b078 100644
--- a/src/hooks/usePaginationApi.jsx
+++ b/src/hooks/usePaginationApi.jsx
@@ -1,8 +1,8 @@
import { ref, reactive, watchEffect, unref } from "vue";
-import useFormData from "./useFormData.js";
-// import { message } from "@/utils/message";
+import useFormData from "@/hooks/useFormData";
+import { deepClone, isEqual } from "@/utils/index.js"
+import { ElMessage } from 'element-plus'
-import { clone, isEqual } from "lodash";
/**
* 鍒嗛〉api
* @param api 鎺ュ彛
@@ -20,7 +20,7 @@
) {
const dataList = ref([]);
const { form: filters, resetForm } = useFormData(initalFilters);
- let lastFilters = clone(initalFilters);
+ let lastFilters = deepClone(initalFilters);
const sorter = reactive(sorters || {});
const others = ref({});
const loading = ref(true);
@@ -79,14 +79,14 @@
// 濡傛灉杩欐鍜屼笂娆$殑filter涓嶅悓锛岄偅涔堝氨閲嶇疆椤电爜
if (!isEqual(unref(filters), lastFilters)) {
pagination.currentPage = 1;
- lastFilters = clone(unref(filters));
+ lastFilters = deepClone(unref(filters));
}
loading.value = true;
api({
...getFinalParams(),
current: pagination.currentPage,
size: pagination.pageSize
- }).then(({ code, data, ...rest }) => {
+ }).then(({ code, data, msg, ...rest }) => {
if (code == 200) {
// pagination.currentPage = meta.current_page;
// pagination.pageSize = meta.per_page;
@@ -97,7 +97,7 @@
loading.value = false;
} else {
loading.value = false;
- // message(data.msg, { type: "error" });
+ ElMessage({ message: msg, type: "error" });
}
});
}
@@ -120,7 +120,7 @@
}
watchEffect(() => {
- pagination.align = paginationAlign.value;
+ pagination.align = paginationAlign.value
});
// onMounted(() => {
diff --git a/src/utils/index.js b/src/utils/index.js
index 9329fe2..3c2e031 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -387,4 +387,7 @@
export function isNumberStr(str) {
return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str)
}
-
+
+export function isEqual(obj1, obj2) {
+ return JSON.stringify(obj1) === JSON.stringify(obj2);
+}
diff --git a/src/views/archiveManagement/index.vue b/src/views/archiveManagement/index.vue
index ac6274d..81d3a18 100644
--- a/src/views/archiveManagement/index.vue
+++ b/src/views/archiveManagement/index.vue
@@ -118,12 +118,12 @@
</el-input>
</div>
</el-col>
- <el-col :offset="10" :span="2">
+ <el-col :offset="8" :span="3">
<el-button :icon="Delete" type="danger" @click="delHandler"
>鍒犻櫎</el-button
>
</el-col>
- <el-col :span="2">
+ <el-col :span="3">
<el-button
:disabled="!tableSwitch"
:icon="Plus"
@@ -142,6 +142,7 @@
:table-data="tableData"
@edit="handleEdit"
@selection-change="handleSelectionChange"
+ style="height: calc(65vh);"
>
</ETable>
<Pagination
@@ -288,6 +289,7 @@
treeId: queryParams.treeId,
current: queryParams.current,
size: queryParams.pageSize,
+ searchAll: queryParams.searchAll,
});
if (res.code !== 200) {
@@ -556,7 +558,10 @@
};
// ===== 鐢熷懡鍛ㄦ湡 =====
-onMounted(getList);
+onMounted(()=>{
+ getList();
+ getArchiveListData();
+});
</script>
<style lang="scss" scoped>
.custom-tree-node {
diff --git a/src/views/equipment/management/index.vue b/src/views/equipment/management/index.vue
new file mode 100644
index 0000000..3481d2f
--- /dev/null
+++ b/src/views/equipment/management/index.vue
@@ -0,0 +1,676 @@
+<template>
+ <div class="app-container">
+ <el-form :inline="true" :model="queryParams" class="search-form">
+ <el-form-item v-if="shouldShowSearch" label="鎼滅储">
+ <el-input
+ v-model="queryParams.searchAll"
+ :placeholder="searchPlaceholder"
+ clearable
+ />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="search">鏌ヨ</el-button>
+ <el-button @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+ <el-card>
+ <!-- 鏍囩椤� -->
+ <el-tabs
+ v-model="activeTab"
+ class="info-tabs"
+ @tab-click="handleTabClick"
+ >
+ <el-tab-pane
+ v-for="tab in tabs"
+ :key="tab.name"
+ :label="tab.label"
+ :name="tab.name"
+ />
+ </el-tabs>
+
+ <!-- 鎿嶄綔鎸夐挳鍖� -->
+ <el-row :gutter="24" class="table-toolbar">
+ <el-button :icon="Plus" type="primary" @click="handleAdd"
+ >鏂板缓</el-button
+ >
+ <el-button :icon="Delete" type="danger" @click="handleDelete"
+ >鍒犻櫎</el-button
+ >
+ <!-- <el-button
+ v-show="canExport"
+ :icon="Download"
+ type="info"
+ @click="handleExport"
+ >瀵煎嚭</el-button
+ > -->
+ </el-row>
+ <!-- 琛ㄦ牸缁勪欢 -->
+ <div>
+ <data-table
+ :border="true"
+ :columns="columns"
+ :loading="loading"
+ style="width: 100%; height: calc(100vh - 29em)"
+ :show-selection="true"
+ :table-data="tableData"
+ @edit="handleEdit"
+ @viewRow="handleView"
+ @selection-change="handleSelectionChange"
+ :operations="['edit', 'viewRow']"
+ :operationsWidth="200"
+ >
+ <!-- 瀛楁鍚嶇О鍒楃殑鑷畾涔夋彃妲� - 鏄剧ず涓烘爣绛� -->
+ <template
+ v-if="tabName === 'coalQualityMaintenance'"
+ #fieldIds="{ row }"
+ >
+ <template
+ v-if="
+ typeof row.fieldIds === 'string' && row.fieldIds.includes(',')
+ "
+ >
+ <el-tag
+ v-for="(field, index) in row.fieldIds.split(',')"
+ :key="index"
+ size="small"
+ style="margin-right: 4px; margin-bottom: 2px"
+ type="primary"
+ >
+ {{ getFieldDisplayName(field.trim()) }}
+ </el-tag>
+ </template>
+ <template v-else>
+ <el-tag size="small" type="primary">
+ {{ getFieldDisplayName(row.fieldIds) || "--" }}
+ </el-tag>
+ </template>
+ </template>
+ </data-table>
+ </div>
+ <pagination
+ v-if="total > 0"
+ :layout="'total, prev, pager, next, jumper'"
+ :limit="pageSizes"
+ :page="pageNum"
+ :total="total"
+ @pagination="handPagination"
+ />
+ <managementDialog
+
+ ></managementDialog>
+ </el-card>
+ </div>
+</template>
+
+<script setup>
+import {
+ computed,
+ getCurrentInstance,
+ onMounted,
+ reactive,
+ ref,
+ nextTick,
+} from "vue";
+import { ElMessage, ElMessageBox } from "element-plus";
+import { Delete, Download, Plus } from "@element-plus/icons-vue";
+
+// ===== 缁勪欢瀵煎叆 =====
+import DataTable from "@/components/Table/ETable.vue";
+import Pagination from "@/components/Pagination";
+import managementDialog from "./mould/managementDialog.vue";
+// ===== API 鏈嶅姟瀵煎叆 =====
+import { delSupply, getSupply } from "@/api/basicInformation/supplier.js";
+import { useDelete } from "@/hooks/useDelete.js";
+import { testUserList } from "@/api/tool/publicInterface.js";
+const { proxy } = getCurrentInstance();
+
+// ===== 鍝嶅簲寮忕姸鎬佺鐞� =====
+const dialogFormVisible = ref(false);
+const form = ref({});
+const title = ref("");
+const copyForm = ref({});
+const addOrEdit = ref("add");
+
+// 鏁版嵁缂撳瓨鏄犲皠
+const userList = ref([]);
+const userMap = ref({}); // 鐢ㄦ埛ID -> 鐢ㄦ埛鍚嶆槧灏勮〃
+const addressMap = ref({}); // 鍦板潃ID -> 鍦板潃淇℃伅鏄犲皠琛�
+const coalFieldList = ref([]); // 鐓よ川瀛楁鍒楄〃
+
+// 椤甸潰鐘舵�佹帶鍒�
+const tabName = ref("management");
+const loading = ref(false);
+const activeTab = ref("management");
+
+// 鍒嗛〉鐘舵�佺鐞�
+const pageNum = ref(1);
+const pageSizes = ref(10);
+const total = ref(0);
+
+// 琛ㄦ牸鐘舵�佺鐞�
+const selectedRows = ref([]);
+const tableData = ref([]);
+const columns = ref();
+
+// 鏌ヨ鍙傛暟
+const queryParams = reactive({});
+
+// 鍦板潃閫夋嫨鏁版嵁
+const addressSelectOptions = ref([]);
+
+// ===== 閰嶇疆甯搁噺 =====
+
+// 鏍囩椤甸厤缃�
+const tabs = reactive([
+ { name: "management", label: "渚涘簲鍟嗕俊鎭�" },
+ { name: "customer", label: "瀹㈡埛淇℃伅" },
+]);
+
+// ===== 宸ュ叿鍑芥暟 =====
+
+
+/**
+ * 鏋勫缓鍦板潃鏄犲皠琛�
+ * @param {Array} areaData - 鍦板潃鏁版嵁
+ * @description 閫掑綊鏋勫缓鍦板潃鏄犲皠琛紝鏀寔澶氱骇鍦板潃鏌ユ壘
+ */
+const buildAddressMap = (areaData) => {
+ const buildMap = (list, pathList = []) => {
+ list.forEach((item) => {
+ const currentPath = [...pathList, item.label];
+ addressMap.value[item.id] = {
+ name: item.label,
+ fullPath: currentPath.join(" / "),
+ };
+ if (item.children && item.children.length > 0) {
+ buildMap(item.children, currentPath);
+ }
+ });
+ };
+ buildMap(areaData);
+};
+
+/**
+ * 鏍煎紡鍖栧湴鍧�鏁扮粍涓烘樉绀哄瓧绗︿覆
+ * @param {Array} addressIds - 鍦板潃ID鏁扮粍
+ * @returns {string} 鏍煎紡鍖栧悗鐨勫湴鍧�瀛楃涓�
+ * @description 灏嗗湴鍧�ID鏁扮粍杞崲涓哄彲璇荤殑鍦板潃瀛楃涓�
+ */
+const formatAddressArray = (addressIds) => {
+ if (
+ !addressMap.value ||
+ Object.keys(addressMap.value).length === 0 ||
+ !addressIds ||
+ !Array.isArray(addressIds) ||
+ addressIds.length === 0 ||
+ addressIds.every((id) => !id)
+ ) {
+ return "--";
+ }
+
+ const addressNames = addressIds.map(
+ (id) => addressMap.value[id]?.name || "--"
+ );
+
+ if (addressNames.every((name) => name === "--")) {
+ return "--";
+ }
+
+ return addressNames.filter((name) => name !== "--").join(" / ");
+};
+
+/**
+ * 鑾峰彇鐢ㄦ埛鍒楄〃鏁版嵁骞舵瀯寤烘槧灏勮〃
+ * @description 鑾峰彇鐢ㄦ埛鏁版嵁骞舵瀯寤篒D鍒扮敤鎴峰悕鐨勬槧灏勫叧绯�
+ */
+const getUserList = async () => {
+ try {
+ const res = await testUserList();
+ console.log("鑾峰彇鐢ㄦ埛鍒楄〃鏁版嵁:", res);
+ console.log("userMap:", userMap.value);
+ if (res && res.data) {
+ userList.value = res.data;
+ userList.value.forEach((user) => {
+ userMap.value[user.userId] = user.nickName;
+ });
+ }
+ } catch (error) {
+ console.error("鑾峰彇鐢ㄦ埛鍒楄〃澶辫触:", error);
+ }
+};
+
+/**
+ * 鏍规嵁瀛楁ID鑾峰彇瀛楁鏄剧ず鍚嶇О
+ * @param {string|number} fieldId - 瀛楁ID
+ * @returns {string} 瀛楁鏄剧ず鍚嶇О
+ * @description 閫氳繃瀛楁ID鍖归厤瀵瑰簲鐨勫瓧娈靛悕绉�
+ */
+const getFieldDisplayName = (fieldId) => {
+ if (!fieldId) return "--";
+
+ const numId = parseInt(fieldId);
+ const matchedField = coalFieldList.value.find((item) => item.id === numId);
+
+ return matchedField ? matchedField.fieldName : numId;
+};
+
+/**
+ * 褰撳墠鏍囩椤垫槸鍚︽敮鎸佸鍑哄姛鑳�
+ */
+const canExport = computed(() => {
+ return ["management"].includes(tabName.value);
+});
+
+/**
+ * 鎼滅储妗嗗崰浣嶇鏂囨湰
+ */
+const searchPlaceholder = computed(() => {
+ const placeholderMap = {
+ management: "渚涘簲鍟�/缁熶竴璇嗗埆鐮�/璇︾粏鍦板潃",
+ };
+ return placeholderMap[tabName.value] || "璇疯緭鍏ユ悳绱俊鎭�";
+});
+
+/**
+ * 鏄惁鏄剧ず鎼滅储妗�
+ */
+const shouldShowSearch = computed(() => {
+ return [
+ "management",
+ ].includes(tabName.value);
+});
+
+/**
+ * 褰撳墠閫変腑琛屾暟閲�
+ */
+const selectedCount = computed(() => selectedRows.value.length);
+
+// ===== 琛ㄦ牸鍒楅厤缃� =====
+
+/**
+ * 渚涘簲鍟嗚〃鏍煎垪閰嶇疆
+ */
+const management = ref([
+ { prop: "equipmentId", label: "璁惧缂栧彿", minWidth: 100 },
+ { prop: "equipmentName", label: "璁惧鍚嶇О", minWidth: 100 },
+ { prop: "quantity", label: "鏁伴噺", minWidth: 100 },
+ { prop: "specification", label: "瑙勬牸鍨嬪彿", minWidth: 100 },
+ { prop: "usageStatus", label: "浣跨敤鐘舵��", minWidth: 100 },
+ { prop: "usingDepartment", label: "浣跨敤閮ㄩ棬", minWidth: 100 },
+ { prop: "userId", label: "浣跨敤浜�", minWidth: 100 },
+ { prop: "purchaseDate", label: "閲囪喘鏃ユ湡", minWidth: 100 },
+ { prop: "purchasePrice", label: "閲囪喘浠锋牸", minWidth: 100 },
+]);
+
+
+// ===== 浜嬩欢澶勭悊鍑芥暟 =====
+
+/**
+ * 鏍囩椤靛垏鎹簨浠跺鐞�
+ * @param {Object} tab - 鏍囩椤靛璞�
+ * @description 澶勭悊鏍囩椤靛垏鎹紝閲嶇疆琛ㄥ崟鍜岀姸鎬侊紝鍔犺浇瀵瑰簲鏁版嵁
+ */
+const handleTabClick = (tab) => {
+ // 閲嶇疆琛ㄥ崟鍜岀姸鎬�
+ form.value = {};
+ addOrEdit.value = "add";
+ loading.value = true;
+ tabName.value = tab.props.name;
+ tableData.value = [];
+ pageNum.value = 1;
+ pageSizes.value = 10;
+ total.value = 0;
+ queryParams.searchAll = "";
+ // 鏍规嵁鏍囩椤电被鍨嬭缃搴旂殑鍒楅厤缃�
+ const tabConfig = {
+ management: () => {
+ columns.value = management.value;
+ getList();
+ },
+ };
+
+ // 鎵ц瀵瑰簲鐨勯厤缃嚱鏁�
+ const configFn = tabConfig[tabName.value];
+ if (configFn) {
+ configFn();
+ }
+};
+
+/**
+ * 閲嶇疆鏌ヨ鏉′欢
+ * @description 閲嶇疆鏌ヨ鍙傛暟骞堕噸鏂板姞杞芥暟鎹�
+ */
+const resetQuery = () => {
+ Object.keys(queryParams).forEach((key) => {
+ if (key !== "pageNum" && key !== "pageSizes") {
+ queryParams[key] = "";
+ }
+ });
+ getList();
+};
+
+/**
+ * 鎼滅储鍔熻兘
+ * @description 閲嶇疆椤电爜骞舵墽琛屾悳绱�
+ */
+const search = () => {
+ pageNum.value = 1;
+ getList();
+};
+
+/**
+ * 鏂板鎸夐挳鐐瑰嚮澶勭悊
+ */
+const handleAdd = () => {
+ addOrEdit.value = "add";
+ handleAddEdit(tabName.value);
+};
+
+/**
+ * 鏂板/缂栬緫寮圭獥澶勭悊
+ * @param {string} currentTabName - 褰撳墠鏍囩椤靛悕绉�
+ * @description 鏍规嵁鏍囩椤电被鍨嬭缃脊绐楁爣棰樺苟鎵撳紑寮圭獥
+ */
+const handleAddEdit = (currentTabName) => {
+ const actionText =
+ addOrEdit.value === "add"
+ ? "鏂板"
+ : addOrEdit.value === "edit"
+ ? "缂栬緫"
+ : "鏌ョ湅";
+
+ const tabTitleMap = {
+ supplier: "渚涘簲鍟嗕俊鎭�",
+ customer: "瀹㈡埛淇℃伅",
+ };
+
+ title.value = `${actionText}${tabTitleMap[currentTabName] || ""}`;
+ openDialog();
+};
+
+/**
+ * 鎵撳紑寮圭獥
+ * @description 鏍规嵁缂栬緫鐘舵�佸喅瀹氭槸鍚﹀鍒惰〃鍗曟暟鎹�
+ */
+const openDialog = () => {
+ if (addOrEdit.value === "edit" || addOrEdit.value === "viewRow") {
+ copyForm.value = JSON.parse(JSON.stringify(form.value));
+ } else {
+ form.value = {};
+ }
+ dialogFormVisible.value = true;
+};
+
+/**
+ * 鍒嗛〉澶勭悊
+ * @param {Object} val - 鍒嗛〉鍙傛暟瀵硅薄
+ */
+const handPagination = (val) => {
+ pageNum.value = val.page;
+ pageSizes.value = val.limit;
+ getList();
+};
+
+/**
+ * 琛ㄥ崟鎻愪氦澶勭悊
+ * @param {Object} val - 鎻愪氦缁撴灉瀵硅薄
+ */
+const handleSubmit = async (val) => {
+ if (val.result.code !== 200) {
+ ElMessage.error("鎿嶄綔澶辫触锛�" + val.result.msg);
+ return;
+ }
+ ElMessage.success(val.title + val.result.msg);
+ dialogFormVisible.value = false;
+ getList();
+};
+
+/**
+ * 寮圭獥鏄剧ず鐘舵�佸鐞�
+ * @param {boolean} value - 鏄剧ず鐘舵��
+ */
+const handleDialogFormVisible = (value) => {
+ dialogFormVisible.value = value;
+};
+
+/**
+ * 琛ㄦ牸琛岄�夋嫨澶勭悊
+ * @param {Array} selection - 閫変腑鐨勮鏁版嵁
+ */
+const handleSelectionChange = (selection) => {
+ selectedRows.value = selection;
+};
+/**
+ * 缂栬緫鎸夐挳鐐瑰嚮澶勭悊
+ * @param {Object} row - 琛屾暟鎹�
+ * @description 澶勭悊缂栬緫鎿嶄綔锛屾瀯寤哄湴鍧�鏁扮粍骞舵墦寮�缂栬緫寮圭獥
+ */
+const handleEdit = (row) => {
+ form.value = JSON.parse(JSON.stringify(row));
+
+ // 鏋勫缓渚涘簲鍟嗕笟鍔″湴鍧�鏁扮粍
+ if (form.value.bprovinceId && form.value.bdistrictId && form.value.bcityId) {
+ form.value.bids = [row.bprovinceId, row.bcityId, row.bdistrictId];
+ }
+
+ // 鏋勫缓渚涘簲鍟嗚仈绯诲湴鍧�鏁扮粍
+ if (form.value.cprovinceId && form.value.cdistrictId && form.value.ccityId) {
+ form.value.cids = [row.cprovinceId, row.ccityId, row.cdistrictId];
+ }
+
+ // 鏋勫缓瀹㈡埛涓氬姟鍦板潃鏁扮粍
+ if (
+ form.value.businessCityId &&
+ form.value.businessDistrictId &&
+ form.value.businessProvinceId
+ ) {
+ form.value.bids = [
+ row.businessProvinceId,
+ row.businessCityId,
+ row.businessDistrictId,
+ ];
+ }
+
+ // 鏋勫缓瀹㈡埛鑱旂郴鍦板潃鏁扮粍
+ if (form.value.cityId && form.value.districtId && form.value.provinceId) {
+ form.value.cids = [row.provinceId, row.cityId, row.districtId];
+ }
+
+ addOrEdit.value = "edit";
+ handleAddEdit(tabName.value);
+};
+
+
+/**
+ * 鎵归噺鍒犻櫎澶勭悊
+ * @description 鎵归噺鍒犻櫎閫変腑鐨勮褰�
+ */
+ const deleteApiMap = {
+ management: delSupply,
+ };
+const {handleDeleteBatch :handleDelete} = useDelete({
+ deleteApi: () => deleteApiMap[tabName.value],
+ selectedRows: selectedRows,
+ getList: () => getList,
+ tableData: tableData,
+ total: total,
+ confirmText: "纭鍒犻櫎閫変腑鐨勬暟鎹悧锛�",
+ successText: "鍒犻櫎鎴愬姛",
+})
+
+/**
+ * 鍏抽棴寮圭獥澶勭悊
+ */
+const handleBeforeClose = () => {
+ dialogFormVisible.value = false;
+ form.value = {};
+};
+
+/**
+ * 瀵煎嚭鏁版嵁
+ * @param {string} api - 瀵煎嚭鎺ュ彛璺緞
+ * @param {string} name - 瀵煎嚭鏂囦欢鍚嶅墠缂�
+ */
+const exportData = (api, name) => {
+ proxy.download(
+ api,
+ { ...queryParams },
+ `${name}${new Date().getTime()}.xlsx`
+ );
+ ElMessage.success("瀵煎嚭鏁版嵁锛�" + name);
+};
+// ===== 鏁版嵁鑾峰彇鍑芥暟 =====
+
+/**
+ * 鏍规嵁褰撳墠鏍囩椤甸�夋嫨瀵瑰簲鐨凙PI鎺ュ彛
+ * @returns {Promise} API璋冪敤Promise
+ * @description 缁熶竴鐨勬帴鍙i�夋嫨鍑芥暟锛屾牴鎹爣绛鹃〉绫诲瀷璋冪敤瀵瑰簲鐨凙PI
+ */
+const selectInterface = () => {
+ const apiParams = {
+ current: pageNum.value,
+ pageSize: pageSizes.value,
+ searchAll: queryParams.searchAll,
+ };
+
+ const apiMap = {
+ management: () => getSupply(apiParams),
+ customer: () => getCustomerList(apiParams),
+ coal: () => getCoalInfo(apiParams),
+ coalQualityMaintenance: () => getCoalPlanList(apiParams),
+ coalMeiZhiZiDuanWeiHu: () => coalField(apiParams),
+ };
+
+ const apiFunction = apiMap[tabName.value];
+ return apiFunction
+ ? apiFunction()
+ : Promise.reject(new Error("鏈壘鍒板搴旂殑API鎺ュ彛"));
+};
+
+/**
+ * 鑾峰彇鍒楄〃鏁版嵁
+ * @description 缁熶竴鐨勬暟鎹幏鍙栧嚱鏁帮紝澶勭悊鍔犺浇鐘舵�佸拰閿欒澶勭悊
+ */
+const getList = async () => {
+ try {
+ loading.value = true;
+ const { data, code } = await selectInterface();
+
+ if (code !== 200) {
+ ElMessage.error("鑾峰彇鏁版嵁澶辫触锛�" + (data?.msg || "鏈煡閿欒"));
+ return;
+ }
+
+ tableData.value = data.records || [];
+ total.value = data.total || 0;
+ } catch (error) {
+ console.error("鑾峰彇鍒楄〃鏁版嵁澶辫触:", error);
+ ElMessage.error("鑾峰彇鏁版嵁澶辫触锛岃绋嶅悗鍐嶈瘯");
+ } finally {
+ loading.value = false;
+ }
+};
+
+const handleView = (row) => {
+ form.value = JSON.parse(JSON.stringify(row));
+ // 鏋勫缓渚涘簲鍟嗕笟鍔″湴鍧�鏁扮粍
+ if (form.value.bprovinceId && form.value.bdistrictId && form.value.bcityId) {
+ form.value.bids = [row.bprovinceId, row.bcityId, row.bdistrictId];
+ }
+
+ // 鏋勫缓渚涘簲鍟嗚仈绯诲湴鍧�鏁扮粍
+ if (form.value.cprovinceId && form.value.cdistrictId && form.value.ccityId) {
+ form.value.cids = [row.cprovinceId, row.ccityId, row.cdistrictId];
+ }
+
+ // 鏋勫缓瀹㈡埛涓氬姟鍦板潃鏁扮粍
+ if (
+ form.value.businessCityId &&
+ form.value.businessDistrictId &&
+ form.value.businessProvinceId
+ ) {
+ form.value.bids = [
+ row.businessProvinceId,
+ row.businessCityId,
+ row.businessDistrictId,
+ ];
+ }
+
+ // 鏋勫缓瀹㈡埛鑱旂郴鍦板潃鏁扮粍
+ if (form.value.cityId && form.value.districtId && form.value.provinceId) {
+ form.value.cids = [row.provinceId, row.cityId, row.districtId];
+ }
+ addOrEdit.value = "viewRow";
+ handleAddEdit(tabName.value);
+};
+
+
+// ===== 鐢熷懡鍛ㄦ湡閽╁瓙 =====
+
+/**
+ * 缁勪欢鎸傝浇鍚庣殑鍒濆鍖栨搷浣�
+ */
+onMounted(async () => {
+ try {
+ // 骞惰鎵ц鍒濆鍖栨搷浣�
+ await Promise.all([
+ handleTabClick({ props: { name: "management" } }),
+ getUserList(),
+ ]);
+ } catch (error) {
+ console.error("缁勪欢鍒濆鍖栧け璐�:", error);
+ ElMessage.error("椤甸潰鍒濆鍖栧け璐ワ紝璇峰埛鏂伴噸璇�");
+ }
+});
+</script>
+
+<style scoped>
+/* 鍝嶅簲寮忓竷灞� */
+@media screen and (min-width: 768px) {
+ .search-form :deep(.el-form-item) {
+ width: 50%;
+ }
+}
+
+@media screen and (min-width: 1200px) {
+ .search-form :deep(.el-form-item) {
+ width: 16%;
+ }
+}
+
+.table-toolbar {
+ margin-bottom: 20px;
+ display: flex;
+ flex-wrap: wrap;
+ gap: 10px;
+}
+
+/* 鍝嶅簲寮忚〃鏍� */
+@media screen and (max-width: 768px) {
+ .table-toolbar {
+ flex-direction: column;
+ }
+
+ .table-toolbar .el-button {
+ width: 100%;
+ }
+}
+
+/* 琛ㄦ牸宸ュ叿鏍� */
+.table-toolbar,
+.table-toolbar > * {
+ margin: 0 0 0 0 !important;
+}
+
+.table-toolbar {
+ margin-bottom: 20px !important;
+}
+
+.el-form--inline .el-form-item {
+ margin-right: 25px;
+}
+
+.main-container {
+ background: red !important;
+}
+</style>
diff --git a/src/views/equipment/management/mould/managementDialog.vue b/src/views/equipment/management/mould/managementDialog.vue
new file mode 100644
index 0000000..f245902
--- /dev/null
+++ b/src/views/equipment/management/mould/managementDialog.vue
@@ -0,0 +1,290 @@
+<template>
+ <div>
+ <el-dialog
+ v-model="dialogVisible"
+ :title="title"
+ width="600"
+ :close-on-click-modal="false"
+ :before-close="handleClose"
+ >
+ <el-form
+ ref="formRef"
+ style="max-width: 400px; margin: 0 auto"
+ :model="formData"
+ :rules="rules"
+ label-width="auto"
+ > <el-form-item
+ label="渚涘簲鍟嗗悕绉�"
+ prop="supplierName"
+ >
+ <el-input
+ v-model="formData.supplierName"
+ placeholder="璇疯緭鍏ヤ緵璐у晢鍚嶇О"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="绾崇◣浜鸿瘑鍒彿"
+ prop="taxpayerId"
+ >
+ <el-input
+ v-model="formData.taxpayerId"
+ placeholder="璇疯緭鍏ョ撼绋庝汉璇嗗埆鍙�"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="缁忚惀鍦板潃"
+ prop="bids"
+ >
+ <el-cascader
+ placeholder="璇烽�夋嫨缁忚惀鍦板潃"
+ size="default"
+ :options="addressSelectOptions"
+ v-model="formData.bids"
+ :props="cascaderProps"
+ @change="handleChange"
+ :disabled="isViewMode"
+ >
+ </el-cascader>
+ </el-form-item>
+ <el-form-item
+ label="璇︾粏鍦板潃"
+ prop="businessAddress"
+ >
+ <el-input
+ v-model="formData.businessAddress"
+ placeholder="璇疯緭鍏ュ鎴疯缁嗗湴鍧�"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="寮�鎴疯"
+ prop="bankAccount"
+ >
+ <el-input
+ v-model="formData.bankAccount"
+ placeholder="璇疯緭鍏ュ紑鎴疯"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="閾惰璐︽埛"
+ prop="bankName"
+ >
+ <el-input
+ v-model="formData.bankName"
+ placeholder="璇疯緭鍏ラ摱琛岃处鎴�"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="鑱旂郴浜�"
+ prop="contactPerson"
+ >
+ <el-input
+ v-model="formData.contactPerson"
+ placeholder="璇疯緭鍏ヨ仈绯讳汉"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="鑱旂郴浜虹數璇�"
+ prop="contactPhone"
+ >
+ <el-input
+ v-model="formData.contactPhone"
+ placeholder="璇疯緭鍏ヨ仈绯讳汉鐢佃瘽"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item
+ label="鑱旂郴浜哄湴鍧�"
+ prop="cids"
+ >
+ <el-cascader
+ placeholder="璇烽�夋嫨鑱旂郴浜哄湴鍧�"
+ size="default"
+ :options="addressSelectOptions"
+ v-model="formData.cids"
+ :props="cascaderProps"
+ @change="handleChange"
+ :disabled="isViewMode"
+ >
+ </el-cascader>
+ </el-form-item>
+ <el-form-item
+ label="鑱旂郴浜鸿缁嗗湴鍧�"
+ prop="contactAddress"
+ >
+ <el-input
+ v-model="formData.contactAddress"
+ placeholder="璇疯緭鍏ヨ仈绯讳汉鍦板潃"
+ :disabled="isViewMode"
+ />
+ </el-form-item>
+ <el-form-item class="dialog-footer">
+ <el-button v-if="addOrEdit === 'edit'" @click="resetForm"
+ >閲嶇疆</el-button
+ >
+ <el-button v-if="addOrEdit !== 'edit'||addOrEdit.includes('viewRow')" @click="cancelForm"
+ >鍙栨秷</el-button
+ >
+ <el-button type="primary" @click="submitForm" v-if="!isViewMode"> 纭畾</el-button>
+ </el-form-item>
+ </el-form>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup>
+import { ref, watch, defineProps, onMounted, computed, reactive } from "vue";
+import { addOrEditSupply } from "@/api/basicInformation/supplier";
+import { getAreaOptions } from "@/api/system/area.js";
+
+const props = defineProps({
+ beforeClose: {
+ type: Function,
+ default: () => {},
+ },
+ form: {
+ type: Object,
+ default: () => ({}),
+ },
+ addOrEdit: {
+ type: String,
+ default: "add",
+ },
+ title: {
+ type: String,
+ default: "",
+ },
+});
+
+// 璁$畻灞炴�э細缁熶竴鎺у埗鏄惁绂佺敤
+const isViewMode = computed(() => props.addOrEdit === 'viewRow');
+
+const emit = defineEmits(["submit", "handleBeforeClose"]);
+const copyForm = defineModel("copyForm", {
+ required: true,
+ type: Object,
+});
+onMounted(() => {
+ fetchAreaOptions();
+});
+
+// 淇敼鏍戝舰閫夋嫨鐨勬槧灏�
+const cascaderProps = ref({
+ value: "id", // 鎸囧畾value瀛楁涓篿d
+ label: "label", // 鎸囧畾label瀛楁
+ children: "children", // 鎸囧畾瀛愯妭鐐瑰瓧娈�
+});
+
+// 鍦板潃閫夋嫨鏁版嵁
+const addressSelectOptions = ref([]);
+const fetchAreaOptions = async () => {
+ addressSelectOptions.value = [];
+
+ const res = await getAreaOptions();
+ if (res.code === 200) {
+ addressSelectOptions.value = res.data;
+ }
+};
+
+// 澶勭悊鍦板潃鏁版嵁杞崲
+function mapAddress(list) {
+ return list.map((item) => ({
+ value: item.id,
+ label: item.name,
+ children: item.children ? mapAddress(item.children) : undefined,
+ }));
+}
+
+// 琛ㄥ崟寮曠敤
+const formRef = ref(null);
+// 琛ㄥ崟鏁版嵁
+const formData = ref({ ...props.form });
+// 寮圭獥鍙鎬�
+const dialogVisible = defineModel("supplierDialogFormVisible", {
+ required: true,
+ type: Boolean,
+});
+// 鐩戝惉澶栭儴浼犲叆鐨勮〃鍗曟暟鎹彉鍖�
+watch(
+ () => props.form,
+ (newVal) => {
+ formData.value = { ...newVal };
+ },
+ { deep: true }
+);
+
+// 鐩戝惉鍐呴儴寮圭獥鐘舵�佸彉鍖�
+watch(
+ () => dialogVisible.value,
+ (newVal) => {
+ emit("update:supplierDialogFormVisible", newVal);
+ }
+);
+// 澶勭悊鍦板潃閫夋嫨鍙樺寲
+const handleChange = (value) => {
+ console.log(value);
+};
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+ if (!formRef.value) return;
+ await formRef.value.validate(async (valid, fields) => {
+ if (valid) {
+ const obj = ref({});
+ if (props.title.includes("鏂板")) {
+ let result = await addOrEditSupply({
+ ...formData.value,
+ });
+ obj.value = {
+ title: "鏂板",
+ ...formData.value,
+ result,
+ };
+ } else {
+ let result = await addOrEditSupply({
+ ...formData.value,
+ });
+ obj.value = {
+ title: "缂栬緫",
+ ...formData.value,
+ result,
+ };
+ }
+ emit("submit", obj.value);
+ }
+ });
+};
+// 鍙栨秷琛ㄥ崟
+const cancelForm = () => {
+ emit("update:supplierDialogFormVisible", false);
+ formData.value = {};
+};
+// 閲嶇疆琛ㄥ崟
+const resetForm = () => {
+ if (!formRef.value) return;
+ formData.value = JSON.parse(JSON.stringify(copyForm.value));
+};
+// 鍏抽棴寮圭獥
+const handleClose = () => {
+ // 瑙﹀彂鐖剁粍浠剁殑鍏抽棴鍑芥暟
+ emit("handleBeforeClose");
+ emit("update:supplierDialogFormVisible", false);
+};
+const rules = reactive({
+ supplierName: [
+ { required: true, message: "璇疯緭鍏ヤ緵璐у晢鍚嶇О", trigger: "blur" },
+ ],
+});
+</script>
+<style lang="scss" scoped>
+.dialog-footer {
+ display: flex;
+ justify-content: flex-end;
+ margin-top: 20px;
+ flex-direction: column;
+}
+</style>
--
Gitblit v1.9.3