| | |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <div> |
| | | <el-statistic title="借方合计" :value="totalDebit" precision="2" prefix="¥" /> |
| | | <el-statistic title="贷方合计" :value="totalCredit" precision="2" prefix="¥" style="margin-left: 30px;" /> |
| | | <el-statistic title="借方合计" :value="totalDebit" :precision="2" prefix="¥" /> |
| | | <el-statistic title="贷方合计" :value="totalCredit" :precision="2" prefix="¥" style="margin-left: 30px;" /> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="add" icon="Plus">新增凭证</el-button> |
| | | <el-button @click="handleImport" icon="Upload">导入</el-button> |
| | | <el-button @click="handleOut" icon="Download">导出</el-button> |
| | | <!-- <el-button @click="handleImport" icon="Upload">导入</el-button> --> |
| | | <!-- <el-button @click="handleOut" icon="Download">导出</el-button> --> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | |
| | | <span class="label">凭证字:</span> |
| | | <el-select v-model="form.voucherPrefix" :disabled="isViewMode" style="width: 70px;"> |
| | | <el-option label="记" value="记" /> |
| | | <el-option label="现" value="现" /> |
| | | <el-option label="银" value="银" /> |
| | | <el-option label="转" value="转" /> |
| | | <el-option label="收" value="收" /> |
| | | <el-option label="付" value="付" /> |
| | | </el-select> |
| | | <el-input v-model="form.voucherNum" :disabled="isViewMode" style="width: 60px;" /> |
| | | <span class="label" style="margin-left: 5px;">号</span> |
| | |
| | | <span class="label">附件:</span> |
| | | <el-input-number v-model="form.attachmentCount" :disabled="isViewMode" :min="0" :controls="false" style="width: 60px;" /> |
| | | <span class="label" style="margin-left: 5px;">张</span> |
| | | <el-button type="primary" link :disabled="isViewMode" style="margin-left: 10px;">上传文件</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="voucher-table"> |
| | |
| | | @change="(val) => handleSubjectChange(val, rowIndex)" |
| | | @focus="selectRow(rowIndex)" |
| | | /> |
| | | <div class="subject-name">{{ entry.subjectName }}</div> |
| | | <!-- <div class="subject-name">{{ entry.subjectName }}</div> --> |
| | | </td> |
| | | <!-- 借方11列 --> |
| | | <template v-if="editingCell.row === rowIndex && editingCell.type === 'debit'"> |
| | | <td colspan="11" class="debit-input-cell"> |
| | | <el-input-number ref="amountInputRef" v-model="entry.debit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" /> |
| | | <el-input-number ref="amountInputRef" v-model="entry.debit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" :value-on-clear="undefined" size="small" @blur="finishEdit" class="full-width-input" /> |
| | | </td> |
| | | </template> |
| | | <template v-else> |
| | |
| | | <!-- 贷方11列 --> |
| | | <template v-if="editingCell.row === rowIndex && editingCell.type === 'credit'"> |
| | | <td colspan="11" class="credit-input-cell"> |
| | | <el-input-number ref="amountInputRef" v-model="entry.credit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" size="small" @blur="finishEdit" class="full-width-input" /> |
| | | <el-input-number ref="amountInputRef" v-model="entry.credit" :disabled="isViewMode" :min="0" :precision="2" :controls="false" :value-on-clear="undefined" size="small" @blur="finishEdit" class="full-width-input" /> |
| | | </td> |
| | | </template> |
| | | <template v-else> |
| | |
| | | </el-select> |
| | | </div> |
| | | </div> |
| | | <!-- 编辑模式:使用 AttachmentUploadFile 上传组件 --> |
| | | <div class="voucher-attachment-upload" v-if="!isViewMode"> |
| | | <div class="attachment-label">附件上传:</div> |
| | | <AttachmentUploadFile |
| | | v-model:fileList="form.attachments" |
| | | :disabled="isViewMode" |
| | | :limit="10" |
| | | :fileSize="50" |
| | | buttonText="点击上传附件" |
| | | @change="handleAttachmentChange" |
| | | /> |
| | | </div> |
| | | </el-form> |
| | | <!-- 查看模式:展示附件列表(放在 el-form 外面,避免被 disabled) --> |
| | | <div class="voucher-attachment-upload" v-if="isViewMode && form.attachments?.length"> |
| | | <div class="attachment-label">附件列表:</div> |
| | | <el-table :data="form.attachments" border class="attachment-table"> |
| | | <el-table-column label="附件名称" show-overflow-tooltip> |
| | | <template #default="scope"> |
| | | {{ scope.row.originalFilename || scope.row.name || scope.row.fileName || '未命名文件' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column fixed="right" label="操作" width="150" align="center"> |
| | | <template #default="scope"> |
| | | <el-button link type="primary" size="small" @click="previewFile(scope.row)">预览</el-button> |
| | | <el-button link type="primary" size="small" @click="downloadFile(scope.row)">下载</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | <template #footer> |
| | | <div> |
| | |
| | | </div> |
| | | </template> |
| | | </FormDialog> |
| | | <!-- 文件预览组件 --> |
| | | <FilePreview ref="filePreviewRef" /> |
| | | </div> |
| | | </template> |
| | | |
| | |
| | | import { ref, reactive, onMounted, computed, nextTick } from "vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import AttachmentUploadFile from "@/components/AttachmentUpload/file/index.vue"; |
| | | import FileList from "@/components/Dialog/FileList.vue"; |
| | | import FilePreview from "@/components/filePreview/index.vue"; |
| | | import download from "@/plugins/download.js"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { userListNoPageByTenantId } from "@/api/system/user"; |
| | | import { listAccountSubject } from "@/api/financialManagement/accountSubject"; |
| | |
| | | const isEdit = ref(false); |
| | | const currentId = ref(null); |
| | | const isViewMode = computed(() => dialogMode.value === "view"); |
| | | const filePreviewRef = ref(null); |
| | | |
| | | const fallbackSubjectTree = [ |
| | | { subjectCode: "1001", subjectName: "库存现金", balanceDirection: "借方", children: [] }, |
| | |
| | | subjectName: "", |
| | | balanceDirection: "", |
| | | summary: "", |
| | | debit: 0, |
| | | credit: 0, |
| | | debit: undefined, |
| | | credit: undefined, |
| | | }); |
| | | |
| | | const createDefaultForm = () => ({ |
| | |
| | | voucherNum: "", |
| | | voucherDate: "", |
| | | attachmentCount: 0, |
| | | attachments: [], |
| | | entries: [createEmptyEntry(), createEmptyEntry()], |
| | | creator: getDefaultCreator(), |
| | | remark: "", |
| | |
| | | form.entries.push(createEmptyEntry()); |
| | | }; |
| | | |
| | | const handleAttachmentChange = (fileList) => { |
| | | form.attachmentCount = fileList?.length || 0; |
| | | }; |
| | | |
| | | // 使用项目封装的 filePreview 组件预览文件 |
| | | const previewFile = (row) => { |
| | | const url = row.previewURL || row.previewUrl || row.url; |
| | | if (url && filePreviewRef.value) { |
| | | filePreviewRef.value.open(url); |
| | | } else { |
| | | ElMessage.warning('文件地址无效,无法预览'); |
| | | } |
| | | }; |
| | | |
| | | // 使用项目封装的 download 插件下载文件 |
| | | const downloadFile = (row) => { |
| | | const url = row.downloadURL || row.downloadUrl || row.url; |
| | | if (url) { |
| | | const filename = row.originalFilename || row.name || row.fileName || 'download'; |
| | | download.byUrl(url, filename); |
| | | } else { |
| | | ElMessage.warning('文件地址无效,无法下载'); |
| | | } |
| | | }; |
| | | |
| | | const selectRow = (index) => { |
| | | selectedRowIndex.value = index; |
| | | }; |
| | |
| | | const { data } = await getVoucherDetail(row.id); |
| | | const detail = data || row; |
| | | const parts = (detail.voucherNo || "").split("-"); |
| | | Object.assign(form, createDefaultForm(), detail, { |
| | | const attachments = detail.storageBlobVOList || detail.storageBlobDTOs || detail.attachments || []; |
| | | Object.assign(form, createDefaultForm(), { |
| | | ...detail, |
| | | voucherPrefix: parts[0] || "记", |
| | | voucherNum: parts[1] || "", |
| | | creator: detail.creator || getDefaultCreator(), |
| | | attachments, |
| | | entries: |
| | | detail.entries?.map(item => ({ |
| | | subjectCode: item.subjectCode || "", |
| | |
| | | remark: form.remark, |
| | | debit: totalDebitEntry.value, |
| | | credit: totalCreditEntry.value, |
| | | storageBlobDTOs: form.attachments || [], |
| | | entries: validEntries.map(entry => ({ |
| | | subjectCode: entry.subjectCode, |
| | | subjectName: entry.subjectName, |
| | |
| | | } |
| | | } |
| | | |
| | | .voucher-attachment-upload { |
| | | margin-top: 15px; |
| | | padding: 0 10px; |
| | | |
| | | .attachment-label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .attachment-table { |
| | | border-radius: 4px; |
| | | } |
| | | } |
| | | |
| | | .voucher-table { |
| | | border: 1px solid #dcdfe6; |
| | | border-right: none; |