fix: 不在销售台账处出库。在发货台账处导入excel,匹配客户进行出库。销售台账处的产品列表需要展示已发货/未发货数量。
| | |
| | | data: query, |
| | | }); |
| | | } |
| | | |
| | | // å
¼å®¹æ§é¡µé¢ï¼éå®å°è´¦ï¼åè´§æ¥å£ |
| | | export function addShippingInfo(data) { |
| | | return request({ |
| | | url: "/shippingInfo/add", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | |
| | | style="width: 240px" |
| | | clearable |
| | | @change="handleQuery"> |
| | | <el-option label="é¶å®å®¢æ·" |
| | | value="é¶å®å®¢æ·" /> |
| | | <el-option label="è¿éå客æ·" |
| | | value="è¿éå客æ·" /> |
| | | <el-option label="对å
¬" |
| | | value="1" /> |
| | | <el-option label="对ç§" |
| | | value="2" /> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | |
| | | <el-select v-model="form.customerType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="é¶å®å®¢æ·" |
| | | value="é¶å®å®¢æ·" /> |
| | | <el-option label="è¿éå客æ·" |
| | | value="è¿éå客æ·" /> |
| | | <el-option label="对å
¬" |
| | | :value="1" /> |
| | | <el-option label="对ç§" |
| | | :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitReminderForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitReminderForm">确认</el-button> |
| | | <el-button @click="closeReminderDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitNegotiationForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitNegotiationForm">确认</el-button> |
| | | <el-button @click="closeNegotiationDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | <el-col :span="12"> |
| | | <div class="info-item"> |
| | | <span class="info-label">客æ·åç±»ï¼</span> |
| | | <span class="info-value">{{ detailForm.customerType }}</span> |
| | | <span class="info-value">{{ detailForm.customerType==1?"对å
¬":"对ç§" }}</span> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | label: "客æ·åç±»", |
| | | prop: "customerType", |
| | | width: 120, |
| | | formatData: params => { |
| | | return params == 1 ? "对å
¬" : "对ç§"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ·»å æ´½è°è¿åº¦", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openNegotiationDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ·»å æ´½è°è¿åº¦", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openNegotiationDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "å访æé", |
| | | type: "text", |
| | |
| | | openReminderDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "详æ
", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openDetailDialog(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "详æ
", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openDetailDialog(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | |
| | | }, |
| | | rules: { |
| | | customerName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxpayerIdentificationNumber: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | companyAddress: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | companyPhone: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // taxpayerIdentificationNumber: [ |
| | | // { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | // ], |
| | | // companyAddress: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // companyPhone: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // contactPerson: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // contactPhone: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | maintainer: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | maintenanceTime: [ |
| | | { required: false, message: "è¯·éæ©", trigger: "change" }, |
| | | ], |
| | | basicBankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankCode: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // basicBankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // bankAccount: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // bankCode: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | customerType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }, |
| | | }); |
| | |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">ä¾åºåæ¡£æ¡ï¼</span> |
| | | <el-input |
| | | v-model="searchForm.supplierName" |
| | | style="width: 240px" |
| | | placeholder="è¾å
¥ä¾åºååç§°æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | /> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-input v-model="searchForm.supplierName" |
| | | style="width: 240px" |
| | | placeholder="è¾å
¥ä¾åºååç§°æç´¢" |
| | | @change="handleQuery" |
| | | clearable |
| | | :prefix-icon="Search" /> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')" |
| | | >æ°å¢ä¾åºå</el-button |
| | | > |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢ä¾åºå</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="info" plain icon="Upload" @click="handleImport" |
| | | >导å
¥</el-button |
| | | > |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button type="info" |
| | | plain |
| | | icon="Upload" |
| | | @click="handleImport">导å
¥</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination"></PIMTable> |
| | | </div> |
| | | <el-dialog |
| | | v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢ä¾åºåä¿¡æ¯' : 'ç¼è¾ä¾åºåä¿¡æ¯'" |
| | | width="70%" |
| | | @close="closeDia" |
| | | > |
| | | <el-form |
| | | :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef" |
| | | > |
| | | <el-dialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢ä¾åºåä¿¡æ¯' : 'ç¼è¾ä¾åºåä¿¡æ¯'" |
| | | width="70%" |
| | | @close="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="rules" |
| | | ref="formRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºååç§°ï¼" prop="supplierName"> |
| | | <el-input |
| | | v-model="form.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="ä¾åºååç§°ï¼" |
| | | prop="supplierName"> |
| | | <el-input v-model="form.supplierName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item |
| | | label="纳ç¨äººè¯å«å·ï¼" |
| | | prop="taxpayerIdentificationNum" |
| | | > |
| | | <el-input |
| | | v-model="form.taxpayerIdentificationNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="纳ç¨äººè¯å«å·ï¼" |
| | | prop="taxpayerIdentificationNum"> |
| | | <el-input v-model="form.taxpayerIdentificationNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬å¸å°åï¼" prop="companyAddress"> |
| | | <el-input |
| | | v-model="form.companyAddress" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="å
¬å¸å°åï¼" |
| | | prop="companyAddress"> |
| | | <el-input v-model="form.companyAddress" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å
¬å¸çµè¯ï¼" prop="companyPhone"> |
| | | <el-input |
| | | v-model="form.companyPhone" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="å
¬å¸çµè¯ï¼" |
| | | prop="companyPhone"> |
| | | <el-input v-model="form.companyPhone" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="弿·è¡ï¼" prop="bankAccountName"> |
| | | <el-input |
| | | v-model="form.bankAccountName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="弿·è¡ï¼" |
| | | prop="bankAccountName"> |
| | | <el-input v-model="form.bankAccountName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è´¦å·ï¼" prop="bankAccountNum"> |
| | | <el-input |
| | | v-model="form.bankAccountNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="è´¦å·ï¼" |
| | | prop="bankAccountNum"> |
| | | <el-input v-model="form.bankAccountNum" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è系人ï¼" prop="contactUserName"> |
| | | <el-input |
| | | v-model="form.contactUserName" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="è系人ï¼" |
| | | prop="contactUserName"> |
| | | <el-input v-model="form.contactUserName" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="èç³»çµè¯ï¼" prop="contactUserPhone"> |
| | | <el-input |
| | | v-model="form.contactUserPhone" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | /> |
| | | <el-form-item label="èç³»çµè¯ï¼" |
| | | prop="contactUserPhone"> |
| | | <el-input v-model="form.contactUserPhone" |
| | | placeholder="请è¾å
¥" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»´æ¤äººï¼" prop="maintainUserId"> |
| | | <el-select |
| | | v-model="form.maintainUserId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled |
| | | > |
| | | <el-option |
| | | v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.userId" |
| | | /> |
| | | <el-form-item label="ç»´æ¤äººï¼" |
| | | prop="maintainUserId"> |
| | | <el-select v-model="form.maintainUserId" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | disabled> |
| | | <el-option v-for="item in userList" |
| | | :key="item.nickName" |
| | | :label="item.nickName" |
| | | :value="item.userId" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç»´æ¤æ¶é´ï¼" prop="maintainTime"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.maintainTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | /> |
| | | <el-form-item label="ç»´æ¤æ¶é´ï¼" |
| | | prop="maintainTime"> |
| | | <el-date-picker style="width: 100%" |
| | | v-model="form.maintainTime" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¾åºåç±»åï¼" prop="supplierType"> |
| | | <el-select v-model="form.supplierType" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="ç²" value="ç²" /> |
| | | <el-option label="ä¹" value="ä¹" /> |
| | | <el-option label="ä¸" value="ä¸" /> |
| | | <el-option label="ä¸" value="ä¸" /> |
| | | <el-form-item label="ä¾åºåç±»åï¼" |
| | | prop="supplierType"> |
| | | <el-select v-model="form.supplierType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="对å
¬" |
| | | :value="1" /> |
| | | <el-option label="对ç§" |
| | | :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¯å¦ç½ååï¼" prop="isWhite"> |
| | | <el-select v-model="form.isWhite" placeholder="è¯·éæ©" clearable> |
| | | <el-option label="æ¯" :value="0" /> |
| | | <el-option label="å¦" :value="1" /> |
| | | <el-form-item label="æ¯å¦ç½ååï¼" |
| | | prop="isWhite"> |
| | | <el-select v-model="form.isWhite" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | | <el-option label="æ¯" |
| | | :value="0" /> |
| | | <el-option label="å¦" |
| | | :value="1" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="submitForm">确认</el-button> |
| | | <el-button @click="closeDia">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- ä¾åºå导å
¥å¯¹è¯æ¡ --> |
| | | <el-dialog |
| | | :title="upload.title" |
| | | v-model="upload.open" |
| | | 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" |
| | | :on-progress="handleFileUploadProgress" |
| | | :on-success="handleFileSuccess" |
| | | :on-error="handleFileError" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <el-dialog :title="upload.title" |
| | | v-model="upload.open" |
| | | 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" |
| | | :on-progress="handleFileUploadProgress" |
| | | :on-success="handleFileSuccess" |
| | | :on-error="handleFileError" |
| | | :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>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link |
| | | type="primary" |
| | | :underline="false" |
| | | style="font-size: 12px; vertical-align: baseline" |
| | | @click="importTemplate" |
| | | >ä¸è½½æ¨¡æ¿</el-link |
| | | > |
| | | <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 type="primary" |
| | | @click="submitFileForm">ç¡® å®</el-button> |
| | | <el-button @click="upload.open = false">å æ¶</el-button> |
| | | </div> |
| | | </template> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { onMounted, ref } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { delSupplier } from "@/api/basicData/supplierManageFile.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | addSupplier, |
| | | getSupplier, |
| | | listSupplier, |
| | | updateSupplier, |
| | | } from "@/api/basicData/supplierManageFile.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | import FilesDia from "../filesDia.vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | import { onMounted, ref } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { delSupplier } from "@/api/basicData/supplierManageFile.js"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | addSupplier, |
| | | getSupplier, |
| | | listSupplier, |
| | | updateSupplier, |
| | | } from "@/api/basicData/supplierManageFile.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { getToken } from "@/utils/auth.js"; |
| | | import FilesDia from "../filesDia.vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ä¾åºååç§°", |
| | | prop: "supplierName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "ä¾åºåç±»å", |
| | | prop: "supplierType", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "纳ç¨äººè¯å«å·", |
| | | prop: "taxpayerIdentificationNum", |
| | | width: 230, |
| | | }, |
| | | { |
| | | label: "å
¬å¸å°å", |
| | | prop: "companyAddress", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "èç³»æ¹å¼", |
| | | prop: "companyPhone", |
| | | width:150 |
| | | }, |
| | | { |
| | | label: "弿·è¡", |
| | | prop: "bankAccountName", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è´¦å·", |
| | | prop: "bankAccountNum", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è系人", |
| | | prop: "contactUserName", |
| | | }, |
| | | { |
| | | label: "èç³»çµè¯", |
| | | prop: "contactUserPhone", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ç»´æ¤äºº", |
| | | prop: "maintainUserName", |
| | | }, |
| | | |
| | | { |
| | | label: "ç»´æ¤æ¶é´", |
| | | prop: "maintainTime", |
| | | width:100 |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openForm("edit", row); |
| | | }, |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "ä¾åºååç§°", |
| | | prop: "supplierName", |
| | | width: 250, |
| | | }, |
| | | { |
| | | label: "ä¾åºåç±»å", |
| | | prop: "supplierType", |
| | | width: 120, |
| | | formatData: params => { |
| | | return params == 1 ? "对å
¬" : "对ç§"; |
| | | }, |
| | | { |
| | | //èµè´¨éä»¶ |
| | | name: "èµè´¨æä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row) |
| | | }, |
| | | { |
| | | label: "纳ç¨äººè¯å«å·", |
| | | prop: "taxpayerIdentificationNum", |
| | | width: 230, |
| | | }, |
| | | { |
| | | label: "å
¬å¸å°å", |
| | | prop: "companyAddress", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "èç³»æ¹å¼", |
| | | prop: "companyPhone", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "弿·è¡", |
| | | prop: "bankAccountName", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è´¦å·", |
| | | prop: "bankAccountNum", |
| | | width: 220, |
| | | }, |
| | | { |
| | | label: "è系人", |
| | | prop: "contactUserName", |
| | | }, |
| | | { |
| | | label: "èç³»çµè¯", |
| | | prop: "contactUserPhone", |
| | | width: 150, |
| | | }, |
| | | { |
| | | label: "ç»´æ¤äºº", |
| | | prop: "maintainUserName", |
| | | }, |
| | | |
| | | { |
| | | label: "ç»´æ¤æ¶é´", |
| | | prop: "maintainTime", |
| | | width: 100, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openForm("edit", row); |
| | | }, |
| | | }, |
| | | { |
| | | //èµè´¨éä»¶ |
| | | name: "èµè´¨æä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const userList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const filesDia = ref(); |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", |
| | | }, |
| | | form: { |
| | | supplierName: "", |
| | | taxpayerIdentificationNum: "", |
| | | companyAddress: "", |
| | | companyPhone: "", |
| | | bankAccountName: "", |
| | | bankAccountNum: "", |
| | | contactUserName: "", |
| | | contactUserPhone: "", |
| | | maintainUserId: "", |
| | | maintainTime: "", |
| | | supplierType: "", |
| | | isWhite: "", |
| | | }, |
| | | rules: { |
| | | supplierName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // taxpayerIdentificationNum: [ |
| | | // { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | // ], |
| | | // companyAddress: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // companyPhone: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // bankAccountName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | // bankAccountNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contactUserName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | contactUserPhone: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | maintainUserId: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | maintainTime: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | supplierType: [ |
| | | { required: true, message: "è¯·éæ©ä¾åºåç±»å", trigger: "change" }, |
| | | ], |
| | | }, |
| | | }); |
| | | const { searchForm, form, rules } = toRefs(data); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | | upload.isUploading = true; |
| | | proxy.$refs["uploadRef"].submit(); |
| | | } |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listSupplier({ ...searchForm.value, ...page, isWhite: 0 }).then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼ä¾åºå导å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼ä¾åºå导å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // æ¯å¦æ´æ°å·²ç»åå¨çç¨æ·æ°æ® |
| | | updateSupport: 1, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import", |
| | | }); |
| | | /** 导å
¥æé®æä½ */ |
| | | function handleImport() { |
| | | upload.title = "ä¾åºå导å
¥"; |
| | | upload.open = true; |
| | | } |
| | | /** ä¸è½½æ¨¡æ¿ */ |
| | | function importTemplate() { |
| | | proxy.download( |
| | | "/system/supplier/downloadTemplate", |
| | | {}, |
| | | "ä¾åºå导å
¥æ¨¡æ¿.xlsx" |
| | | ); |
| | | } |
| | | |
| | | /**æä»¶ä¸ä¼ ä¸å¤ç */ |
| | | const handleFileUploadProgress = (event, file, fileList) => { |
| | | upload.isUploading = true; |
| | | }; |
| | | |
| | | /** æä»¶ä¸ä¼ æåå¤ç */ |
| | | const handleFileSuccess = (response, file, fileList) => { |
| | | upload.isUploading = false; |
| | | if (response.code === 200) { |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | upload.open = false; |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | getList(); |
| | | } else if (response.code === 500) { |
| | | proxy.$modal.msgError(response.msg); |
| | | } else { |
| | | proxy.$modal.msgWarning(response.msg); |
| | | } |
| | | }; |
| | | |
| | | /** æä»¶ä¸ä¼ 失败å¤ç */ |
| | | const handleFileError = (error, file, fileList) => { |
| | | upload.isUploading = false; |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | form.value.maintainUserId = userStore.id; |
| | | form.value.maintainTime = getCurrentDate(); |
| | | userListNoPage().then(res => { |
| | | userList.value = res.data; |
| | | }); |
| | | if (type === "edit") { |
| | | getSupplier(row.id).then(res => { |
| | | form.value = { ...res.data }; |
| | | }); |
| | | } |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate(valid => { |
| | | if (valid) { |
| | | if (operationType.value === "edit") { |
| | | submitEdit(); |
| | | } else { |
| | | submitAdd(); |
| | | } |
| | | } |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const selectedRows = ref([]); |
| | | const userList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const filesDia = ref() |
| | | // ç¨æ·ä¿¡æ¯è¡¨åå¼¹æ¡æ°æ® |
| | | const operationType = ref(""); |
| | | const dialogFormVisible = ref(false); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | supplierName: "", |
| | | }, |
| | | form: { |
| | | supplierName: "", |
| | | taxpayerIdentificationNum: "", |
| | | companyAddress: "", |
| | | companyPhone: "", |
| | | bankAccountName: "", |
| | | bankAccountNum: "", |
| | | contactUserName: "", |
| | | contactUserPhone: "", |
| | | maintainUserId: "", |
| | | maintainTime: "", |
| | | supplierType: "", |
| | | isWhite: "", |
| | | }, |
| | | rules: { |
| | | supplierName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | taxpayerIdentificationNum: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | companyAddress: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | companyPhone: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankAccountName: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | bankAccountNum: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | contactUserName: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | contactUserPhone: [{ required: false, message: "请è¾å
¥", trigger: "blur" }], |
| | | maintainUserId: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | maintainTime: [{ required: false, message: "è¯·éæ©", trigger: "change" }], |
| | | supplierType: [{ required: true, message: "è¯·éæ©ä¾åºåç±»å", trigger: "change" }], |
| | | }, |
| | | }); |
| | | const { searchForm, form, rules } = toRefs(data); |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | /** æäº¤ä¸ä¼ æä»¶ */ |
| | | function submitFileForm() { |
| | | upload.isUploading = true; |
| | | proxy.$refs["uploadRef"].submit(); |
| | | } |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | listSupplier({ ...searchForm.value, ...page, isWhite: 0 }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }); |
| | | }; |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå±ï¼ä¾åºå导å
¥ï¼ |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ï¼ä¾åºå导å
¥ï¼ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // æ¯å¦æ´æ°å·²ç»åå¨çç¨æ·æ°æ® |
| | | updateSupport: 1, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/system/supplier/import", |
| | | }); |
| | | /** 导å
¥æé®æä½ */ |
| | | function handleImport() { |
| | | upload.title = "ä¾åºå导å
¥"; |
| | | upload.open = true; |
| | | } |
| | | /** ä¸è½½æ¨¡æ¿ */ |
| | | function importTemplate() { |
| | | proxy.download("/system/supplier/downloadTemplate", {}, "ä¾åºå导å
¥æ¨¡æ¿.xlsx"); |
| | | } |
| | | |
| | | /**æä»¶ä¸ä¼ ä¸å¤ç */ |
| | | const handleFileUploadProgress = (event, file, fileList) => { |
| | | upload.isUploading = true; |
| | | }; |
| | | |
| | | /** æä»¶ä¸ä¼ æåå¤ç */ |
| | | const handleFileSuccess = (response, file, fileList) => { |
| | | upload.isUploading = false; |
| | | if(response.code === 200){ |
| | | proxy.$modal.msgSuccess("æä»¶ä¸ä¼ æå"); |
| | | upload.open = false; |
| | | proxy.$refs["uploadRef"].clearFiles(); |
| | | getList(); |
| | | }else if(response.code === 500){ |
| | | proxy.$modal.msgError(response.msg); |
| | | }else{ |
| | | proxy.$modal.msgWarning(response.msg); |
| | | } |
| | | }; |
| | | |
| | | /** æä»¶ä¸ä¼ 失败å¤ç */ |
| | | const handleFileError = (error, file, fileList) => { |
| | | upload.isUploading = false; |
| | | proxy.$modal.msgError("æä»¶ä¸ä¼ 失败"); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | form.value.maintainUserId = userStore.id; |
| | | form.value.maintainTime = getCurrentDate(); |
| | | userListNoPage().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | | if (type === "edit") { |
| | | getSupplier(row.id).then((res) => { |
| | | form.value = { ...res.data }; |
| | | }); |
| | | } |
| | | dialogFormVisible.value = true; |
| | | }; |
| | | // æäº¤è¡¨å |
| | | const submitForm = () => { |
| | | proxy.$refs["formRef"].validate((valid) => { |
| | | if (valid) { |
| | | if (operationType.value === "edit") { |
| | | submitEdit(); |
| | | } else { |
| | | submitAdd(); |
| | | } |
| | | } |
| | | }); |
| | | }; |
| | | // æäº¤æ°å¢ |
| | | const submitAdd = () => { |
| | | addSupplier(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | }; |
| | | // æäº¤ä¿®æ¹ |
| | | const submitEdit = () => { |
| | | updateSupplier(form.value).then((res) => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | }; |
| | | // æäº¤æ°å¢ |
| | | const submitAdd = () => { |
| | | addSupplier(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | }; |
| | | // æäº¤ä¿®æ¹ |
| | | const submitEdit = () => { |
| | | updateSupplier(form.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeDia(); |
| | | getList(); |
| | | }); |
| | | }; |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.resetForm("formRef"); |
| | | dialogFormVisible.value = false; |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/system/supplier/export", { isWhite: 0 }, "ä¾åºåæ¡£æ¡.xlsx"); |
| | | proxy.download( |
| | | "/system/supplier/export", |
| | | { isWhite: 0 }, |
| | | "ä¾åºåæ¡£æ¡.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter(item => item.maintainUserName !== userStore.nickName); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | }; |
| | | // å é¤ |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | // æ£æ¥æ¯å¦æä»äººç»´æ¤çæ°æ® |
| | | const unauthorizedData = selectedRows.value.filter( |
| | | item => item.maintainUserName !== userStore.nickName |
| | | ); |
| | | if (unauthorizedData.length > 0) { |
| | | proxy.$modal.msgWarning("ä¸å¯å é¤ä»äººç»´æ¤çæ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | delSupplier(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | .then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (row) => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(row) |
| | | }) |
| | | }; |
| | | // è·åå½åæ¥æå¹¶æ ¼å¼å为 YYYY-MM-DD |
| | | function getCurrentDate() { |
| | | const today = new Date(); |
| | | const year = today.getFullYear(); |
| | | const month = String(today.getMonth() + 1).padStart(2, "0"); // æä»½ä»0å¼å§ |
| | | const day = String(today.getDate()).padStart(2, "0"); |
| | | return `${year}-${month}-${day}`; |
| | | } |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = row => { |
| | | nextTick(() => { |
| | | filesDia.value?.openDialog(row); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | |
| | | defineExpose({ |
| | | getList, |
| | | }); |
| | | defineExpose({ |
| | | getList, |
| | | }); |
| | | </script> |
| | | |
| | |
| | | <!-- å¨ä½ ç主页é¢ä¸ --> |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <el-tab-pane label="æ£å¸¸ä¾åºå" name="home"> |
| | | <el-tabs v-model="activeTab" |
| | | @tab-change="handleTabChange"> |
| | | <el-tab-pane label="æ£å¸¸ä¾åºå" |
| | | name="home"> |
| | | <HomeTab ref="homeTab" /> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="é»åå" name="blacklist"> |
| | | <el-tab-pane label="é»åå" |
| | | name="blacklist"> |
| | | <BlacklistTab ref="blacklistTab" /> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | |
| | | </template> |
| | | |
| | | <script> |
| | | import HomeTab from './components/HomeTab.vue' |
| | | import BlacklistTab from './components/BlacklistTab.vue' |
| | | import HomeTab from "./components/HomeTab.vue"; |
| | | import BlacklistTab from "./components/BlacklistTab.vue"; |
| | | |
| | | export default { |
| | | name: 'MainPage', |
| | | components: { |
| | | HomeTab, |
| | | BlacklistTab |
| | | }, |
| | | data() { |
| | | return { |
| | | activeTab: 'home' |
| | | } |
| | | }, |
| | | methods: { |
| | | handleTabChange(tabName) { |
| | | this.activeTab = tabName |
| | | this.$nextTick(() => { |
| | | if (tabName === 'home') { |
| | | this.$refs.homeTab && this.$refs.homeTab.getList && this.$refs.homeTab.getList() |
| | | } else if (tabName === 'blacklist') { |
| | | this.$refs.blacklistTab && this.$refs.blacklistTab.getList && this.$refs.blacklistTab.getList() |
| | | } |
| | | }) |
| | | export default { |
| | | name: "MainPage", |
| | | components: { |
| | | HomeTab, |
| | | BlacklistTab, |
| | | }, |
| | | } |
| | | } |
| | | data() { |
| | | return { |
| | | activeTab: "home", |
| | | }; |
| | | }, |
| | | methods: { |
| | | handleTabChange(tabName) { |
| | | this.activeTab = tabName; |
| | | this.$nextTick(() => { |
| | | if (tabName === "home") { |
| | | this.$refs.homeTab && |
| | | this.$refs.homeTab.getList && |
| | | this.$refs.homeTab.getList(); |
| | | } else if (tabName === "blacklist") { |
| | | this.$refs.blacklistTab && |
| | | this.$refs.blacklistTab.getList && |
| | | this.$refs.blacklistTab.getList(); |
| | | } |
| | | }); |
| | | }, |
| | | }, |
| | | }; |
| | | </script> |
| | |
| | | <div class="welcome-banner"> |
| | | <div class="welcome-title"> |
| | | <span class="welcome-user">{{ userStore.roleName || 'ç³»ç»ç®¡çå' }}</span> |
| | | <span> æ¨å¥½ï¼ç¥æ¨å¼å¿æ¯ä¸å¤©</span> |
| | | <span> æ¨å¥½ï¼ï¼ç¥æ¨å¼å¿æ¯ä¸å¤©</span> |
| | | </div> |
| | | <div class="welcome-time">ç»å½äº: {{ userStore.currentLoginTime }}</div> |
| | | </div> |
| | | |
| | | <!-- ç¨æ·ä¿¡æ¯å¡ç --> |
| | | <div class="user-card"> |
| | | <img :src="userStore.avatar" class="avatar" alt="" /> |
| | | <img :src="userStore.avatar" |
| | | class="avatar" |
| | | alt="" /> |
| | | <div class="user-card-main"> |
| | | <div class="user-name">{{ userStore.name }}</div> |
| | | <div class="user-role">{{ userStore.roleName }}</div> |
| | |
| | | <div class="data-value">{{ businessInfo.monthSaleHaveMoney }}</div> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | <div class="data-card purchase"> |
| | | <div class="data-title">éè´æ°æ®</div> |
| | |
| | | <!-- å³ï¼å¾
åäºé¡¹ --> |
| | | <div class="todo-panel"> |
| | | <div class="section-title">å¾
åäºé¡¹</div> |
| | | <ul class="todo-list" v-if="todoList.length > 0"> |
| | | <li v-for="item in todoList" :key="item.id"> |
| | | <ul class="todo-list" |
| | | v-if="todoList.length > 0"> |
| | | <li v-for="item in todoList" |
| | | :key="item.id"> |
| | | <div style="display: flex;flex-direction: column;justify-content: space-between;width: 100%;gap: 20px"> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;"> |
| | | <div class="todo-title">å¾
åç¼å·ï¼{{ item.approveId }}</div> |
| | |
| | | </div> |
| | | </li> |
| | | </ul> |
| | | <div v-else style="text-align: center"> |
| | | <div v-else |
| | | style="text-align: center"> |
| | | ææ æ°æ® |
| | | </div> |
| | | </div> |
| | |
| | | <div class="process-panel__header"> |
| | | <div class="section-title">å·¥åºæ°æ®ç产ç»è®¡æç»</div> |
| | | <div style="display: flex; gap: 10px; align-items: center;"> |
| | | <el-button type="primary" size="small" plain icon="Filter" @click="openProcessDialog">鿩工åº</el-button> |
| | | <el-button type="info" size="small" plain icon="Refresh" @click="resetProcessFilter">éç½®</el-button> |
| | | <el-radio-group v-model="processRange" size="small" @change="refreshProcessStats"> |
| | | <el-button type="primary" |
| | | size="small" |
| | | plain |
| | | icon="Filter" |
| | | @click="openProcessDialog">鿩工åº</el-button> |
| | | <el-button type="info" |
| | | size="small" |
| | | plain |
| | | icon="Refresh" |
| | | @click="resetProcessFilter">éç½®</el-button> |
| | | <el-radio-group v-model="processRange" |
| | | size="small" |
| | | @change="refreshProcessStats"> |
| | | <el-radio-button :value="1">æ¥</el-radio-button> |
| | | <el-radio-button :value="2">å¨</el-radio-button> |
| | | <el-radio-button :value="3">æ</el-radio-button> |
| | | </el-radio-group> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="process-panel__body"> |
| | | <div class="process-panel__chart"> |
| | | <Echarts :chartStyle="{ width: '100%', height: '100%' }" :grid="processGrid" :series="processSeries" |
| | | :tooltip="processTooltip" :xAxis="processXAxis" :yAxis="processYAxis" style="height: 100%" |
| | | @click="handleChartClick" /> |
| | | <Echarts :chartStyle="{ width: '100%', height: '100%' }" |
| | | :grid="processGrid" |
| | | :series="processSeries" |
| | | :tooltip="processTooltip" |
| | | :xAxis="processXAxis" |
| | | :yAxis="processYAxis" |
| | | style="height: 100%" |
| | | @click="handleChartClick" /> |
| | | </div> |
| | | |
| | | <div class="process-panel__aside"> |
| | | <div class="process-legend"> |
| | | <div class="process-legend__item"> |
| | |
| | | <span class="dot dot-teal"></span><span>产åºé</span> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="process-card process-card--name">{{ processAside.processName }}</div> |
| | | |
| | | <div class="process-card"> |
| | | <div class="process-card__label">ç´¯è®¡æ»æå
¥</div> |
| | | <div class="process-card__value">{{ formatAmount(processAside.totalInput) }} |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- å·¥åºéæ©å¼¹çª --> |
| | | <el-dialog v-model="processDialogVisible" title="鿩工åº" width="500px" append-to-body> |
| | | <el-dialog v-model="processDialogVisible" |
| | | title="鿩工åº" |
| | | width="500px" |
| | | append-to-body> |
| | | <div class="process-selection-wrapper"> |
| | | <el-checkbox-group v-model="tempProcessIds"> |
| | | <div class="process-grid"> |
| | | <el-checkbox v-for="item in processOptions" :key="item.id" :label="item.id" border> |
| | | <el-checkbox v-for="item in processOptions" |
| | | :key="item.id" |
| | | :label="item.id" |
| | | border> |
| | | {{ item.name }} |
| | | </el-checkbox> |
| | | </div> |
| | |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button @click="processDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleProcessDialogConfirm">确认</el-button> |
| | | <el-button type="primary" |
| | | @click="handleProcessDialogConfirm">确认</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <div class="section-title">客æ·ååéé¢åæ</div> |
| | | <div class="contract-summary"> |
| | | <div class="contract-info"> |
| | | <img src="../assets/images/khtitle.png" alt="" style="width: 42px" /> |
| | | <img src="../assets/images/khtitle.png" |
| | | alt="" |
| | | style="width: 42px" /> |
| | | <div class="contract-card"> |
| | | <div class="contract-name">æ»ååéé¢(å
)</div> |
| | | <div class="contract-meta"> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div |
| | | style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px"> |
| | | <div style="display: flex;align-items: center;gap: 20px;justify-content: space-evenly;height: 180px;margin-top: 20px"> |
| | | <div> |
| | | <Echarts ref="chart" :legend="pieLegend" :chartStyle="chartStylePie" :series="materialPieSeries" |
| | | :tooltip="pieTooltip"></Echarts> |
| | | <Echarts ref="chart" |
| | | :legend="pieLegend" |
| | | :chartStyle="chartStylePie" |
| | | :series="materialPieSeries" |
| | | :tooltip="pieTooltip"></Echarts> |
| | | </div> |
| | | <ul class="contract-list"> |
| | | <li v-for="item in materialPieSeries[0].data" :key="item.name"> |
| | | <li v-for="item in materialPieSeries[0].data" |
| | | :key="item.name"> |
| | | <div style="display: flex;align-items: center;justify-content: space-between;width: 100%"> |
| | | <div class="line" :style="{ color: item.itemStyle.color }">â{{ item.name }}</div> |
| | | <div class="line" |
| | | :style="{ color: item.itemStyle.color }">â{{ item.name }}</div> |
| | | <div style="width: 70px">{{ item.rate }}%</div> |
| | | <div>ï¿¥{{ item.value }}</div> |
| | | </div> |
| | |
| | | <!-- <el-radio-button label="æå£åº¦" :value="3" />--> |
| | | <!-- </el-radio-group>--> |
| | | </div> |
| | | <Echarts ref="chart" :color="barColors2" :chartStyle="chartStyle" :grid="grid" :series="barSeries" |
| | | :tooltip="tooltip" :xAxis="xAxis" :yAxis="yAxis" style="height: 260px"></Echarts> |
| | | <Echarts ref="chart" |
| | | :color="barColors2" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :series="barSeries" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis" |
| | | :yAxis="yAxis" |
| | | style="height: 260px"></Echarts> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- åºé¨æ¨ªå两æ --> |
| | | <div class="dashboard-row"> |
| | | <div class="main-panel"> |
| | | <div style="display: flex;justify-content: space-between;align-items: center;margin-bottom: 10px;"> |
| | | <div class="section-title" style="margin-bottom: 0;">è´¨éç»è®¡</div> |
| | | <el-radio-group v-model="qualityRange" size="small" @change="qualityStatisticsInfo"> |
| | | <div class="section-title" |
| | | style="margin-bottom: 0;">è´¨éç»è®¡</div> |
| | | <el-radio-group v-model="qualityRange" |
| | | size="small" |
| | | @change="qualityStatisticsInfo"> |
| | | <el-radio-button :value="1">å¨</el-radio-button> |
| | | <el-radio-button :value="2">æ</el-radio-button> |
| | | <el-radio-button :value="3">å£åº¦</el-radio-button> |
| | |
| | | <div class="quality-card two">è¿ç¨æ£éªæ°é <span>{{ qualityStatisticsObject.processNum }}ä»¶</span></div> |
| | | <div class="quality-card three">åºåå·²æ£æ°é <span>{{ qualityStatisticsObject.factoryNum }}ä»¶</span></div> |
| | | </div> |
| | | <Echarts ref="chart" :chartStyle="chartStyle" :grid="grid" :legend="barLegend" :series="barSeries1" |
| | | :tooltip="tooltip" :xAxis="xAxis1" :yAxis="yAxis1" style="height: 260px"></Echarts> |
| | | <Echarts ref="chart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="barLegend" |
| | | :series="barSeries1" |
| | | :tooltip="tooltip" |
| | | :xAxis="xAxis1" |
| | | :yAxis="yAxis1" |
| | | style="height: 260px"></Echarts> |
| | | </div> |
| | | |
| | | <div class="main-panel"> |
| | | <div class="section-title">忬¾ä¸å¼ç¥¨åæ</div> |
| | | <Echarts ref="invoiceChart" :chartStyle="chartStyle" :grid="grid" :legend="lineLegend" :series="lineSeries" |
| | | :tooltip="tooltipLine" :xAxis="xAxis2" :yAxis="yAxis2" style="height: 270px;" /> |
| | | <Echarts ref="invoiceChart" |
| | | :chartStyle="chartStyle" |
| | | :grid="grid" |
| | | :legend="lineLegend" |
| | | :series="lineSeries" |
| | | :tooltip="tooltipLine" |
| | | :xAxis="xAxis2" |
| | | :yAxis="yAxis2" |
| | | style="height: 270px;" /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, computed, reactive } from 'vue' |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import * as echarts from 'echarts'; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import { |
| | | analysisCustomerContractAmounts, getAmountHalfYear, |
| | | getBusiness, |
| | | homeTodos, |
| | | processDataProductionStatistics, |
| | | statisticsReceivablePayable, |
| | | qualityInspectionStatistics |
| | | } from "@/api/viewIndex.js"; |
| | | import { list } from '@/api/productionManagement/productionProcess'; |
| | | import { ref, onMounted, computed, reactive } from "vue"; |
| | | import Echarts from "@/components/Echarts/echarts.vue"; |
| | | import * as echarts from "echarts"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import { |
| | | analysisCustomerContractAmounts, |
| | | getAmountHalfYear, |
| | | getBusiness, |
| | | homeTodos, |
| | | processDataProductionStatistics, |
| | | statisticsReceivablePayable, |
| | | qualityInspectionStatistics, |
| | | } from "@/api/viewIndex.js"; |
| | | import { list } from "@/api/productionManagement/productionProcess"; |
| | | |
| | | const userStore = useUserStore(); |
| | | |
| | | const userStore = useUserStore() |
| | | const processOptions = ref([]); |
| | | const selectedProcessIds = ref([]); |
| | | const tempProcessIds = ref([]); |
| | | const processDialogVisible = ref(false); |
| | | const activeProcessIndex = ref(0); |
| | | |
| | | const processOptions = ref([]) |
| | | const selectedProcessIds = ref([]) |
| | | const tempProcessIds = ref([]) |
| | | const processDialogVisible = ref(false) |
| | | const activeProcessIndex = ref(0) |
| | | const businessInfo = ref({ |
| | | inventoryNum: 0, |
| | | monthPurchaseHaveMoney: 0, |
| | | monthPurchaseMoney: 0, |
| | | monthSaleHaveMoney: 0, |
| | | monthSaleMoney: 0, |
| | | todayInventoryNum: 0, |
| | | }); |
| | | const qualityStatisticsObject = ref({ |
| | | supplierNum: 0, |
| | | processNum: 0, |
| | | factoryNum: 0, |
| | | }); |
| | | const sum = ref(0); |
| | | const yny = ref(0); |
| | | const chain = ref(0); |
| | | |
| | | const businessInfo = ref({ |
| | | inventoryNum: 0, |
| | | monthPurchaseHaveMoney: 0, |
| | | monthPurchaseMoney: 0, |
| | | monthSaleHaveMoney: 0, |
| | | monthSaleMoney: 0, |
| | | todayInventoryNum: 0, |
| | | }) |
| | | const qualityStatisticsObject = ref({ |
| | | supplierNum: 0, |
| | | processNum: 0, |
| | | factoryNum: 0, |
| | | }) |
| | | const sum = ref(0) |
| | | const yny = ref(0) |
| | | const chain = ref(0) |
| | | |
| | | const pieLegend = reactive({ |
| | | show: false, |
| | | }) |
| | | const barSeries = ref([ |
| | | { |
| | | type: 'bar', |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | | } |
| | | }, |
| | | ]) |
| | | |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: 'åææä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | barGap: 0, |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'è¿ç¨ä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | data: [] |
| | | }, |
| | | { |
| | | name: 'åºåä¸åæ ¼æ°', |
| | | type: 'bar', |
| | | emphasis: { |
| | | focus: 'series' |
| | | }, |
| | | data: [] |
| | | }, |
| | | ]) |
| | | const chartStyle = { |
| | | width: '100%', |
| | | height: '100%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | const chartStylePie = { |
| | | width: '140%', |
| | | height: '140%' // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | } |
| | | const grid = { |
| | | left: '3%', |
| | | right: '4%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | } |
| | | const barLegend = { |
| | | show: true, |
| | | data: ['åææä¸åæ ¼æ°', 'è¿ç¨ä¸åæ ¼æ°', 'åºåä¸åæ ¼æ°'] |
| | | } |
| | | const barLegend1 = { |
| | | show: true, |
| | | data: ['é¢ä»è´¦æ¬¾', 'åºä»è´¦æ¬¾', '颿¶è´¦æ¬¾', 'åºæ¶è´¦æ¬¾'] |
| | | } |
| | | const lineLegend = { |
| | | show: true, |
| | | data: ['å¼ç¥¨', '忬¾'] |
| | | } |
| | | const tooltip = { |
| | | trigger: 'axis', |
| | | axisPointer: { |
| | | type: 'shadow' |
| | | } |
| | | } |
| | | const xAxis = [{ |
| | | type: 'value', |
| | | }] |
| | | const xAxis1 = ref([{ |
| | | type: 'category', |
| | | axisTick: { show: false }, |
| | | data: [] |
| | | }]) |
| | | const yAxis = [{ |
| | | type: 'category', |
| | | data: ['åºä»è´¦æ¬¾', 'åºæ¶è´¦æ¬¾',] |
| | | }] |
| | | const yAxis1 = [{ |
| | | type: 'value' |
| | | }] |
| | | const pieTooltip = reactive({ |
| | | trigger: 'item', |
| | | formatter: function (params) { |
| | | // å¨æçææç¤ºä¿¡æ¯ï¼åºäºæ°æ®é¡¹ç name 屿§ |
| | | const description = params.name === 'æ¬æåæ¬¾éé¢' ? 'æ¬æåæ¬¾éé¢' : 'åºæ¶æ¬¾éé¢'; |
| | | return `${description} ${formatNumber(params.value)}å
${params.percent}%`; |
| | | }, |
| | | position: 'right' |
| | | }) |
| | | const materialPieSeries = ref([ |
| | | { |
| | | type: 'pie', |
| | | radius: ['66%', '90%'], |
| | | avoidLabelOverlap: false, |
| | | itemStyle: { |
| | | borderColor: '#fff', |
| | | borderWidth: 2 |
| | | }, |
| | | label: { |
| | | show: false |
| | | }, |
| | | data: [] |
| | | } |
| | | ]) |
| | | const lineSeries = ref([ |
| | | { |
| | | type: 'line', |
| | | data: [], |
| | | label: { |
| | | show: true |
| | | }, |
| | | showSymbol: true, // æ¾ç¤ºåç¹ |
| | | }, |
| | | ]) |
| | | const tooltipLine = { |
| | | trigger: 'axis', |
| | | } |
| | | const yAxis2 = ref([ |
| | | { |
| | | type: 'value', |
| | | } |
| | | ]) |
| | | const xAxis2 = ref([ |
| | | { |
| | | type: 'category', |
| | | data: [], |
| | | axisLabel: { |
| | | interval: 0, |
| | | formatter: function (value) { |
| | | return value.replace(/~/g, '\n'); |
| | | }, |
| | | } |
| | | } |
| | | ]) |
| | | |
| | | // å¾
åäºé¡¹ |
| | | const todoList = ref([]) |
| | | const radio1 = ref(1) |
| | | const qualityRange = ref(1) |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | const barChart = ref(null) |
| | | const lineChart = ref(null) |
| | | const barColors2 = ['#5181DB', '#D369E0', '#F2CA6D', '#60CCA8'] |
| | | |
| | | // éæºé¢è²çæå½æ° |
| | | const getRandomColor = () => { |
| | | return '#' + Math.floor(Math.random() * 0xffffff).toString(16).padStart(6, '0'); |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getBusinessData() |
| | | analysisCustomer() |
| | | todoInfoS() |
| | | statisticsReceivable() |
| | | qualityStatisticsInfo() |
| | | getAmountHalfYearNum() |
| | | getProcessList() |
| | | }) |
| | | // æ°æ®ç»è®¡ |
| | | const getBusinessData = () => { |
| | | getBusiness().then((res) => { |
| | | businessInfo.value = { ...res.data } |
| | | }) |
| | | } |
| | | // ååéé¢ |
| | | const analysisCustomer = () => { |
| | | analysisCustomerContractAmounts().then((res) => { |
| | | sum.value = res.data.sum |
| | | yny.value = res.data.yny |
| | | chain.value = res.data.chain |
| | | // 为æ¯ä¸ªæ°æ®é¡¹åé
éæºé¢è² |
| | | materialPieSeries.value[0].data = res.data.item.map(item => ({ |
| | | ...item, |
| | | itemStyle: { color: getRandomColor() } |
| | | })) |
| | | }) |
| | | } |
| | | // å¾
åäºé¡¹ |
| | | const todoInfoS = () => { |
| | | homeTodos().then((res) => { |
| | | todoList.value = res.data |
| | | }) |
| | | } |
| | | // è·åå·¥åºå表 |
| | | const getProcessList = () => { |
| | | list().then(res => { |
| | | processOptions.value = res.data |
| | | }) |
| | | } |
| | | |
| | | const openProcessDialog = () => { |
| | | tempProcessIds.value = [...selectedProcessIds.value] |
| | | processDialogVisible.value = true |
| | | } |
| | | |
| | | const handleProcessDialogConfirm = () => { |
| | | selectedProcessIds.value = [...tempProcessIds.value] |
| | | processDialogVisible.value = false |
| | | refreshProcessStats() |
| | | } |
| | | |
| | | const resetProcessFilter = () => { |
| | | selectedProcessIds.value = [] |
| | | tempProcessIds.value = [] |
| | | refreshProcessStats() |
| | | } |
| | | |
| | | const handleChartClick = (params) => { |
| | | if (params && params.dataIndex !== undefined) { |
| | | activeProcessIndex.value = params.dataIndex |
| | | } |
| | | } |
| | | // åºä»åºæ¶ç»è®¡ |
| | | const statisticsReceivable = () => { |
| | | statisticsReceivablePayable({ type: radio1.value }).then((res) => { |
| | | barSeries.value[0].data = [ |
| | | // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } }, |
| | | { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } }, |
| | | // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } }, |
| | | { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } } |
| | | ] |
| | | }) |
| | | } |
| | | // è´¨æ£ç»è®¡ |
| | | const qualityStatisticsInfo = () => { |
| | | qualityInspectionStatistics({ type: qualityRange.value }).then((res) => { |
| | | xAxis1.value[0].data = [] |
| | | barSeries1.value[0].data = [] |
| | | barSeries1.value[1].data = [] |
| | | barSeries1.value[2].data = [] |
| | | res.data.item.forEach(item => { |
| | | xAxis1.value[0].data.push(item.date) |
| | | barSeries1.value[0].data.push(item.supplierNum) |
| | | barSeries1.value[1].data.push(item.processNum) |
| | | barSeries1.value[2].data.push(item.factoryNum) |
| | | }) |
| | | qualityStatisticsObject.value.supplierNum = res.data.supplierNum |
| | | qualityStatisticsObject.value.processNum = res.data.processNum |
| | | qualityStatisticsObject.value.factoryNum = res.data.factoryNum |
| | | }) |
| | | } |
| | | const getAmountHalfYearNum = async () => { |
| | | const res = await getAmountHalfYear() |
| | | console.log(res) |
| | | const monthName = [] |
| | | const receiptAmount = [] |
| | | const invoiceAmount = [] |
| | | res.data.forEach(item => { |
| | | monthName.push(item.month) |
| | | receiptAmount.push(item.receiptAmount) |
| | | invoiceAmount.push(item.invoiceAmount) |
| | | }) |
| | | // æ£ç¡®ååºå¼èµå¼ï¼å建æ°ç xAxis å series 对象 |
| | | xAxis2.value[0].data = monthName |
| | | xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, '\n~')); |
| | | lineSeries.value = [ |
| | | const pieLegend = reactive({ |
| | | show: false, |
| | | }); |
| | | const barSeries = ref([ |
| | | { |
| | | name: 'å¼ç¥¨', |
| | | type: 'line', |
| | | data: invoiceAmount, |
| | | stack: 'Total', |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: 'rgba(131, 207, 255, 1)' |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: 'rgba(186, 228, 255, 1)' |
| | | } |
| | | ]) |
| | | type: "bar", |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | | }, |
| | | itemStyle: { |
| | | color: '#2D99FF', |
| | | borderColor: '#2D99FF' |
| | | }, |
| | | }, |
| | | ]); |
| | | |
| | | const barSeries1 = ref([ |
| | | { |
| | | name: "åææä¸åæ ¼æ°", |
| | | type: "bar", |
| | | barGap: 0, |
| | | emphasis: { |
| | | focus: 'series' |
| | | focus: "series", |
| | | }, |
| | | lineStyle: { |
| | | width: 0 |
| | | }, |
| | | showSymbol: true, |
| | | data: [], |
| | | }, |
| | | { |
| | | name: '忬¾', |
| | | type: 'line', |
| | | data: receiptAmount, |
| | | stack: 'Total', |
| | | lineStyle: { |
| | | width: 0 |
| | | }, |
| | | itemStyle: { |
| | | color: '#83CFFF', |
| | | borderColor: '#83CFFF' |
| | | }, |
| | | showSymbol: true, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: 'rgba(54, 153, 255, 1)' |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: 'rgba(89, 169, 254, 1)' |
| | | } |
| | | ]) |
| | | }, |
| | | name: "è¿ç¨ä¸åæ ¼æ°", |
| | | type: "bar", |
| | | emphasis: { |
| | | focus: 'series' |
| | | focus: "series", |
| | | }, |
| | | data: [], |
| | | }, |
| | | { |
| | | name: "åºåä¸åæ ¼æ°", |
| | | type: "bar", |
| | | emphasis: { |
| | | focus: "series", |
| | | }, |
| | | data: [], |
| | | }, |
| | | ]); |
| | | const chartStyle = { |
| | | width: "100%", |
| | | height: "100%", // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | }; |
| | | const chartStylePie = { |
| | | width: "140%", |
| | | height: "140%", // 设置å¾è¡¨å®¹å¨çé«åº¦ |
| | | }; |
| | | const grid = { |
| | | left: "3%", |
| | | right: "4%", |
| | | bottom: "3%", |
| | | containLabel: true, |
| | | }; |
| | | const barLegend = { |
| | | show: true, |
| | | data: ["åææä¸åæ ¼æ°", "è¿ç¨ä¸åæ ¼æ°", "åºåä¸åæ ¼æ°"], |
| | | }; |
| | | const barLegend1 = { |
| | | show: true, |
| | | data: ["é¢ä»è´¦æ¬¾", "åºä»è´¦æ¬¾", "颿¶è´¦æ¬¾", "åºæ¶è´¦æ¬¾"], |
| | | }; |
| | | const lineLegend = { |
| | | show: true, |
| | | data: ["å¼ç¥¨", "忬¾"], |
| | | }; |
| | | const tooltip = { |
| | | trigger: "axis", |
| | | axisPointer: { |
| | | type: "shadow", |
| | | }, |
| | | }; |
| | | const xAxis = [ |
| | | { |
| | | type: "value", |
| | | }, |
| | | ]; |
| | | const xAxis1 = ref([ |
| | | { |
| | | type: "category", |
| | | axisTick: { show: false }, |
| | | data: [], |
| | | }, |
| | | ]); |
| | | const yAxis = [ |
| | | { |
| | | type: "category", |
| | | data: ["åºä»è´¦æ¬¾", "åºæ¶è´¦æ¬¾"], |
| | | }, |
| | | ]; |
| | | const yAxis1 = [ |
| | | { |
| | | type: "value", |
| | | }, |
| | | ]; |
| | | const pieTooltip = reactive({ |
| | | trigger: "item", |
| | | formatter: function (params) { |
| | | // å¨æçææç¤ºä¿¡æ¯ï¼åºäºæ°æ®é¡¹ç name 屿§ |
| | | const description = |
| | | params.name === "æ¬æåæ¬¾éé¢" ? "æ¬æåæ¬¾éé¢" : "åºæ¶æ¬¾éé¢"; |
| | | return `${description} ${formatNumber(params.value)}å
${params.percent}%`; |
| | | }, |
| | | position: "right", |
| | | }); |
| | | const materialPieSeries = ref([ |
| | | { |
| | | type: "pie", |
| | | radius: ["66%", "90%"], |
| | | avoidLabelOverlap: false, |
| | | itemStyle: { |
| | | borderColor: "#fff", |
| | | borderWidth: 2, |
| | | }, |
| | | label: { |
| | | show: false, |
| | | }, |
| | | data: [], |
| | | }, |
| | | ]); |
| | | const lineSeries = ref([ |
| | | { |
| | | type: "line", |
| | | data: [], |
| | | label: { |
| | | show: true, |
| | | }, |
| | | showSymbol: true, // æ¾ç¤ºåç¹ |
| | | }, |
| | | ]); |
| | | const tooltipLine = { |
| | | trigger: "axis", |
| | | }; |
| | | const yAxis2 = ref([ |
| | | { |
| | | type: "value", |
| | | }, |
| | | ]); |
| | | const xAxis2 = ref([ |
| | | { |
| | | type: "category", |
| | | data: [], |
| | | axisLabel: { |
| | | interval: 0, |
| | | formatter: function (value) { |
| | | return value.replace(/~/g, "\n"); |
| | | }, |
| | | }, |
| | | }, |
| | | ]); |
| | | |
| | | // å¾
åäºé¡¹ |
| | | const todoList = ref([]); |
| | | const radio1 = ref(1); |
| | | const qualityRange = ref(1); |
| | | |
| | | // å¾è¡¨å¼ç¨ |
| | | const barChart = ref(null); |
| | | const lineChart = ref(null); |
| | | const barColors2 = ["#5181DB", "#D369E0", "#F2CA6D", "#60CCA8"]; |
| | | |
| | | // éæºé¢è²çæå½æ° |
| | | const getRandomColor = () => { |
| | | return ( |
| | | "#" + |
| | | Math.floor(Math.random() * 0xffffff) |
| | | .toString(16) |
| | | .padStart(6, "0") |
| | | ); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getBusinessData(); |
| | | analysisCustomer(); |
| | | todoInfoS(); |
| | | statisticsReceivable(); |
| | | qualityStatisticsInfo(); |
| | | getAmountHalfYearNum(); |
| | | getProcessList(); |
| | | }); |
| | | // æ°æ®ç»è®¡ |
| | | const getBusinessData = () => { |
| | | getBusiness().then(res => { |
| | | businessInfo.value = { ...res.data }; |
| | | }); |
| | | }; |
| | | // ååéé¢ |
| | | const analysisCustomer = () => { |
| | | analysisCustomerContractAmounts().then(res => { |
| | | sum.value = res.data.sum; |
| | | yny.value = res.data.yny; |
| | | chain.value = res.data.chain; |
| | | // 为æ¯ä¸ªæ°æ®é¡¹åé
éæºé¢è² |
| | | materialPieSeries.value[0].data = res.data.item.map(item => ({ |
| | | ...item, |
| | | itemStyle: { color: getRandomColor() }, |
| | | })); |
| | | }); |
| | | }; |
| | | // å¾
åäºé¡¹ |
| | | const todoInfoS = () => { |
| | | homeTodos().then(res => { |
| | | todoList.value = res.data; |
| | | }); |
| | | }; |
| | | // è·åå·¥åºå表 |
| | | const getProcessList = () => { |
| | | list().then(res => { |
| | | processOptions.value = res.data; |
| | | }); |
| | | }; |
| | | |
| | | const openProcessDialog = () => { |
| | | tempProcessIds.value = [...selectedProcessIds.value]; |
| | | processDialogVisible.value = true; |
| | | }; |
| | | |
| | | const handleProcessDialogConfirm = () => { |
| | | selectedProcessIds.value = [...tempProcessIds.value]; |
| | | processDialogVisible.value = false; |
| | | refreshProcessStats(); |
| | | }; |
| | | |
| | | const resetProcessFilter = () => { |
| | | selectedProcessIds.value = []; |
| | | tempProcessIds.value = []; |
| | | refreshProcessStats(); |
| | | }; |
| | | |
| | | const handleChartClick = params => { |
| | | if (params && params.dataIndex !== undefined) { |
| | | activeProcessIndex.value = params.dataIndex; |
| | | } |
| | | ] |
| | | } |
| | | }; |
| | | // åºä»åºæ¶ç»è®¡ |
| | | const statisticsReceivable = () => { |
| | | statisticsReceivablePayable({ type: radio1.value }).then(res => { |
| | | barSeries.value[0].data = [ |
| | | // { value: res.data.prepayMoney, itemStyle: { color: barColors2[0] } }, |
| | | { value: res.data.payableMoney, itemStyle: { color: barColors2[0] } }, |
| | | // { value: res.data.advanceMoney, itemStyle: { color: barColors2[2] } }, |
| | | { value: res.data.receivableMoney, itemStyle: { color: barColors2[1] } }, |
| | | ]; |
| | | }); |
| | | }; |
| | | // è´¨æ£ç»è®¡ |
| | | const qualityStatisticsInfo = () => { |
| | | qualityInspectionStatistics({ type: qualityRange.value }).then(res => { |
| | | xAxis1.value[0].data = []; |
| | | barSeries1.value[0].data = []; |
| | | barSeries1.value[1].data = []; |
| | | barSeries1.value[2].data = []; |
| | | res.data.item.forEach(item => { |
| | | xAxis1.value[0].data.push(item.date); |
| | | barSeries1.value[0].data.push(item.supplierNum); |
| | | barSeries1.value[1].data.push(item.processNum); |
| | | barSeries1.value[2].data.push(item.factoryNum); |
| | | }); |
| | | qualityStatisticsObject.value.supplierNum = res.data.supplierNum; |
| | | qualityStatisticsObject.value.processNum = res.data.processNum; |
| | | qualityStatisticsObject.value.factoryNum = res.data.factoryNum; |
| | | }); |
| | | }; |
| | | const getAmountHalfYearNum = async () => { |
| | | const res = await getAmountHalfYear(); |
| | | console.log(res); |
| | | const monthName = []; |
| | | const receiptAmount = []; |
| | | const invoiceAmount = []; |
| | | res.data.forEach(item => { |
| | | monthName.push(item.month); |
| | | receiptAmount.push(item.receiptAmount); |
| | | invoiceAmount.push(item.invoiceAmount); |
| | | }); |
| | | // æ£ç¡®ååºå¼èµå¼ï¼å建æ°ç xAxis å series 对象 |
| | | xAxis2.value[0].data = monthName; |
| | | xAxis2.value[0].data = monthName.map(item => item.replace(/~/g, "\n~")); |
| | | lineSeries.value = [ |
| | | { |
| | | name: "å¼ç¥¨", |
| | | type: "line", |
| | | data: invoiceAmount, |
| | | stack: "Total", |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: "rgba(131, 207, 255, 1)", |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: "rgba(186, 228, 255, 1)", |
| | | }, |
| | | ]), |
| | | }, |
| | | itemStyle: { |
| | | color: "#2D99FF", |
| | | borderColor: "#2D99FF", |
| | | }, |
| | | emphasis: { |
| | | focus: "series", |
| | | }, |
| | | lineStyle: { |
| | | width: 0, |
| | | }, |
| | | showSymbol: true, |
| | | }, |
| | | { |
| | | name: "忬¾", |
| | | type: "line", |
| | | data: receiptAmount, |
| | | stack: "Total", |
| | | lineStyle: { |
| | | width: 0, |
| | | }, |
| | | itemStyle: { |
| | | color: "#83CFFF", |
| | | borderColor: "#83CFFF", |
| | | }, |
| | | showSymbol: true, |
| | | areaStyle: { |
| | | color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ |
| | | { |
| | | offset: 0, |
| | | color: "rgba(54, 153, 255, 1)", |
| | | }, |
| | | { |
| | | offset: 1, |
| | | color: "rgba(89, 169, 254, 1)", |
| | | }, |
| | | ]), |
| | | }, |
| | | emphasis: { |
| | | focus: "series", |
| | | }, |
| | | }, |
| | | ]; |
| | | }; |
| | | |
| | | // å·¥åºæ°æ®ç产ç»è®¡æç»ï¼åæ°æ® + å¾è¡¨ï¼ |
| | | const processRange = ref(1) |
| | | const processChartData = ref([]) |
| | | // å·¥åºæ°æ®ç产ç»è®¡æç»ï¼åæ°æ® + å¾è¡¨ï¼ |
| | | const processRange = ref(1); |
| | | const processChartData = ref([]); |
| | | |
| | | const processXAxis = ref([ |
| | | { |
| | | nameTextStyle: { color: 'rgba(0,0,0,0.35)', fontSize: 12 }, |
| | | axisLabel: { color: 'rgba(0,0,0,0.35)' }, |
| | | splitLine: { lineStyle: { color: 'rgba(0,0,0,0.06)', type: 'dashed' } }, |
| | | }, |
| | | ]) |
| | | |
| | | const processYAxis = ref([ |
| | | { |
| | | type: 'category', |
| | | axisTick: { show: false }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: 'rgba(0,0,0,0.45)' }, |
| | | data: [], |
| | | }, |
| | | ]) |
| | | |
| | | const processGrid = reactive({ left: 0, right: 100, top: 30, bottom: 20, containLabel: true }) |
| | | |
| | | const processTooltip = reactive({ |
| | | trigger: 'axis', |
| | | axisPointer: { type: 'shadow' }, |
| | | formatter: (params) => { |
| | | const name = params?.[0]?.name ?? '' |
| | | const list = Array.isArray(params) ? params : [] |
| | | const lines = list |
| | | .map((p) => { |
| | | const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>` |
| | | return `${colorBox}${p.seriesName} <b style="float:right;">${Number(p.value || 0).toFixed(2)}</b>` |
| | | }) |
| | | .join('<br/>') |
| | | return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>` |
| | | }, |
| | | }) |
| | | |
| | | const processSeries = computed(() => { |
| | | const input = processChartData.value.map((i) => i.input) |
| | | const scrap = processChartData.value.map((i) => i.scrap) |
| | | const output = processChartData.value.map((i) => i.output) |
| | | |
| | | return [ |
| | | const processXAxis = ref([ |
| | | { |
| | | name: 'æå
¥é', |
| | | type: 'bar', |
| | | stack: 'total', |
| | | barWidth: 22, |
| | | itemStyle: { color: '#1E5BFF', borderRadius: [6, 0, 0, 6] }, |
| | | data: input, |
| | | nameTextStyle: { color: "rgba(0,0,0,0.35)", fontSize: 12 }, |
| | | axisLabel: { color: "rgba(0,0,0,0.35)" }, |
| | | splitLine: { lineStyle: { color: "rgba(0,0,0,0.06)", type: "dashed" } }, |
| | | }, |
| | | ]); |
| | | |
| | | const processYAxis = ref([ |
| | | { |
| | | name: 'æ¥åºé', |
| | | type: 'bar', |
| | | stack: 'total', |
| | | barWidth: 22, |
| | | itemStyle: { color: '#F7B500' }, |
| | | data: scrap, |
| | | type: "category", |
| | | axisTick: { show: false }, |
| | | axisLine: { show: false }, |
| | | axisLabel: { color: "rgba(0,0,0,0.45)" }, |
| | | data: [], |
| | | }, |
| | | { |
| | | name: '产åºé', |
| | | type: 'bar', |
| | | stack: 'total', |
| | | barWidth: 22, |
| | | itemStyle: { color: '#19C6C6', borderRadius: [0, 6, 6, 0] }, |
| | | data: output, |
| | | ]); |
| | | |
| | | const processGrid = reactive({ |
| | | left: 0, |
| | | right: 100, |
| | | top: 30, |
| | | bottom: 20, |
| | | containLabel: true, |
| | | }); |
| | | |
| | | const processTooltip = reactive({ |
| | | trigger: "axis", |
| | | axisPointer: { type: "shadow" }, |
| | | formatter: params => { |
| | | const name = params?.[0]?.name ?? ""; |
| | | const list = Array.isArray(params) ? params : []; |
| | | const lines = list |
| | | .map(p => { |
| | | const colorBox = `<span style="display:inline-block;margin-right:6px;border-radius:2px;width:10px;height:10px;background:${p.color}"></span>`; |
| | | return `${colorBox}${p.seriesName} <b style="float:right;">${Number( |
| | | p.value || 0 |
| | | ).toFixed(2)}</b>`; |
| | | }) |
| | | .join("<br/>"); |
| | | return `<div style="min-width:140px;"><div style="font-weight:700;margin-bottom:6px;">${name}</div>${lines}</div>`; |
| | | }, |
| | | ] |
| | | }) |
| | | }); |
| | | |
| | | const processAside = computed(() => { |
| | | const list = processChartData.value |
| | | const item = list[activeProcessIndex.value] || {} |
| | | return { |
| | | processName: item.name || 'ææ æ°æ®', |
| | | totalInput: item.input || 0, |
| | | totalScrap: item.scrap || 0, |
| | | totalOutput: item.output || 0, |
| | | } |
| | | }) |
| | | const processSeries = computed(() => { |
| | | const input = processChartData.value.map(i => i.input); |
| | | const scrap = processChartData.value.map(i => i.scrap); |
| | | const output = processChartData.value.map(i => i.output); |
| | | |
| | | const formatAmount = (n) => { |
| | | const num = Number(n || 0) |
| | | return num.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }) |
| | | } |
| | | return [ |
| | | { |
| | | name: "æå
¥é", |
| | | type: "bar", |
| | | stack: "total", |
| | | barWidth: 22, |
| | | itemStyle: { color: "#1E5BFF", borderRadius: [6, 0, 0, 6] }, |
| | | data: input, |
| | | }, |
| | | { |
| | | name: "æ¥åºé", |
| | | type: "bar", |
| | | stack: "total", |
| | | barWidth: 22, |
| | | itemStyle: { color: "#F7B500" }, |
| | | data: scrap, |
| | | }, |
| | | { |
| | | name: "产åºé", |
| | | type: "bar", |
| | | stack: "total", |
| | | barWidth: 22, |
| | | itemStyle: { color: "#19C6C6", borderRadius: [0, 6, 6, 0] }, |
| | | data: output, |
| | | }, |
| | | ]; |
| | | }); |
| | | |
| | | const refreshProcessStats = () => { |
| | | processDataProductionStatistics({ |
| | | type: processRange.value, |
| | | processIds: selectedProcessIds.value.length > 0 ? selectedProcessIds.value.join(',') : null |
| | | }).then(res => { |
| | | processChartData.value = res.data.map(item => ({ |
| | | name: item.processName, |
| | | input: item.totalInput, |
| | | scrap: item.totalScrap, |
| | | output: item.totalOutput |
| | | })) |
| | | processYAxis.value[0].data = processChartData.value.map((i) => i.name) |
| | | activeProcessIndex.value = 0 |
| | | }) |
| | | } |
| | | const processAside = computed(() => { |
| | | const list = processChartData.value; |
| | | const item = list[activeProcessIndex.value] || {}; |
| | | return { |
| | | processName: item.name || "ææ æ°æ®", |
| | | totalInput: item.input || 0, |
| | | totalScrap: item.scrap || 0, |
| | | totalOutput: item.output || 0, |
| | | }; |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | getBusinessData() |
| | | analysisCustomer() |
| | | todoInfoS() |
| | | statisticsReceivable() |
| | | qualityStatisticsInfo() |
| | | getAmountHalfYearNum() |
| | | refreshProcessStats() |
| | | }) |
| | | const formatAmount = n => { |
| | | const num = Number(n || 0); |
| | | return num.toLocaleString(undefined, { |
| | | minimumFractionDigits: 2, |
| | | maximumFractionDigits: 2, |
| | | }); |
| | | }; |
| | | |
| | | const refreshProcessStats = () => { |
| | | processDataProductionStatistics({ |
| | | type: processRange.value, |
| | | processIds: |
| | | selectedProcessIds.value.length > 0 |
| | | ? selectedProcessIds.value.join(",") |
| | | : null, |
| | | }).then(res => { |
| | | processChartData.value = res.data.map(item => ({ |
| | | name: item.processName, |
| | | input: item.totalInput, |
| | | scrap: item.totalScrap, |
| | | output: item.totalOutput, |
| | | })); |
| | | processYAxis.value[0].data = processChartData.value.map(i => i.name); |
| | | activeProcessIndex.value = 0; |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getBusinessData(); |
| | | analysisCustomer(); |
| | | todoInfoS(); |
| | | statisticsReceivable(); |
| | | qualityStatisticsInfo(); |
| | | getAmountHalfYearNum(); |
| | | refreshProcessStats(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .dashboard { |
| | | background: #f5f7fa; |
| | | min-height: 100vh; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | } |
| | | .dashboard { |
| | | background: #f5f7fa; |
| | | min-height: 100vh; |
| | | padding: 20px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .dashboard-top { |
| | | display: flex; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | align-items: flex-start; |
| | | justify-content: space-evenly; |
| | | } |
| | | .dashboard-top { |
| | | display: flex; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | align-items: flex-start; |
| | | justify-content: space-evenly; |
| | | } |
| | | |
| | | .company-info { |
| | | padding: 0; |
| | | overflow: hidden; |
| | | border-radius: 12px; |
| | | background: #fff; |
| | | height: 100%; |
| | | } |
| | | .company-info { |
| | | padding: 0; |
| | | overflow: hidden; |
| | | border-radius: 12px; |
| | | background: #fff; |
| | | height: 100%; |
| | | } |
| | | |
| | | .welcome-banner { |
| | | padding: 10px 10px; |
| | | background: linear-gradient(135deg, rgba(229, 240, 255, 0.9), rgba(214, 232, 255, 0.7), rgba(207, 236, 255, 0.9)); |
| | | } |
| | | .welcome-banner { |
| | | padding: 10px 10px; |
| | | background: linear-gradient( |
| | | 135deg, |
| | | rgba(229, 240, 255, 0.9), |
| | | rgba(214, 232, 255, 0.7), |
| | | rgba(207, 236, 255, 0.9) |
| | | ); |
| | | } |
| | | |
| | | .welcome-title { |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: #222; |
| | | line-height: 1.3; |
| | | } |
| | | .welcome-title { |
| | | font-size: 18px; |
| | | font-weight: 700; |
| | | color: #222; |
| | | line-height: 1.3; |
| | | } |
| | | |
| | | .welcome-user { |
| | | margin-right: 6px; |
| | | } |
| | | .welcome-user { |
| | | margin-right: 6px; |
| | | } |
| | | |
| | | .welcome-time { |
| | | margin-top: 10px; |
| | | font-size: 16px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | } |
| | | .welcome-time { |
| | | margin-top: 10px; |
| | | font-size: 16px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | } |
| | | |
| | | .user-card { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | padding: 18px 22px; |
| | | } |
| | | .user-card { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 10px; |
| | | padding: 18px 22px; |
| | | } |
| | | |
| | | .user-card-main { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 5px; |
| | | min-width: 0; |
| | | } |
| | | .user-card-main { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 5px; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .user-name { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #111; |
| | | letter-spacing: 1px; |
| | | } |
| | | .user-name { |
| | | font-size: 16px; |
| | | font-weight: bold; |
| | | color: #111; |
| | | letter-spacing: 1px; |
| | | } |
| | | |
| | | .user-role { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 20px; |
| | | padding: 5px 10px; |
| | | background: rgba(245, 246, 248, 1); |
| | | color: #333; |
| | | width: fit-content; |
| | | font-weight: 600; |
| | | } |
| | | .user-role { |
| | | display: inline-flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | height: 20px; |
| | | padding: 5px 10px; |
| | | background: rgba(245, 246, 248, 1); |
| | | color: #333; |
| | | width: fit-content; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .user-meta { |
| | | font-size: 12px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .user-meta { |
| | | font-size: 12px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | |
| | | .user-meta .sep { |
| | | margin: 0 10px; |
| | | color: rgba(0, 0, 0, 0.25); |
| | | } |
| | | .user-meta .sep { |
| | | margin: 0 10px; |
| | | color: rgba(0, 0, 0, 0.25); |
| | | } |
| | | |
| | | .avatar { |
| | | width: 90px; |
| | | height: 90px; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | flex: 0 0 auto; |
| | | } |
| | | .avatar { |
| | | width: 90px; |
| | | height: 90px; |
| | | border-radius: 50%; |
| | | object-fit: cover; |
| | | flex: 0 0 auto; |
| | | } |
| | | |
| | | .data-cards { |
| | | width: 50%; |
| | | display: flex; |
| | | gap: 16px; |
| | | justify-content: flex-start; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | } |
| | | .data-cards { |
| | | width: 50%; |
| | | display: flex; |
| | | gap: 16px; |
| | | justify-content: flex-start; |
| | | background: #ffffff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | } |
| | | |
| | | .data-title { |
| | | font-weight: 700; |
| | | font-size: 26px; |
| | | color: #FFFFFF; |
| | | } |
| | | .data-title { |
| | | font-weight: 700; |
| | | font-size: 26px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .data-num { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-top: 20px; |
| | | } |
| | | .data-num { |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .data-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 14px 10px 10px 10px; |
| | | min-width: 160px; |
| | | box-shadow: 0 2px 8px #eee; |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 32%; |
| | | height: 140px; |
| | | } |
| | | .data-card { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 14px 10px 10px 10px; |
| | | min-width: 160px; |
| | | box-shadow: 0 2px 8px #eee; |
| | | display: flex; |
| | | flex-direction: column; |
| | | width: 32%; |
| | | height: 140px; |
| | | } |
| | | |
| | | .data-card.sales { |
| | | background-image: url("../assets/images/xioashoushuju.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .data-card.sales { |
| | | background-image: url("../assets/images/xioashoushuju.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .data-card.purchase { |
| | | background-image: url("../assets/images/caigou.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .data-card.purchase { |
| | | background-image: url("../assets/images/caigou.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .data-card.inventory { |
| | | background-image: url("../assets/images/kucun.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | .data-card.inventory { |
| | | background-image: url("../assets/images/kucun.png"); |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .data-desc { |
| | | font-weight: 500; |
| | | font-size: 13px; |
| | | color: #FFFFFF; |
| | | } |
| | | .data-desc { |
| | | font-weight: 500; |
| | | font-size: 13px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .data-value { |
| | | font-size: 18px; |
| | | font-weight: 500; |
| | | margin: 10px 0; |
| | | color: #FFFFFF; |
| | | } |
| | | .data-value { |
| | | font-size: 18px; |
| | | font-weight: 500; |
| | | margin: 10px 0; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .top-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | height: 180px; |
| | | width: 20%; |
| | | } |
| | | .top-left { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 20px; |
| | | height: 180px; |
| | | width: 20%; |
| | | } |
| | | |
| | | .todo-panel { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | height: 180px; |
| | | width: 30%; |
| | | } |
| | | .todo-panel { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | height: 180px; |
| | | width: 30%; |
| | | } |
| | | |
| | | .todo-list { |
| | | height: 100px; |
| | | list-style: none; |
| | | padding: 0; |
| | | margin: 0; |
| | | font-size: 15px; |
| | | overflow-y: auto; |
| | | } |
| | | .todo-list { |
| | | height: 100px; |
| | | list-style: none; |
| | | padding: 0; |
| | | margin: 0; |
| | | font-size: 15px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .todo-list li { |
| | | border-radius: 8px; |
| | | margin-bottom: 12px; |
| | | padding: 8px 20px; |
| | | height: 74px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | background: rgba(225, 227, 250, 0.62); |
| | | } |
| | | |
| | | .todo-title { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | position: relative; |
| | | } |
| | | |
| | | .todo-title::before { |
| | | content: ''; |
| | | /* å¿
éï¼è¡¨ç¤ºè¿éæä¸ä¸ªå
容 */ |
| | | position: absolute; |
| | | left: -10px; |
| | | /* å®ä½å°å·¦ä¾§ */ |
| | | top: 50%; |
| | | /* åç´å±
ä¸ */ |
| | | transform: translateY(-50%); |
| | | /* å¾®è°åç´å±
ä¸ */ |
| | | width: 6px; |
| | | /* åçç´å¾ */ |
| | | height: 6px; |
| | | /* åçç´å¾ */ |
| | | background: #498CEB; |
| | | border-radius: 50%; |
| | | /* 让å
¶åæåå½¢ */ |
| | | } |
| | | |
| | | .todo-division { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | } |
| | | |
| | | .todo-time { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | } |
| | | |
| | | .todo-meta { |
| | | color: #888; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .dashboard-row { |
| | | display: flex; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .main-panel { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .section-title { |
| | | position: relative; |
| | | font-size: 18px; |
| | | color: #333; |
| | | padding-left: 10px; |
| | | margin-bottom: 10px; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .section-title::before { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 4px; |
| | | content: ''; |
| | | width: 4px; |
| | | height: 18px; |
| | | background-color: #002FA7; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .contract-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 20px; |
| | | height: 90px; |
| | | background: rgba(245, 245, 245, 0.59); |
| | | width: 100%; |
| | | border-radius: 10px; |
| | | padding: 10px 30px; |
| | | } |
| | | |
| | | .contract-summary { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .contract-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .contract-name { |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #050505; |
| | | } |
| | | |
| | | .contract-meta { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | gap: 80px; |
| | | } |
| | | |
| | | .main-amount { |
| | | font-size: 24px; |
| | | color: rgba(51, 50, 50, 0.85); |
| | | } |
| | | |
| | | .up { |
| | | color: #e57373; |
| | | } |
| | | |
| | | .contract-list { |
| | | margin-top: 16px; |
| | | font-size: 14px; |
| | | color: #666; |
| | | list-style: none; |
| | | padding: 0; |
| | | height: 190px; |
| | | overflow-y: auto; |
| | | width: 460px; |
| | | } |
| | | |
| | | .line { |
| | | position: relative; |
| | | width: 230px; |
| | | } |
| | | |
| | | .line::after { |
| | | content: ''; |
| | | position: absolute; |
| | | right: 2px; |
| | | top: 0; |
| | | bottom: 0; |
| | | width: 1px; |
| | | background-color: #C9C5C5; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .contract-list li { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .quality-cards { |
| | | display: flex; |
| | | gap: 12px; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .quality-card { |
| | | border-radius: 8px; |
| | | padding: 15px 10px 10px 50px; |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: rgba(0, 0, 0, 0.67); |
| | | width: 236px; |
| | | height: 49px; |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .quality-card.one { |
| | | background-image: url("../assets/images/yuancailiao.png"); |
| | | } |
| | | |
| | | .quality-card.two { |
| | | background-image: url("../assets/images/guocheng.png"); |
| | | } |
| | | |
| | | .quality-card.three { |
| | | background-image: url("../assets/images/chuchang.png"); |
| | | |
| | | } |
| | | |
| | | .quality-card span { |
| | | color: #4fc3f7; |
| | | font-weight: bold; |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | .chart { |
| | | width: 100%; |
| | | height: 220px; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .process-panel { |
| | | padding-bottom: 10px; |
| | | } |
| | | |
| | | .process-panel__header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .process-panel__body { |
| | | display: flex; |
| | | gap: 24px; |
| | | align-items: stretch; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .process-panel__chart { |
| | | flex: 1; |
| | | min-width: 0; |
| | | padding: 6px 0; |
| | | } |
| | | |
| | | .process-panel__aside { |
| | | width: 260px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .process-legend { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | align-items: flex-start; |
| | | padding: 8px 6px; |
| | | } |
| | | |
| | | .process-legend__item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | font-size: 13px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | } |
| | | |
| | | .dot { |
| | | width: 10px; |
| | | height: 10px; |
| | | border-radius: 2px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .dot-blue { |
| | | background: #1E5BFF; |
| | | } |
| | | |
| | | .dot-yellow { |
| | | background: #F7B500; |
| | | } |
| | | .todo-list li { |
| | | border-radius: 8px; |
| | | margin-bottom: 12px; |
| | | padding: 8px 20px; |
| | | height: 74px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | background: rgba(225, 227, 250, 0.62); |
| | | } |
| | | |
| | | .dot-teal { |
| | | background: #19C6C6; |
| | | } |
| | | .todo-title { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | position: relative; |
| | | } |
| | | |
| | | .process-card { |
| | | background: rgba(245, 247, 250, 0.9); |
| | | border-radius: 10px; |
| | | padding: 16px 16px; |
| | | } |
| | | .todo-title::before { |
| | | content: ""; |
| | | /* å¿
éï¼è¡¨ç¤ºè¿éæä¸ä¸ªå
容 */ |
| | | position: absolute; |
| | | left: -10px; |
| | | /* å®ä½å°å·¦ä¾§ */ |
| | | top: 50%; |
| | | /* åç´å±
ä¸ */ |
| | | transform: translateY(-50%); |
| | | /* å¾®è°åç´å±
ä¸ */ |
| | | width: 6px; |
| | | /* åçç´å¾ */ |
| | | height: 6px; |
| | | /* åçç´å¾ */ |
| | | background: #498ceb; |
| | | border-radius: 50%; |
| | | /* 让å
¶åæåå½¢ */ |
| | | } |
| | | |
| | | .process-card--name { |
| | | background: rgba(235, 242, 255, 1); |
| | | color: #1E5BFF; |
| | | font-weight: 800; |
| | | font-size: 14px; |
| | | } |
| | | .todo-division { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | } |
| | | |
| | | .process-card__label { |
| | | font-size: 13px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | margin-bottom: 10px; |
| | | } |
| | | .todo-time { |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: #000000; |
| | | } |
| | | |
| | | .process-card__value { |
| | | font-size: 24px; |
| | | font-weight: 800; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | .todo-meta { |
| | | color: #888; |
| | | font-size: 13px; |
| | | } |
| | | |
| | | .process-card__value .unit { |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | color: rgba(0, 0, 0, 0.45); |
| | | margin-left: 6px; |
| | | } |
| | | .dashboard-row { |
| | | display: flex; |
| | | gap: 20px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | @media (max-width: 1200px) { |
| | | .process-panel__body { |
| | | .main-panel { |
| | | background: #fff; |
| | | border-radius: 12px; |
| | | padding: 20px; |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .process-panel__aside { |
| | | .section-title { |
| | | position: relative; |
| | | font-size: 18px; |
| | | color: #333; |
| | | padding-left: 10px; |
| | | margin-bottom: 10px; |
| | | font-weight: 700; |
| | | } |
| | | |
| | | .section-title::before { |
| | | position: absolute; |
| | | left: 0; |
| | | top: 4px; |
| | | content: ""; |
| | | width: 4px; |
| | | height: 18px; |
| | | background-color: #002fa7; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .contract-info { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 20px; |
| | | height: 90px; |
| | | background: rgba(245, 245, 245, 0.59); |
| | | width: 100%; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | border-radius: 10px; |
| | | padding: 10px 30px; |
| | | } |
| | | |
| | | .contract-summary { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .contract-card { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | } |
| | | |
| | | .contract-name { |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #050505; |
| | | } |
| | | |
| | | .contract-meta { |
| | | display: flex; |
| | | align-items: center; |
| | | width: 100%; |
| | | gap: 80px; |
| | | } |
| | | |
| | | .main-amount { |
| | | font-size: 24px; |
| | | color: rgba(51, 50, 50, 0.85); |
| | | } |
| | | |
| | | .up { |
| | | color: #e57373; |
| | | } |
| | | |
| | | .contract-list { |
| | | margin-top: 16px; |
| | | font-size: 14px; |
| | | color: #666; |
| | | list-style: none; |
| | | padding: 0; |
| | | height: 190px; |
| | | overflow-y: auto; |
| | | width: 460px; |
| | | } |
| | | |
| | | .line { |
| | | position: relative; |
| | | width: 230px; |
| | | } |
| | | |
| | | .line::after { |
| | | content: ""; |
| | | position: absolute; |
| | | right: 2px; |
| | | top: 0; |
| | | bottom: 0; |
| | | width: 1px; |
| | | background-color: #c9c5c5; |
| | | border-radius: 2px; |
| | | } |
| | | |
| | | .contract-list li { |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .quality-cards { |
| | | display: flex; |
| | | gap: 12px; |
| | | margin-bottom: 12px; |
| | | } |
| | | |
| | | .quality-card { |
| | | border-radius: 8px; |
| | | padding: 15px 10px 10px 50px; |
| | | font-weight: 400; |
| | | font-size: 12px; |
| | | color: rgba(0, 0, 0, 0.67); |
| | | width: 236px; |
| | | height: 49px; |
| | | background-size: cover; |
| | | background-position: center; |
| | | background-repeat: no-repeat; |
| | | } |
| | | |
| | | .quality-card.one { |
| | | background-image: url("../assets/images/yuancailiao.png"); |
| | | } |
| | | |
| | | .quality-card.two { |
| | | background-image: url("../assets/images/guocheng.png"); |
| | | } |
| | | |
| | | .quality-card.three { |
| | | background-image: url("../assets/images/chuchang.png"); |
| | | } |
| | | |
| | | .quality-card span { |
| | | color: #4fc3f7; |
| | | font-weight: bold; |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | .chart { |
| | | width: 100%; |
| | | height: 220px; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .process-panel { |
| | | padding-bottom: 10px; |
| | | } |
| | | |
| | | .process-panel__header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | |
| | | .process-panel__body { |
| | | display: flex; |
| | | gap: 24px; |
| | | align-items: stretch; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | .process-panel__chart { |
| | | flex: 1; |
| | | min-width: 0; |
| | | padding: 6px 0; |
| | | } |
| | | |
| | | .process-panel__aside { |
| | | width: 260px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .process-legend { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | align-items: flex-start; |
| | | padding: 8px 6px; |
| | | } |
| | | |
| | | .process-legend__item { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | font-size: 13px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | } |
| | | |
| | | .dot { |
| | | width: 10px; |
| | | height: 10px; |
| | | border-radius: 2px; |
| | | display: inline-block; |
| | | } |
| | | |
| | | .dot-blue { |
| | | background: #1e5bff; |
| | | } |
| | | |
| | | .dot-yellow { |
| | | background: #f7b500; |
| | | } |
| | | |
| | | .dot-teal { |
| | | background: #19c6c6; |
| | | } |
| | | |
| | | .process-card { |
| | | flex: 1; |
| | | min-width: 220px; |
| | | background: rgba(245, 247, 250, 0.9); |
| | | border-radius: 10px; |
| | | padding: 16px 16px; |
| | | } |
| | | } |
| | | |
| | | .process-selection-wrapper { |
| | | max-height: 400px; |
| | | overflow-y: auto; |
| | | padding: 10px; |
| | | } |
| | | .process-card--name { |
| | | background: rgba(235, 242, 255, 1); |
| | | color: #1e5bff; |
| | | font-weight: 800; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .process-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); |
| | | gap: 12px; |
| | | } |
| | | .process-card__label { |
| | | font-size: 13px; |
| | | color: rgba(0, 0, 0, 0.55); |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | :deep(.el-checkbox.is-bordered) { |
| | | margin-left: 0 !important; |
| | | width: 100%; |
| | | } |
| | | .process-card__value { |
| | | font-size: 24px; |
| | | font-weight: 800; |
| | | color: rgba(0, 0, 0, 0.8); |
| | | } |
| | | |
| | | .process-card__value .unit { |
| | | font-size: 12px; |
| | | font-weight: 600; |
| | | color: rgba(0, 0, 0, 0.45); |
| | | margin-left: 6px; |
| | | } |
| | | |
| | | @media (max-width: 1200px) { |
| | | .process-panel__body { |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .process-panel__aside { |
| | | width: 100%; |
| | | flex-direction: row; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .process-card { |
| | | flex: 1; |
| | | min-width: 220px; |
| | | } |
| | | } |
| | | |
| | | .process-selection-wrapper { |
| | | max-height: 400px; |
| | | overflow-y: auto; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .process-grid { |
| | | display: grid; |
| | | grid-template-columns: repeat(auto-fill, minmax(130px, 1fr)); |
| | | gap: 12px; |
| | | } |
| | | |
| | | :deep(.el-checkbox.is-bordered) { |
| | | margin-left: 0 !important; |
| | | width: 100%; |
| | | } |
| | | </style> |
| | |
| | | prefix-icon="Search" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºåç±»åï¼"> |
| | | <el-select v-model="searchForm.supplierType" |
| | | placeholder="è¯·éæ©" |
| | | style="width: 220px" |
| | | clearable |
| | | @change="handleQuery"> |
| | | <el-option label="对å
¬" |
| | | value="1" /> |
| | | <el-option label="对ç§" |
| | | value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æï¼"> |
| | | <el-date-picker v-model="searchForm.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | |
| | | <div style="display: flex;justify-content: flex-end;margin-bottom: 20px;"> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢å°è´¦</el-button> |
| | | <el-button type="primary" plain @click="handleImport">导å
¥</el-button> |
| | | <el-button type="primary" |
| | | plain |
| | | @click="handleImport">导å
¥</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | |
| | | prop="availableQuality" /> |
| | | <el-table-column label="éè´§æ°é" |
| | | prop="returnQuality" /> |
| | | |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" /> |
| | | prop="taxRate" |
| | | v-if="props.row.supplierType === 1" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" /> |
| | | :formatter="formattedNumber" |
| | | v-if="props.row.supplierType === 1" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | :formatter="formattedNumber" |
| | | v-if="props.row.supplierType === 1" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" /> |
| | | :formatter="formattedNumber" |
| | | v-if="props.row.supplierType === 1" /> |
| | | <el-table-column label="åä»·ï¼å¯¹ç§ï¼" |
| | | prop="unitPrice" |
| | | :formatter="formattedNumber" |
| | | v-if="props.row.supplierType === 2" /> |
| | | <el-table-column label="æ»ä»·ï¼å¯¹ç§ï¼" |
| | | prop="totalPrice" |
| | | :formatter="formattedNumber" |
| | | v-if="props.row.supplierType === 2" /> |
| | | </el-table> |
| | | </template> |
| | | </el-table-column> |
| | |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="éå®ååå·" |
| | | prop="salesContractNo" |
| | | width="160" |
| | | width="160" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºååç§°" |
| | | prop="supplierName" |
| | | width="160" |
| | | width="160" |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ä¾åºåç±»å" |
| | | prop="supplierType" |
| | | width="100" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ scope.row.supplierType === 1 ? '对å
¬' : '对ç§' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="项ç®åç§°" |
| | | prop="projectName" |
| | | width="320" |
| | |
| | | width="100" |
| | | show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="getApprovalStatusType(scope.row.approvalStatus)" |
| | | size="small"> |
| | | <el-tag :type="getApprovalStatusType(scope.row.approvalStatus)" |
| | | size="small"> |
| | | {{ approvalStatusText[scope.row.approvalStatus] || 'æªç¥ç¶æ' }} |
| | | </el-tag> |
| | | </template> |
| | |
| | | @pagination="paginationChange" /> |
| | | </div> |
| | | <FormDialog v-model="dialogFormVisible" |
| | | :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" |
| | | :width="'70%'" |
| | | :operation-type="operationType" |
| | | @close="closeDia" |
| | | @confirm="submitForm" |
| | | @cancel="closeDia"> |
| | | :title="operationType === 'add' ? 'æ°å¢éè´å°è´¦é¡µé¢' : 'ç¼è¾éè´å°è´¦é¡µé¢'" |
| | | :width="'70%'" |
| | | :operation-type="operationType" |
| | | @close="closeDia" |
| | | @confirm="submitForm" |
| | | @cancel="closeDia"> |
| | | <el-form :model="form" |
| | | label-width="140px" |
| | | label-position="top" |
| | |
| | | <el-select v-model="form.supplierId" |
| | | placeholder="è¯·éæ©" |
| | | filterable |
| | | clearable> |
| | | clearable |
| | | @change="handleSupplierChange"> |
| | | <el-option v-for="item in supplierList" |
| | | :key="item.id" |
| | | :label="item.supplierName" |
| | | :value="item.id" >{{item.supplierName + '---' + item.supplierType}}</el-option> |
| | | :value="item.id">{{item.supplierName + '---' + (item.supplierType === 1 ? item.taxpayerIdentificationNum || 'æ ' : '对ç§')}}</el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | <template #label> |
| | | <div style="display: flex; align-items: center; justify-content: space-between; width: 100%;"> |
| | | <span>审æ¹äººéæ©ï¼</span> |
| | | <el-button type="primary" size="small" @click="addApproverNode" icon="Plus">æ°å¢èç¹</el-button> |
| | | <el-button type="primary" |
| | | size="small" |
| | | @click="addApproverNode" |
| | | icon="Plus">æ°å¢èç¹</el-button> |
| | | </div> |
| | | </template> |
| | | <div class="approver-nodes-container"> |
| | | <div |
| | | v-for="(node, index) in approverNodes" |
| | | :key="node.id" |
| | | class="approver-node-item" |
| | | > |
| | | <div v-for="(node, index) in approverNodes" |
| | | :key="node.id" |
| | | class="approver-node-item"> |
| | | <div class="approver-node-header"> |
| | | <span class="approver-node-label">审æ¹èç¹ {{ index + 1 }}</span> |
| | | <el-button |
| | | v-if="approverNodes.length > 1" |
| | | type="danger" |
| | | size="small" |
| | | text |
| | | @click="removeApproverNode(index)" |
| | | icon="Delete" |
| | | >å é¤</el-button> |
| | | <el-button v-if="approverNodes.length > 1" |
| | | type="danger" |
| | | size="small" |
| | | text |
| | | @click="removeApproverNode(index)" |
| | | icon="Delete">å é¤</el-button> |
| | | </div> |
| | | <el-select |
| | | v-model="node.userId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | filterable |
| | | style="width: 100%;" |
| | | > |
| | | <el-option |
| | | v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" |
| | | /> |
| | | <el-select v-model="node.userId" |
| | | placeholder="è¯·éæ©å®¡æ¹äºº" |
| | | filterable |
| | | style="width: 100%;"> |
| | | <el-option v-for="user in userList" |
| | | :key="user.userId" |
| | | :label="user.nickName" |
| | | :value="user.userId" /> |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | |
| | | <el-form-item label="产åä¿¡æ¯ï¼" |
| | | prop="entryDate"> |
| | | <el-button type="primary" |
| | | v-if="currentSupplierType" |
| | | @click="openProductForm('add')">æ·»å </el-button> |
| | | <el-button plain |
| | | type="danger" |
| | |
| | | :value="item.templateName"> |
| | | <div style="display: flex; justify-content: space-between; align-items: center;"> |
| | | <span>{{ item.templateName }}</span> |
| | | <el-icon |
| | | v-if="item.id" |
| | | class="delete-icon" |
| | | @click.stop="handleDeleteTemplate(item)" |
| | | style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;"> |
| | | <el-icon v-if="item.id" |
| | | class="delete-icon" |
| | | @click.stop="handleDeleteTemplate(item)" |
| | | style="cursor: pointer; color: #f56c6c; font-size: 14px; margin-left: 8px;"> |
| | | <Delete /> |
| | | </el-icon> |
| | | </div> |
| | |
| | | show-overflow-tooltip /> |
| | | <el-table-column label="ç¨ç(%)" |
| | | prop="taxRate" |
| | | width="80" /> |
| | | width="80" |
| | | v-if="currentSupplierType === 1" /> |
| | | <el-table-column label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | width="150" |
| | | v-if="currentSupplierType === 1" /> |
| | | <el-table-column label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | width="150" |
| | | v-if="currentSupplierType === 1" /> |
| | | <el-table-column label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" /> |
| | | width="150" |
| | | v-if="currentSupplierType === 1" /> |
| | | <el-table-column label="åä»·ï¼å¯¹ç§ï¼" |
| | | prop="unitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | v-if="currentSupplierType === 2" /> |
| | | <el-table-column label="æ»ä»·ï¼å¯¹ç§ï¼" |
| | | prop="totalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | v-if="currentSupplierType === 2" /> |
| | | <el-table-column label="æ¯å¦è´¨æ£" |
| | | prop="isChecked" |
| | | width="150"> |
| | |
| | | </el-form> |
| | | </FormDialog> |
| | | <!-- 导å
¥å¼¹çª --> |
| | | <FormDialog |
| | | v-model="importUpload.open" |
| | | :title="importUpload.title" |
| | | :width="'600px'" |
| | | @close="importUpload.open = false" |
| | | @confirm="submitImportFile" |
| | | @cancel="importUpload.open = false" |
| | | > |
| | | <el-upload |
| | | ref="importUploadRef" |
| | | :limit="1" |
| | | accept=".xlsx,.xls" |
| | | :action="importUpload.url" |
| | | :headers="importUpload.headers" |
| | | :before-upload="importUpload.beforeUpload" |
| | | :on-success="importUpload.onSuccess" |
| | | :on-error="importUpload.onError" |
| | | :on-progress="importUpload.onProgress" |
| | | :on-change="importUpload.onChange" |
| | | :auto-upload="false" |
| | | drag |
| | | > |
| | | <FormDialog v-model="importUpload.open" |
| | | :title="importUpload.title" |
| | | :width="'600px'" |
| | | @close="importUpload.open = false" |
| | | @confirm="submitImportFile" |
| | | @cancel="importUpload.open = false"> |
| | | <el-upload ref="importUploadRef" |
| | | :limit="1" |
| | | accept=".xlsx,.xls" |
| | | :action="importUpload.url" |
| | | :headers="importUpload.headers" |
| | | :before-upload="importUpload.beforeUpload" |
| | | :on-success="importUpload.onSuccess" |
| | | :on-error="importUpload.onError" |
| | | :on-progress="importUpload.onProgress" |
| | | :on-change="importUpload.onChange" |
| | | :auto-upload="false" |
| | | drag> |
| | | <i class="el-icon-upload"></i> |
| | | <div class="el-upload__text"> |
| | | å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em> |
| | |
| | | <template #tip> |
| | | <div class="el-upload__tip"> |
| | | ä»
æ¯æ xls/xlsxï¼å¤§å°ä¸è¶
è¿ 10MBã |
| | | <el-button link type="primary" @click="downloadTemplate">ä¸è½½å¯¼å
¥æ¨¡æ¿</el-button> |
| | | <el-button link |
| | | type="primary" |
| | | @click="downloadTemplate">ä¸è½½å¯¼å
¥æ¨¡æ¿</el-button> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | </FormDialog> |
| | | <FormDialog v-model="productFormVisible" |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | :width="'40%'" |
| | | :operation-type="productOperationType" |
| | | @close="closeProductDia" |
| | | @confirm="submitProduct" |
| | | @cancel="closeProductDia"> |
| | | :title="productOperationType === 'add' ? 'æ°å¢äº§å' : 'ç¼è¾äº§å'" |
| | | :width="'40%'" |
| | | :operation-type="productOperationType" |
| | | @close="closeProductDia" |
| | | @confirm="submitProduct" |
| | | @cancel="closeProductDia"> |
| | | <el-form :model="productForm" |
| | | label-width="140px" |
| | | label-position="top" |
| | | :rules="productRules" |
| | | :rules="getProductRules()" |
| | | ref="productFormRef"> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ç¨ç(%)ï¼" |
| | | prop="taxRate"> |
| | | prop="taxRate" |
| | | v-if="currentSupplierType === 1"> |
| | | <el-select v-model="productForm.taxRate" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" |
| | | prop="taxInclusiveUnitPrice"> |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ°éï¼" |
| | | prop="quantity"> |
| | | <el-input-number :step="0.1" |
| | |
| | | style="width: 100%" |
| | | v-model="productForm.quantity" |
| | | placeholder="请è¾å
¥" |
| | | @change="currentSupplierType === 1 ? mathNum() : mathNumPrivate()" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨åä»·(å
)ï¼" |
| | | prop="taxInclusiveUnitPrice" |
| | | v-if="currentSupplierType === 1"> |
| | | <el-input-number v-model="productForm.taxInclusiveUnitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNum" /> |
| | | </el-form-item> |
| | | <el-form-item label="åä»·ï¼å¯¹ç§ï¼ï¼" |
| | | prop="unitPrice" |
| | | v-else> |
| | | <el-input-number v-model="productForm.unitPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="mathNumPrivate" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxInclusiveTotalPrice"> |
| | | prop="taxInclusiveTotalPrice" |
| | | v-if="currentSupplierType === 1"> |
| | | <el-input-number v-model="productForm.taxInclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | |
| | | style="width: 100%" |
| | | @change="reverseMathNum('taxInclusiveTotalPrice')" /> |
| | | </el-form-item> |
| | | <el-form-item label="æ»ä»·ï¼å¯¹ç§ï¼ï¼" |
| | | prop="totalPrice" |
| | | v-else> |
| | | <el-input-number v-model="productForm.totalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" |
| | | @change="reverseMathNumPrivate('totalPrice')" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col v-if="currentSupplierType === 2" |
| | | :span="12"> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" |
| | | prop="warnNum"> |
| | | <el-input-number v-model="productForm.warnNum" |
| | | :precision="2" |
| | | :step="0.1" |
| | | :min="0" |
| | | clearable |
| | | style="width: 100%" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="ä¸å«ç¨æ»ä»·(å
)ï¼" |
| | | prop="taxExclusiveTotalPrice"> |
| | | prop="taxExclusiveTotalPrice" |
| | | v-if="currentSupplierType === 1"> |
| | | <el-input-number v-model="productForm.taxExclusiveTotalPrice" |
| | | :precision="2" |
| | | :step="0.1" |
| | |
| | | <el-row :gutter="30"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="å票类åï¼" |
| | | prop="invoiceType"> |
| | | prop="invoiceType" |
| | | v-if="currentSupplierType === 1"> |
| | | <el-select v-model="productForm.invoiceType" |
| | | placeholder="è¯·éæ©" |
| | | clearable> |
| | |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-col v-if="currentSupplierType === 1" |
| | | :span="12"> |
| | | <el-form-item label="åºåé¢è¦æ°éï¼" |
| | | prop="warnNum"> |
| | | <el-input-number v-model="productForm.warnNum" |
| | |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | <FileListDialog |
| | | ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | title="éä»¶å表" |
| | | /> |
| | | <FileListDialog ref="fileListRef" |
| | | v-model="fileListDialogVisible" |
| | | title="éä»¶å表" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { Search, Delete } from "@element-plus/icons-vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FormDialog from '@/components/Dialog/FormDialog.vue'; |
| | | import FileListDialog from '@/components/Dialog/FileListDialog.vue'; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import FileListDialog from "@/components/Dialog/FileListDialog.vue"; |
| | | import { |
| | | getSalesLedgerWithProducts, |
| | | addOrUpdateSalesLedgerProduct, |
| | |
| | | const salesContractList = ref([]); |
| | | const supplierList = ref([]); |
| | | const tableLoading = ref(false); |
| | | const currentSupplierType = ref(null); // è·è¸ªå½åéæ©çä¾åºåç±»å |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | |
| | | const addApproverNode = () => { |
| | | approverNodes.value.push({ id: nextApproverId++, userId: null }); |
| | | }; |
| | | const removeApproverNode = (index) => { |
| | | const removeApproverNode = index => { |
| | | approverNodes.value.splice(index, 1); |
| | | }; |
| | | |
| | | // 订å审æ¹ç¶ææ¾ç¤ºææ¬ |
| | | // å¤çä¾åºåéæ©åå |
| | | const handleSupplierChange = async supplierId => { |
| | | const selectedSupplier = supplierList.value.find( |
| | | item => item.id === supplierId |
| | | ); |
| | | if (selectedSupplier) { |
| | | // åªæå½å½åä¾åºåç±»åä¸ä¸º null ä¸åçååæ¶ï¼ææ¸
空产å表 |
| | | // è¿æ ·å¨ç¼è¾æ¶å è½½æ°æ®åè°ç¨è¯¥å½æ°ä¸ä¼æ¸
ç©ºäº§åæ°æ® |
| | | if ( |
| | | currentSupplierType.value !== null && |
| | | currentSupplierType.value !== selectedSupplier.supplierType |
| | | ) { |
| | | productData.value = []; |
| | | } |
| | | currentSupplierType.value = selectedSupplier.supplierType; |
| | | } else { |
| | | currentSupplierType.value = null; |
| | | productData.value = []; |
| | | } |
| | | await getTemplateList(); |
| | | }; |
| | | const approvalStatusText = { |
| | | 1: "å¾
å®¡æ ¸", |
| | | 2: "审æ¹ä¸", |
| | |
| | | }; |
| | | |
| | | // è·å审æ¹ç¶ææ ç¾ç±»å |
| | | const getApprovalStatusType = (status) => { |
| | | const getApprovalStatusType = status => { |
| | | const typeMap = { |
| | | 1: "info", // å¾
å®¡æ ¸ - ç°è² |
| | | 2: "warning", // 审æ¹ä¸ - æ©è² |
| | | 3: "success", // 审æ¹éè¿ - ç»¿è² |
| | | 4: "danger", // 审æ¹å¤±è´¥ - çº¢è² |
| | | 1: "info", // å¾
å®¡æ ¸ - ç°è² |
| | | 2: "warning", // 审æ¹ä¸ - æ©è² |
| | | 3: "success", // 审æ¹éè¿ - ç»¿è² |
| | | 4: "danger", // 审æ¹å¤±è´¥ - çº¢è² |
| | | }; |
| | | return typeMap[status] || ""; |
| | | }; |
| | |
| | | form.value.paymentMethod = matchedTemplate.paymentMethod; |
| | | } |
| | | // æ¨¡æ¿æ°æ®ä¸ç产ååæ®µæ¯ productListï¼éè¦è½¬æ¢ä¸º productData |
| | | productData.value = matchedTemplate.productList || matchedTemplate.productData || []; |
| | | productData.value = |
| | | matchedTemplate.productList || matchedTemplate.productData || []; |
| | | } else { |
| | | // æªå¹é
å°å·²ææ¨¡æ¿ï¼è§ä¸ºæ°æ¨¡æ¿ |
| | | currentTemplateId.value = null; |
| | |
| | | entryDate: null, // å½å
¥æ¥æ |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | supplierType: "", // ä¾åºåç±»å |
| | | }, |
| | | form: { |
| | | purchaseContractNumber: "", |
| | |
| | | }, |
| | | }); |
| | | const { productForm, productRules } = toRefs(productFormData); |
| | | const getProductRules = () => { |
| | | const baseRules = { |
| | | productId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | productModelId: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | unit: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | quantity: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | warnNum: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | isChecked: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }; |
| | | |
| | | if (currentSupplierType.value === 1) { |
| | | // 对å
¬ä¾åºåéè¦éªè¯çåæ®µ |
| | | return { |
| | | ...baseRules, |
| | | taxInclusiveUnitPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxRate: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | taxInclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | taxExclusiveTotalPrice: [ |
| | | { required: true, message: "请è¾å
¥", trigger: "blur" }, |
| | | ], |
| | | invoiceType: [{ required: true, message: "è¯·éæ©", trigger: "change" }], |
| | | }; |
| | | } else if (currentSupplierType.value === 2) { |
| | | // 对ç§ä¾åºåéè¦éªè¯çåæ®µ |
| | | return { |
| | | ...baseRules, |
| | | unitPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | totalPrice: [{ required: true, message: "请è¾å
¥", trigger: "blur" }], |
| | | }; |
| | | } else { |
| | | return baseRules; |
| | | } |
| | | }; |
| | | const upload = reactive({ |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/file/upload", |
| | |
| | | url: import.meta.env.VITE_APP_BASE_API + "/purchase/ledger/import", |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | isUploading: false, |
| | | beforeUpload: (file) => { |
| | | beforeUpload: file => { |
| | | const isExcel = file.name.endsWith(".xlsx") || file.name.endsWith(".xls"); |
| | | const isLt10M = file.size / 1024 / 1024 < 10; |
| | | if (!isExcel) { |
| | |
| | | |
| | | // ä¸è½½å¯¼å
¥æ¨¡æ¿ï¼å¦å端路å¾ä¸åï¼å¯å¨æ¤å¤è°æ´ï¼ |
| | | const downloadTemplate = () => { |
| | | proxy.download("/purchase/ledger/exportTemplate", {}, "éè´å°è´¦å¯¼å
¥æ¨¡æ¿.xlsx"); |
| | | proxy.download( |
| | | "/purchase/ledger/exportTemplate", |
| | | {}, |
| | | "éè´å°è´¦å¯¼å
¥æ¨¡æ¿.xlsx" |
| | | ); |
| | | }; |
| | | |
| | | const submitImportFile = () => { |
| | |
| | | // æ£æ¥æ¯å¦æäº§åæ°æ® |
| | | if (!productData.value || productData.value.length === 0) { |
| | | ElMessage({ |
| | | message: '请å
æ·»å 产åä¿¡æ¯', |
| | | type: 'warning', |
| | | message: "请å
æ·»å 产åä¿¡æ¯", |
| | | type: "warning", |
| | | }); |
| | | return; |
| | | } |
| | |
| | | .filter(node => node.userId) |
| | | .map(node => node.userId) |
| | | .join(","); |
| | | |
| | | |
| | | let params = { |
| | | productData: proxy.HaveJson(productData.value), |
| | | supplierId: form.value.supplierId, |
| | |
| | | approveUserIds: approveUserIds, |
| | | templateName: templateName.value.trim(), |
| | | }; |
| | | console.log("template params ===>", params, "currentTemplateId:", currentTemplateId.value); |
| | | console.log( |
| | | "template params ===>", |
| | | params, |
| | | "currentTemplateId:", |
| | | currentTemplateId.value |
| | | ); |
| | | |
| | | // 妿 currentTemplateId æå¼ï¼è¯´æå½åæ¯âç¼è¾å·²ææ¨¡æ¿â â è°ç¨æ´æ°æ¥å£ |
| | | // å¦åä¸ºâæ°å»ºæ¨¡æ¿â â è°ç¨æ°å¢æ¥å£ |
| | |
| | | ...params, |
| | | }); |
| | | } else { |
| | | res = await addPurchaseTemplate(params); |
| | | res = await addPurchaseTemplate({ |
| | | ...params, |
| | | templateType: currentSupplierType.value, |
| | | }); |
| | | } |
| | | |
| | | if (res && res.code === 200) { |
| | |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeChildrenTable = param => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | [ |
| | | // æ£æ¥æ¯å¦ææ°æ®ï¼ä»¥åæ°æ®çä¾åºåç±»å |
| | | const hasData = param && param.data && param.data.length > 0; |
| | | const supplierType = hasData ? param.data[0].supplierType : null; |
| | | |
| | | // æ ¹æ®ä¾åºåç±»åç¡®å®è¦å计çåæ®µ |
| | | const fields = [ |
| | | "ticketsNum", |
| | | "ticketsAmount", |
| | | "futureTickets", |
| | | "futureTicketsAmount", |
| | | ]; |
| | | |
| | | if (supplierType === 1) { |
| | | // 对å
¬ä¾åºå |
| | | fields.unshift( |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | "ticketsNum", |
| | | "ticketsAmount", |
| | | "futureTickets", |
| | | "futureTicketsAmount", |
| | | ], |
| | | { |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | } |
| | | ); |
| | | "taxExclusiveTotalPrice" |
| | | ); |
| | | } else if (supplierType === 2) { |
| | | // 对ç§ä¾åºå |
| | | fields.unshift("unitPrice", "totalPrice"); |
| | | } |
| | | |
| | | return proxy.summarizeTable(param, fields, { |
| | | ticketsNum: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | futureTickets: { noDecimal: true }, // ä¸ä¿çå°æ° |
| | | }); |
| | | }; |
| | | const paginationChange = obj => { |
| | | page.current = obj.page; |
| | |
| | | const res = await productList({ salesLedgerId: row.id, type: 2 }); |
| | | const index = tableData.value.findIndex(item => item.id === row.id); |
| | | if (index > -1) { |
| | | tableData.value[index].children = res.data || []; |
| | | // 为åè¡¨æ ¼æ°æ®æ·»å ä¾åºåç±»åä¿¡æ¯ |
| | | const children = (res.data || []).map(item => ({ |
| | | ...item, |
| | | supplierType: row.supplierType, // ä»ç¶è¡è·åä¾åºåç±»å |
| | | })); |
| | | tableData.value[index].children = children; |
| | | expandedRowKeys.value.push(row.id); |
| | | } |
| | | } catch (error) { |
| | |
| | | }; |
| | | // å表åè®¡æ¹æ³ |
| | | const summarizeProTable = param => { |
| | | return proxy.summarizeTable(param, [ |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice", |
| | | ]); |
| | | const fields = []; |
| | | if (currentSupplierType.value === 1) { |
| | | fields.push( |
| | | "taxInclusiveUnitPrice", |
| | | "taxInclusiveTotalPrice", |
| | | "taxExclusiveTotalPrice" |
| | | ); |
| | | } else if (currentSupplierType.value === 2) { |
| | | fields.push("unitPrice", "totalPrice"); |
| | | } |
| | | return proxy.summarizeTable(param, fields); |
| | | }; |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = async (type, row) => { |
| | |
| | | return; |
| | | } |
| | | } |
| | | |
| | | await getTemplateList(); |
| | | currentSupplierType.value = null; |
| | | |
| | | operationType.value = type; |
| | | form.value = {}; |
| | | productData.value = []; |
| | |
| | | form.value.entryDate = getCurrentDate(); |
| | | |
| | | if (type === "add") { |
| | | await getTemplateList(); |
| | | // æ°å¢æ¶çæéè´ååå· |
| | | try { |
| | | const purchaseNoRes = await createPurchaseNo(); |
| | |
| | | const approverIds = purchaseRes.approveUserIds.split(","); |
| | | approverNodes.value = approverIds.map((id, index) => ({ |
| | | id: index + 1, |
| | | userId: Number(id) |
| | | userId: Number(id), |
| | | })); |
| | | nextApproverId = approverIds.length + 1; |
| | | } |
| | | // 设置å½åä¾åºåç±»å |
| | | if (form.value.supplierId) { |
| | | handleSupplierChange(form.value.supplierId); |
| | | } |
| | | } catch (error) { |
| | | console.error("å è½½éè´å°è´¦æ°æ®å¤±è´¥:", error); |
| | |
| | | proxy.$modal.msgError("请为ææå®¡æ¹èç¹éæ©å®¡æ¹äººï¼"); |
| | | return; |
| | | } |
| | | const approveUserIds = approverNodes.value.map(node => node.userId).join(","); |
| | | |
| | | const approveUserIds = approverNodes.value |
| | | .map(node => node.userId) |
| | | .join(","); |
| | | |
| | | if (productData.value.length > 0) { |
| | | // æ°å¢æ¶ï¼éè¦ä»æ¯ä¸ªäº§å对象ä¸å é¤ id åæ®µ |
| | | let processedProductData = productData.value; |
| | |
| | | } |
| | | |
| | | // æ°å¢æ¶ä¸ä¼ éid |
| | | const submitData = { ...form.value }; |
| | | const submitData = { |
| | | ...form.value, |
| | | purchaseType: currentSupplierType.value, |
| | | }; |
| | | if (operationType.value === "add") { |
| | | delete submitData.id; |
| | | } |
| | |
| | | const openProductForm = async (type, row, index) => { |
| | | productOperationType.value = type; |
| | | productOperationIndex.value = index; |
| | | productForm.value = {}; |
| | | productForm.value = { |
| | | productId: "", |
| | | productCategory: "", |
| | | productModelId: "", |
| | | specificationModel: "", |
| | | unit: "", |
| | | quantity: "", |
| | | // 对å
¬å段 |
| | | taxInclusiveUnitPrice: "", |
| | | taxRate: "", |
| | | taxInclusiveTotalPrice: "", |
| | | taxExclusiveTotalPrice: "", |
| | | invoiceType: "", |
| | | // 对ç§å段 |
| | | unitPrice: "", |
| | | totalPrice: "", |
| | | // å
Œ
±å段 |
| | | warnNum: "", |
| | | isChecked: true, |
| | | }; |
| | | proxy.resetForm("productFormRef"); |
| | | productFormVisible.value = true; |
| | | |
| | | |
| | | // å
è·å产åé项ï¼ç¡®ä¿æ°æ®å è½½å®æ |
| | | await getProductOptions(); |
| | | |
| | | |
| | | // çå¾
DOM æ´æ° |
| | | await nextTick(); |
| | | |
| | | |
| | | if (type === "edit") { |
| | | // å¤å¶è¡æ°æ® |
| | | productForm.value = { ...row }; |
| | | |
| | | |
| | | // 妿æ¯ä»æ¨¡æ¿å è½½çæ°æ®ï¼å¯è½æ²¡æ productId å productModelId |
| | | // éè¦æ ¹æ® productCategory å specificationModel æ¥æ¥æ¾å¯¹åºç ID |
| | | if (!productForm.value.productId && productForm.value.productCategory) { |
| | |
| | | return nodes[i].value; |
| | | } |
| | | if (nodes[i].children && nodes[i].children.length > 0) { |
| | | const found = findProductIdByCategory(nodes[i].children, categoryName); |
| | | const found = findProductIdByCategory( |
| | | nodes[i].children, |
| | | categoryName |
| | | ); |
| | | if (found) return found; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const productId = findProductIdByCategory(productOptions.value, productForm.value.productCategory); |
| | | |
| | | const productId = findProductIdByCategory( |
| | | productOptions.value, |
| | | productForm.value.productCategory |
| | | ); |
| | | if (productId) { |
| | | productForm.value.productId = productId; |
| | | // è·ååå·å表并çå¾
宿 |
| | | const modelRes = await modelList({ id: productId }); |
| | | modelOptions.value = modelRes; |
| | | |
| | | |
| | | // çå¾
DOM æ´æ° |
| | | await nextTick(); |
| | | |
| | | |
| | | // æ ¹æ® specificationModel æ¥æ¾ productModelId |
| | | if (productForm.value.specificationModel && modelOptions.value.length > 0) { |
| | | if ( |
| | | productForm.value.specificationModel && |
| | | modelOptions.value.length > 0 |
| | | ) { |
| | | const modelItem = modelOptions.value.find( |
| | | item => item.model === productForm.value.specificationModel |
| | | ); |
| | |
| | | } else if (productForm.value.productId) { |
| | | // 妿æ productIdï¼æ£å¸¸å è½½åå·å表 |
| | | await getModels(productForm.value.productId); |
| | | |
| | | |
| | | // çå¾
DOM æ´æ° |
| | | await nextTick(); |
| | | |
| | | |
| | | if (productForm.value.productModelId) { |
| | | getProductModel(productForm.value.productModelId); |
| | | } |
| | | } |
| | | |
| | | |
| | | // æååçå¾
䏿¬¡ DOM æ´æ°ï¼ç¡®ä¿æææ°æ®é½å·²è®¾ç½® |
| | | await nextTick(); |
| | | } |
| | |
| | | }); |
| | | }; |
| | | const submitProductEdit = () => { |
| | | productForm.value.salesLedgerId = currentId.value; |
| | | productForm.value.type = 2; |
| | | addOrUpdateSalesLedgerProduct(productForm.value).then(res => { |
| | | proxy.$modal.msgSuccess("æäº¤æå"); |
| | | closeProductDia(); |
| | | getPurchaseById({ id: currentId.value, type: 2 }).then(res => { |
| | | productData.value = res.productData; |
| | | }); |
| | | }); |
| | | // ç´æ¥ä¿®æ¹æ¬å°æ°æ®ï¼ä¸åè°ç¨æ¥å£ |
| | | if (productOperationType.value === "add") { |
| | | // æ°å¢äº§å |
| | | productData.value.push({ ...productForm.value }); |
| | | } else if (productOperationType.value === "edit") { |
| | | // ç¼è¾äº§å |
| | | if ( |
| | | productOperationIndex.value !== "" && |
| | | productOperationIndex.value !== null |
| | | ) { |
| | | productData.value[productOperationIndex.value] = { ...productForm.value }; |
| | | } |
| | | } |
| | | proxy.$modal.msgSuccess("æä½æå"); |
| | | closeProductDia(); |
| | | }; |
| | | // å é¤äº§å |
| | | const deleteProduct = () => { |
| | |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | if (operationType.value === "add") { |
| | | productSelectedRows.value.forEach(selectedRow => { |
| | | const index = productData.value.findIndex( |
| | | product => product.id === selectedRow.id |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | } |
| | | }); |
| | | } else { |
| | | let ids = []; |
| | | if (productSelectedRows.value.length > 0) { |
| | | ids = productSelectedRows.value.map(item => item.id); |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | delProduct(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | getPurchaseById({ id: currentId.value, type: 2 }).then( |
| | | res => { |
| | | productData.value = res.productData; |
| | | } |
| | | ); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | // ç´æ¥ä»æ¬å°æ°æ®ä¸å é¤ï¼ä¸åè°ç¨æ¥å£ |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | productSelectedRows.value.forEach(selectedRow => { |
| | | const index = productData.value.findIndex( |
| | | product => product.id === selectedRow.id |
| | | ); |
| | | if (index !== -1) { |
| | | productData.value.splice(index, 1); |
| | | } |
| | | }); |
| | | } |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | closeProductDia(); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å
³é产åå¼¹æ¡ |
| | | const closeProductDia = () => { |
| | |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // 对ç§ä¾åºåçä»·æ ¼è®¡ç® |
| | | const mathNumPrivate = () => { |
| | | const { unitPrice, quantity } = productForm.value; |
| | | if (unitPrice && quantity) { |
| | | productForm.value.totalPrice = (unitPrice * quantity).toFixed(2); |
| | | } |
| | | }; |
| | | |
| | | // 对ç§ä¾åºåçååä»·æ ¼è®¡ç® |
| | | const reverseMathNumPrivate = type => { |
| | | const { unitPrice, quantity, totalPrice } = productForm.value; |
| | | if (type === "totalPrice") { |
| | | if (quantity) { |
| | | productForm.value.unitPrice = (totalPrice / quantity).toFixed(2); |
| | | } else if (unitPrice) { |
| | | productForm.value.quantity = (totalPrice / unitPrice).toFixed(2); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // éå®ååéæ©æ¹åæ¹æ³ |
| | | const salesLedgerChange = async row => { |
| | | console.log("row", row); |
| | |
| | | |
| | | // è·å模æ¿ä¿¡æ¯ |
| | | const getTemplateList = async () => { |
| | | let res = await getPurchaseTemplateList(); |
| | | if (res && res.code === 200 && Array.isArray(res.data)) { |
| | | templateList.value = res.data; |
| | | console.log("currentSupplierType.value", currentSupplierType.value); |
| | | if (currentSupplierType.value) { |
| | | let res = await getPurchaseTemplateList({ |
| | | templateType: currentSupplierType.value, |
| | | }); |
| | | if (res && res.code === 200 && Array.isArray(res.data)) { |
| | | templateList.value = res.data; |
| | | } |
| | | } else { |
| | | templateList.value = []; |
| | | } |
| | | }; |
| | | |
| | | // å 餿¨¡æ¿ |
| | | const handleDeleteTemplate = async (item) => { |
| | | const handleDeleteTemplate = async item => { |
| | | if (!item.id) { |
| | | proxy.$modal.msgWarning("æ æ³å é¤è¯¥æ¨¡æ¿"); |
| | | return; |
| | | } |
| | | |
| | | |
| | | try { |
| | | await ElMessageBox.confirm( |
| | | `ç¡®å®è¦å 餿¨¡æ¿"${item.templateName}"åï¼`, |
| | |
| | | type: "warning", |
| | | } |
| | | ); |
| | | |
| | | |
| | | const res = await delPurchaseTemplate([item.id]); |
| | | if (res && res.code === 200) { |
| | | ElMessage({ |
| | |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | |
| | | // 审æ¹äººèç¹å®¹å¨æ ·å¼ |
| | | .approver-nodes-container { |
| | | display: flex; |
| | |
| | | border-radius: 4px; |
| | | border: 1px solid #e4e7ed; |
| | | } |
| | | |
| | | |
| | | .approver-node-item { |
| | | flex: 0 0 calc(33.333% - 12px); |
| | | min-width: 200px; |
| | |
| | | border-radius: 4px; |
| | | border: 1px solid #dcdfe6; |
| | | transition: all 0.3s; |
| | | |
| | | |
| | | &:hover { |
| | | border-color: #409eff; |
| | | box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1); |
| | | } |
| | | } |
| | | |
| | | |
| | | .approver-node-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | |
| | | .approver-node-label { |
| | | font-size: 13px; |
| | | font-weight: 500; |
| | | color: #606266; |
| | | } |
| | | |
| | | |
| | | @media (max-width: 1200px) { |
| | | .approver-node-item { |
| | | flex: 0 0 calc(50% - 8px); |
| | | } |
| | | } |
| | | |
| | | |
| | | @media (max-width: 768px) { |
| | | .approver-node-item { |
| | | flex: 0 0 100%; |
| | | } |
| | | } |
| | | |
| | | |
| | | // å é¤å¾æ æ ·å¼ |
| | | .delete-icon { |
| | | transition: all 0.3s; |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-row :gutter="16" class="content-row"> |
| | | <!-- 左侧å°è´¦ + é¡¶é¨çé --> |
| | | <el-col :xs="24" :sm="24" :md="24" :lg="8" :xl="8" class="left-col"> |
| | | <div class="left-panel"> |
| | | <div class="left-header"> |
| | | <el-form :model="searchForm" inline> |
| | | <el-form-item prop="dateType"> |
| | | <el-radio-group v-model="searchForm.dateType" size="small" @change="handleDateTypeChange"> |
| | | <el-radio-button label="day">æ¥</el-radio-button> |
| | | <el-radio-button label="month">æ</el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | |
| | | <el-form-item label="æ¥æï¼" prop="dateRange"> |
| | | <el-date-picker |
| | | v-model="searchForm.dateRange" |
| | | :type="searchForm.dateType === 'day' ? 'date' : 'daterange'" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 200px" |
| | | @change="handleDateRangeChange" |
| | | /> |
| | | <div class="app-container"> |
| | | <el-row :gutter="16" |
| | | class="content-row"> |
| | | <!-- 左侧å°è´¦ + é¡¶é¨çé --> |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="24" |
| | | :lg="8" |
| | | :xl="8" |
| | | class="left-col"> |
| | | <div class="left-panel"> |
| | | <div class="left-header"> |
| | | <el-form :model="searchForm" |
| | | inline> |
| | | <el-form-item prop="dateType"> |
| | | <el-radio-group v-model="searchForm.dateType" |
| | | size="small" |
| | | @change="handleDateTypeChange"> |
| | | <el-radio-button label="day">æ¥</el-radio-button> |
| | | <el-radio-button label="month">æ</el-radio-button> |
| | | </el-radio-group> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥æï¼" |
| | | prop="dateRange"> |
| | | <el-date-picker v-model="searchForm.dateRange" |
| | | :type="searchForm.dateType === 'day' ? 'date' : 'daterange'" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 200px" |
| | | @change="handleDateRangeChange" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | :column="leftTableColumn" |
| | | :tableData="leftTableData" |
| | | :tableLoading="tableLoading" |
| | | :page="page" |
| | | @row-click="handleLeftRowClick" |
| | | @pagination="pagination"></PIMTable> |
| | | </div> |
| | | </el-col> |
| | | <!-- å³ä¾§æç» --> |
| | | <el-col :xs="24" |
| | | :sm="24" |
| | | :md="24" |
| | | :lg="16" |
| | | :xl="16" |
| | | class="right-col"> |
| | | <div class="right-panel"> |
| | | <el-form inline> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleOut">导åº</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="leftTableColumn" |
| | | :tableData="leftTableData" |
| | | :tableLoading="tableLoading" |
| | | :page="page" |
| | | @row-click="handleLeftRowClick" |
| | | @pagination="pagination" |
| | | ></PIMTable> |
| | | </div> |
| | | </el-col> |
| | | |
| | | <!-- å³ä¾§æç» --> |
| | | <el-col :xs="24" :sm="24" :md="24" :lg="16" :xl="16" class="right-col"> |
| | | <div class="right-panel"> |
| | | |
| | | <el-form inline> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleOut">导åº</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page1" |
| | | :tableLoading="tableLoading1" |
| | | style="margin-right: 20px;" |
| | | @pagination="pagination1" |
| | | ></PIMTable> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page1" |
| | | :tableLoading="tableLoading1" |
| | | style="margin-right: 20px;" |
| | | @pagination="pagination1"></PIMTable> |
| | | </div> |
| | | </el-col> |
| | | </el-row> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {onMounted, ref} from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import {salesLedgerProductionAccountingListProductionDetails, salesLedgerProductionAccountingList} from "@/api/productionManagement/productionCosting.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | import { onMounted, ref } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { |
| | | salesLedgerProductionAccountingListProductionDetails, |
| | | salesLedgerProductionAccountingList, |
| | | } from "@/api/productionManagement/productionCosting.js"; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "çäº§æ¥æ", |
| | | prop: "schedulingDate", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "ç产人", |
| | | prop: "schedulingUserName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "ååå·", |
| | | prop: "salesContractNo", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "productModelName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "process", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "ç产æ°é", |
| | | prop: "quantity", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥æ¶å®é¢", |
| | | prop: "workHours", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥èµ", |
| | | prop: "wages", |
| | | minWidth: 100, |
| | | }, |
| | | ]); |
| | | |
| | | // å·¦ä¾§æ±æ»å°è´¦åï¼ç产人ã产éãå·¥èµãåæ ¼çï¼ |
| | | const leftTableColumn = ref([ |
| | | { |
| | | label: "ç产人", |
| | | prop: "schedulingUserName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "产é", |
| | | prop: "outputNum", |
| | | minWidth: 100, |
| | | |
| | | }, |
| | | { |
| | | label: "å·¥èµ", |
| | | prop: "wages", |
| | | minWidth: 100, |
| | | |
| | | }, |
| | | { |
| | | label: "åæ ¼ç", |
| | | prop: "outputRate", |
| | | minWidth: 100, |
| | | formatData: (val) => { |
| | | if (val == null || val === '') return '-' |
| | | return parseFloat(val).toFixed(2) |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "çäº§æ¥æ", |
| | | prop: "schedulingDate", |
| | | minWidth: 100, |
| | | }, |
| | | }, |
| | | ]); |
| | | { |
| | | label: "ç产人", |
| | | prop: "schedulingUserName", |
| | | minWidth: 100, |
| | | }, |
| | | // { |
| | | // label: "ååå·", |
| | | // prop: "salesContractNo", |
| | | // minWidth: 100, |
| | | // }, |
| | | // { |
| | | // label: "客æ·åç§°", |
| | | // prop: "customerName", |
| | | // minWidth: 100, |
| | | // }, |
| | | { |
| | | label: "产å大类", |
| | | prop: "productName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "productModelName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "åä½", |
| | | prop: "unit", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥åº", |
| | | prop: "process", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "ç产æ°é", |
| | | prop: "quantity", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥æ¶å®é¢", |
| | | prop: "workHours", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥èµ", |
| | | prop: "wages", |
| | | minWidth: 100, |
| | | }, |
| | | ]); |
| | | |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const tableLoading1 = ref(false); |
| | | const leftTableData = ref([]); |
| | | // æ¥ / æ 忢ï¼é»è®¤ææ¥ï¼ |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | // å·¦ä¾§æ±æ»å°è´¦åï¼ç产人ã产éãå·¥èµãåæ ¼çï¼ |
| | | const leftTableColumn = ref([ |
| | | { |
| | | label: "ç产人", |
| | | prop: "schedulingUserName", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "产é", |
| | | prop: "outputNum", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "å·¥èµ", |
| | | prop: "wages", |
| | | minWidth: 100, |
| | | }, |
| | | { |
| | | label: "åæ ¼ç", |
| | | prop: "outputRate", |
| | | minWidth: 100, |
| | | formatData: val => { |
| | | if (val == null || val === "") return "-"; |
| | | return parseFloat(val).toFixed(2); |
| | | }, |
| | | }, |
| | | ]); |
| | | |
| | | const page1 = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const tableLoading1 = ref(false); |
| | | const leftTableData = ref([]); |
| | | // æ¥ / æ 忢ï¼é»è®¤ææ¥ï¼ |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | schedulingUserName: "", |
| | | salesContractNo: "", |
| | | dateType: "day", |
| | | dateRange: dayjs().format("YYYY-MM-DD"), |
| | | entryDate: dayjs().format("YYYY-MM-DD"), |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const page1 = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const data = reactive({ |
| | | searchForm: { |
| | | schedulingUserName: "", |
| | | salesContractNo: "", |
| | | dateType: "day", |
| | | dateRange: dayjs().format("YYYY-MM-DD"), |
| | | entryDate: dayjs().format("YYYY-MM-DD"), |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const pagination1 = (obj) => { |
| | | page1.current = obj.page; |
| | | page1.size = obj.limit; |
| | | getList1(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const handleDateRangeChange = (value) => { |
| | | if (value) { |
| | | if (searchForm.value.dateType === "day") { |
| | | searchForm.value.entryDate = value; |
| | | const pagination1 = obj => { |
| | | page1.current = obj.page; |
| | | page1.size = obj.limit; |
| | | getList1(); |
| | | }; |
| | | |
| | | const handleDateRangeChange = value => { |
| | | if (value) { |
| | | if (searchForm.value.dateType === "day") { |
| | | searchForm.value.entryDate = value; |
| | | } else { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | } |
| | | } else { |
| | | searchForm.value.entryDateStart = dayjs(value[0]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs(value[1]).format("YYYY-MM-DD"); |
| | | searchForm.value.entryDate = undefined; |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | reloadData(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | |
| | | salesLedgerProductionAccountingList(params) |
| | | .then(res => { |
| | | const records = res.data.records || []; |
| | | leftTableData.value = records; |
| | | page.total = res.data.total || 0; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const getList1 = () => { |
| | | tableLoading1.value = true; |
| | | const params = { ...page1, ...searchForm.value }; |
| | | salesLedgerProductionAccountingListProductionDetails(params) |
| | | .then(res => { |
| | | tableData.value = res.data.records || []; |
| | | page1.total = res.data.total || 0; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading1.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // æå»ºå·¦ä¾§æ±æ»å°è´¦ï¼æçäº§äººæ±æ»äº§éãå·¥èµçï¼ |
| | | const buildLeftTableData = records => { |
| | | const map = {}; |
| | | records.forEach(item => { |
| | | const key = item.schedulingUserName || "æªç¥"; |
| | | if (!map[key]) { |
| | | map[key] = { |
| | | id: key, |
| | | schedulingUserName: key, |
| | | finishedNum: 0, |
| | | wages: 0, |
| | | qualifiedRate: item.qualifiedRate ?? null, |
| | | }; |
| | | } |
| | | map[key].finishedNum += Number(item.finishedNum || 0); |
| | | map[key].wages += Number(item.wages || 0); |
| | | if (item.qualifiedRate != null) { |
| | | map[key].qualifiedRate = item.qualifiedRate; |
| | | } |
| | | }); |
| | | leftTableData.value = Object.values(map); |
| | | }; |
| | | |
| | | // 左侧æ¥/æåæ¢ |
| | | const handleDateTypeChange = value => { |
| | | // è¿éåªä½ä¸ºç鿡件çä¸é¨åï¼ç´æ¥éæ°æ¥è¯¢å表 |
| | | if (value === "day") { |
| | | searchForm.value.entryDate = dayjs().format("YYYY-MM-DD"); |
| | | searchForm.value.dateRange = searchForm.value.entryDate; |
| | | } else { |
| | | searchForm.value.entryDateStart = dayjs() |
| | | .startOf("month") |
| | | .format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs().endOf("month").format("YYYY-MM-DD"); |
| | | searchForm.value.dateRange = [ |
| | | searchForm.value.entryDateStart, |
| | | searchForm.value.entryDateEnd, |
| | | ]; |
| | | } |
| | | |
| | | } else { |
| | | searchForm.value.entryDate = undefined; |
| | | searchForm.value.entryDateStart = undefined; |
| | | searchForm.value.entryDateEnd = undefined; |
| | | } |
| | | reloadData() |
| | | }; |
| | | reloadData(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | const params = { ...searchForm.value, ...page }; |
| | | const reloadData = () => { |
| | | page.current = 1; |
| | | page1.current = 1; |
| | | getList(); |
| | | tableData.value = []; |
| | | }; |
| | | |
| | | salesLedgerProductionAccountingList(params).then((res) => { |
| | | const records = res.data.records || []; |
| | | leftTableData.value = records; |
| | | page.total = res.data.total || 0; |
| | | }).finally(() => { |
| | | tableLoading.value = false; |
| | | }) |
| | | // ç¹å»å·¦ä¾§è¡ï¼å·å³ä¾§æç»ï¼æçäº§äººè¿æ»¤ï¼ |
| | | const handleLeftRowClick = row => { |
| | | searchForm.value.schedulingUserName = row.schedulingUserName || ""; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page1.current = 1; |
| | | getList1(); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download( |
| | | "/salesLedger/productionAccounting/export", |
| | | {}, |
| | | "çäº§æ ¸ç®.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | }; |
| | | |
| | | const getList1 = () => { |
| | | tableLoading1.value = true; |
| | | const params = { ...page1, ...searchForm.value }; |
| | | salesLedgerProductionAccountingListProductionDetails(params).then((res) => { |
| | | tableData.value = res.data.records || [];; |
| | | page1.total = res.data.total || 0; |
| | | }).finally(() => { |
| | | tableLoading1.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // æå»ºå·¦ä¾§æ±æ»å°è´¦ï¼æçäº§äººæ±æ»äº§éãå·¥èµçï¼ |
| | | const buildLeftTableData = (records) => { |
| | | const map = {}; |
| | | records.forEach((item) => { |
| | | const key = item.schedulingUserName || "æªç¥"; |
| | | if (!map[key]) { |
| | | map[key] = { |
| | | id: key, |
| | | schedulingUserName: key, |
| | | finishedNum: 0, |
| | | wages: 0, |
| | | qualifiedRate: item.qualifiedRate ?? null, |
| | | }; |
| | | } |
| | | map[key].finishedNum += Number(item.finishedNum || 0); |
| | | map[key].wages += Number(item.wages || 0); |
| | | if (item.qualifiedRate != null) { |
| | | map[key].qualifiedRate = item.qualifiedRate; |
| | | } |
| | | }); |
| | | leftTableData.value = Object.values(map); |
| | | }; |
| | | |
| | | // 左侧æ¥/æåæ¢ |
| | | const handleDateTypeChange = (value) => { |
| | | // è¿éåªä½ä¸ºç鿡件çä¸é¨åï¼ç´æ¥éæ°æ¥è¯¢å表 |
| | | if (value === "day") { |
| | | searchForm.value.entryDate = dayjs().format("YYYY-MM-DD"); |
| | | searchForm.value.dateRange = searchForm.value.entryDate |
| | | } else { |
| | | searchForm.value.entryDateStart = dayjs().startOf("month").format("YYYY-MM-DD"); |
| | | searchForm.value.entryDateEnd = dayjs().endOf("month").format("YYYY-MM-DD"); |
| | | searchForm.value.dateRange = [searchForm.value.entryDateStart, searchForm.value.entryDateEnd] |
| | | } |
| | | |
| | | reloadData() |
| | | }; |
| | | |
| | | const reloadData = () => { |
| | | page.current = 1; |
| | | page1.current = 1; |
| | | getList(); |
| | | tableData.value = [] |
| | | } |
| | | |
| | | // ç¹å»å·¦ä¾§è¡ï¼å·å³ä¾§æç»ï¼æçäº§äººè¿æ»¤ï¼ |
| | | const handleLeftRowClick = (row) => { |
| | | searchForm.value.schedulingUserName = row.schedulingUserName || ""; |
| | | handleQuery(); |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page1.current = 1; |
| | | getList1(); |
| | | }; |
| | | |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/salesLedger/productionAccounting/export", {}, "çäº§æ ¸ç®.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .content-row { |
| | | width: 100%; |
| | | } |
| | | .content-row { |
| | | width: 100%; |
| | | } |
| | | |
| | | .content-row .left-col, |
| | | .content-row .right-col { |
| | | margin-bottom: 16px; |
| | | } |
| | | .content-row .left-col, |
| | | .content-row .right-col { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .left-panel, |
| | | .right-panel { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | min-width: 0; |
| | | } |
| | | .left-panel, |
| | | .right-panel { |
| | | display: flex; |
| | | flex-direction: column; |
| | | gap: 10px; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .left-header { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | .left-header { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .left-title { |
| | | font-size: 16px; |
| | | color: #ffffff; |
| | | } |
| | | .left-title { |
| | | font-size: 16px; |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .header-filters { |
| | | display: flex; |
| | | align-items: center; |
| | | flex: 1; |
| | | justify-content: flex-end; |
| | | gap: 8px; |
| | | } |
| | | .header-filters { |
| | | display: flex; |
| | | align-items: center; |
| | | flex: 1; |
| | | justify-content: flex-end; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search_title { |
| | | color: #ffffff; |
| | | } |
| | | .search_title { |
| | | color: #ffffff; |
| | | } |
| | | |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | .ml10 { |
| | | margin-left: 10px; |
| | | } |
| | | </style> |
| | |
| | | style="width: 160px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item label="ååå·:"> |
| | | <!-- <el-form-item label="ååå·:"> |
| | | <el-input v-model="searchForm.salesContractNo" |
| | | placeholder="请è¾å
¥" |
| | | clearable |
| | | prefix-icon="Search" |
| | | style="width: 160px;" |
| | | @change="handleQuery" /> |
| | | </el-form-item> |
| | | </el-form-item> --> |
| | | <el-form-item label="产ååç§°:"> |
| | | <el-input v-model="searchForm.productCategory" |
| | | placeholder="请è¾å
¥" |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <div> |
| | | <el-button type="primary" @click="isShowNewModal = true">æ°å¢</el-button> |
| | | <el-button type="danger" @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" |
| | | @click="isShowNewModal = true">æ°å¢</el-button> |
| | | <el-button type="danger" |
| | | @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="pagination"> |
| | | <template #completionStatus="{ row }"> |
| | | <el-progress |
| | | :percentage="toProgressPercentage(row?.completionStatus)" |
| | | :color="progressColor(toProgressPercentage(row?.completionStatus))" |
| | | :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" |
| | | /> |
| | | <el-progress :percentage="toProgressPercentage(row?.completionStatus)" |
| | | :color="progressColor(toProgressPercentage(row?.completionStatus))" |
| | | :status="toProgressPercentage(row?.completionStatus) >= 100 ? 'success' : ''" /> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <new-product-order v-if="isShowNewModal" |
| | | v-model:visible="isShowNewModal" |
| | | @completed="handleQuery" /> |
| | | v-model:visible="isShowNewModal" |
| | | @completed="handleQuery" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | productOrderListPage, |
| | | listProcessRoute, |
| | | bindingRoute, |
| | | listProcessBom, delProductOrder, |
| | | listProcessBom, |
| | | delProductOrder, |
| | | } from "@/api/productionManagement/productionOrder.js"; |
| | | import { listMain as getOrderProcessRouteMain } from "@/api/productionManagement/productProcessRoute.js"; |
| | | import {fileDel} from "@/api/financialManagement/revenueManagement.js"; |
| | | import { fileDel } from "@/api/financialManagement/revenueManagement.js"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | const NewProductOrder = defineAsyncComponent(() => import("@/views/productionManagement/productionOrder/New.vue")); |
| | | const NewProductOrder = defineAsyncComponent(() => |
| | | import("@/views/productionManagement/productionOrder/New.vue") |
| | | ); |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | |
| | | { |
| | | label: "ç产订åå·", |
| | | prop: "npsNo", |
| | | width: '120px', |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: '150px', |
| | | }, |
| | | { |
| | | label: "客æ·åç§°", |
| | | prop: "customerName", |
| | | width: '200px', |
| | | }, |
| | | // { |
| | | // label: "éå®ååå·", |
| | | // prop: "salesContractNo", |
| | | // width: "150px", |
| | | // }, |
| | | // { |
| | | // label: "客æ·åç§°", |
| | | // prop: "customerName", |
| | | // width: "200px", |
| | | // }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productCategory", |
| | | width: '120px', |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "è§æ ¼", |
| | | prop: "specificationModel", |
| | | width: '120px', |
| | | width: "120px", |
| | | }, |
| | | { |
| | | label: "å·¥èºè·¯çº¿ç¼å·", |
| | | prop: "processRouteCode", |
| | | width: '200px', |
| | | width: "200px", |
| | | }, |
| | | { |
| | | label: "éæ±æ°é", |
| | |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "äº¤ä»æ¥æ", |
| | | prop: "deliveryDate", |
| | | formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | width: 120, |
| | | }, |
| | | // { |
| | | // label: "äº¤ä»æ¥æ", |
| | | // prop: "deliveryDate", |
| | | // formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""), |
| | | // width: 120, |
| | | // }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | |
| | | |
| | | // æ·»å 表è¡ç±»åæ¹æ³ |
| | | const tableRowClassName = ({ row }) => { |
| | | if (!row.deliveryDate) return ''; |
| | | if (row.isFh) return ''; |
| | | if (!row.deliveryDate) return ""; |
| | | if (row.isFh) return ""; |
| | | |
| | | const diff = row.deliveryDaysDiff; |
| | | if (diff === 15) { |
| | | return 'yellow'; |
| | | return "yellow"; |
| | | } else if (diff === 10) { |
| | | return 'pink'; |
| | | return "pink"; |
| | | } else if (diff === 2) { |
| | | return 'purple'; |
| | | return "purple"; |
| | | } else if (diff < 2) { |
| | | return 'red'; |
| | | return "red"; |
| | | } |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(() => { |
| | | delProductOrder(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .then(() => { |
| | | delProductOrder(ids).then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }).catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/productOrder/export", {...searchForm.value}, "ç产订å.xlsx"); |
| | | proxy.download( |
| | | "/productOrder/export", |
| | | { ...searchForm.value }, |
| | | "ç产订å.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .search_form{ |
| | | align-items: start; |
| | | } |
| | | .search_form { |
| | | align-items: start; |
| | | } |
| | | |
| | | ::v-deep .yellow { |
| | | background-color: #FAF0DE; |
| | | } |
| | | ::v-deep .yellow { |
| | | background-color: #faf0de; |
| | | } |
| | | |
| | | ::v-deep .pink { |
| | | background-color: #FAE1DE; |
| | | } |
| | | ::v-deep .pink { |
| | | background-color: #fae1de; |
| | | } |
| | | |
| | | ::v-deep .red { |
| | | background-color: #f80202; |
| | | } |
| | | ::v-deep .red { |
| | | background-color: #f80202; |
| | | } |
| | | |
| | | ::v-deep .purple{ |
| | | background-color: #F4DEFA; |
| | | } |
| | | ::v-deep .purple { |
| | | background-color: #f4defa; |
| | | } |
| | | </style> |
| | |
| | | style="width: 100%" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æä½" |
| | | > |
| | | <el-table-column label="æä½"> |
| | | <template #default="scope"> |
| | | <el-button link |
| | | type="primary" |
| | |
| | | prop: "workOrderNo", |
| | | width: 120, |
| | | }, |
| | | { |
| | | label: "éå®ååå·", |
| | | prop: "salesContractNo", |
| | | width: 120, |
| | | }, |
| | | // { |
| | | // label: "éå®ååå·", |
| | | // prop: "salesContractNo", |
| | | // width: 120, |
| | | // }, |
| | | { |
| | | label: "产ååç§°", |
| | | prop: "productName", |
| | |
| | | prop: "unit", |
| | | width: 120, |
| | | }, |
| | | |
| | | |
| | | { |
| | | label: "å建æ¶é´", |
| | | prop: "createTime", |
| | |
| | | :data="salesRecord" |
| | | border |
| | | :row-key="(row) => row.id" |
| | | show-summary |
| | | :summary-method="summarizeSalesTable" |
| | | height="calc(100vh - 18.5em)" |
| | | > |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | |
| | | return summarizeTable; |
| | | }; |
| | | |
| | | // éå®å¾æ¥è¡¨å计ï¼å·²åè´§/æªåè´§ï¼ |
| | | const summarizeSalesTable = (param) => { |
| | | return proxy.summarizeTable( |
| | | param, |
| | | ["shippedQuantity", "unshippedQuantity"], |
| | | { |
| | | shippedQuantity: { noDecimal: false }, |
| | | unshippedQuantity: { noDecimal: false }, |
| | | } |
| | | ); |
| | | }; |
| | | |
| | | const receiptPaymentList = (id) => { |
| | | const param = { |
| | | customerId: id, |