Merge remote-tracking branch 'origin/dev' into dev
¶Ô±ÈÐÂÎļþ |
| | |
| | | // 设å¤ç®¡ç |
| | | 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 |
| | | }) |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| | |
| | | */ |
| | | import { ref, reactive, computed, nextTick } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { clone } from "lodash"; |
| | | import { deepClone } from "@/utils/index.js" |
| | | |
| | | |
| | | /** |
| | | * åå»ºè¡¨åæ°æ®ç®¡çåè½ |
| | |
| | | } |
| | | |
| | | // ååå
¼å®¹çé»è®¤å¯¼åº |
| | | 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)); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | }; |
| | | } |
| | |
| | | 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 æ¥å£ |
| | |
| | | ) { |
| | | 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); |
| | |
| | | // å¦æè¿æ¬¡å䏿¬¡ç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; |
| | |
| | | loading.value = false; |
| | | } else { |
| | | loading.value = false; |
| | | // message(data.msg, { type: "error" }); |
| | | ElMessage({ message: msg, type: "error" }); |
| | | } |
| | | }); |
| | | } |
| | |
| | | } |
| | | |
| | | watchEffect(() => { |
| | | pagination.align = paginationAlign.value; |
| | | pagination.align = paginationAlign.value |
| | | }); |
| | | |
| | | // onMounted(() => { |
| | |
| | | return /^[+-]?(0|([1-9]\d*))(\.\d+)?$/g.test(str) |
| | | } |
| | | |
| | | export function isEqual(obj1, obj2) { |
| | | return JSON.stringify(obj1) === JSON.stringify(obj2); |
| | | } |
| | |
| | | </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" |
| | |
| | | :table-data="tableData" |
| | | @edit="handleEdit" |
| | | @selection-change="handleSelectionChange" |
| | | style="height: calc(65vh);" |
| | | > |
| | | </ETable> |
| | | <Pagination |
| | |
| | | treeId: queryParams.treeId, |
| | | current: queryParams.current, |
| | | size: queryParams.pageSize, |
| | | searchAll: queryParams.searchAll, |
| | | }); |
| | | |
| | | if (res.code !== 200) { |
| | |
| | | }; |
| | | |
| | | // ===== çå½å¨æ ===== |
| | | onMounted(getList); |
| | | onMounted(()=>{ |
| | | getList(); |
| | | getArchiveListData(); |
| | | }); |
| | | </script> |
| | | <style lang="scss" scoped> |
| | | .custom-tree-node { |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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 è·åç¨æ·æ°æ®å¹¶æå»ºIDå°ç¨æ·åçæ å°å
³ç³» |
| | | */ |
| | | 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); |
| | | }; |
| | | // ===== æ°æ®è·å彿° ===== |
| | | |
| | | /** |
| | | * æ ¹æ®å½åæ ç¾é¡µéæ©å¯¹åºçAPIæ¥å£ |
| | | * @returns {Promise} APIè°ç¨Promise |
| | | * @description ç»ä¸çæ¥å£éæ©å½æ°ï¼æ ¹æ®æ ç¾é¡µç±»åè°ç¨å¯¹åºçAPI |
| | | */ |
| | | 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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åæ®µä¸ºid |
| | | 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> |