PC端和手机端端双端适配

This commit is contained in:
2026-03-14 10:22:48 +08:00
parent cb13784141
commit 5a1923d9ca
92 changed files with 9011 additions and 3149 deletions

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="审批流程"
direction="rtl"
@@ -65,23 +67,48 @@
<el-button @click="dialogVisible = false">关闭</el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" title="审批流程" width="700px" :close-on-press-escape="true" :destroy-on-close="true">
<el-table v-loading="loading" :data="approvalRecords" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="审批层级" align="center" width="100"><template #default="scope">{{ getLevelText(scope.row.approvalLevel) }}</template></el-table-column>
<el-table-column label="申请人" align="center" prop="applicantName" width="100"><template #default="scope">{{ scope.row.applicantName || scope.row.applicant }}</template></el-table-column>
<el-table-column label="审批人" align="center" prop="approverName" width="100"><template #default="scope">{{ scope.row.approverName || scope.row.approver }}</template></el-table-column>
<el-table-column label="审批结果" align="center" width="90"><template #default="scope"><el-tag :type="getStatusTagType(scope.row.approvalResult)" size="small">{{ getApprovalResultText(scope.row.approvalResult) }}</el-tag></template></el-table-column>
<el-table-column label="流程状态" align="center" width="90"><template #default="scope"><el-tag :type="getProcessStatusTagType(scope.row.processStatus)" size="small">{{ getProcessStatusText(scope.row.processStatus) }}</el-tag></template></el-table-column>
<el-table-column label="审批时间" align="center" prop="approvalTime" width="160"><template #default="scope">{{ scope.row.approvalTime ? formatDate(scope.row.approvalTime) : '-' }}</template></el-table-column>
<el-table-column label="审批意见" align="center" prop="comment" min-width="150" />
</el-table>
<el-empty v-if="approvalRecords.length === 0" description="暂无审批记录" />
<template #footer>
<el-button @click="dialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ref, computed } from 'vue'
import { ApprovalRecordApi } from '@/api/erp/approval'
import { formatDate } from '@/utils/formatTime'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const dialogVisible = ref(false)
const loading = ref(false)
const approvalRecords = ref<any[]>([])
const open = async (bizId: string, bizTableName: string) => {
dialogVisible.value = true
loading.value = true
try {
const data = await ApprovalRecordApi.getApprovalRecordListByBiz(bizId, bizTableName)
approvalRecords.value = data
} catch (error) {
console.error('获取审批记录失败', error)
} finally {
loading.value = false
}
}

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="处理审批"
direction="rtl"
@@ -113,6 +115,52 @@
<el-button type="primary" @click="submitForm" :loading="loading">确定</el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" title="处理审批" width="600px" :close-on-press-escape="true" :destroy-on-close="true">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
<el-form-item label="审批记录" prop="approvalRecordId">
<el-select v-model="formData.approvalRecordId" placeholder="请选择待处理的审批记录" filterable clearable style="width: 100%" @change="handleRecordChange">
<el-option v-for="record in pendingRecords" :key="record.id" :label="`第${record.approvalLevel}级审批 - ${record.applicantName || record.applicant}`" :value="record.id">
<div style="display: flex; justify-content: space-between; align-items: center"><span>{{ record.approvalLevel }}级审批</span><el-tag size="small" type="warning">待处理</el-tag></div>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="审批结果" prop="approvalResult">
<el-radio-group v-model="formData.approvalResult">
<el-radio :label="1">通过</el-radio>
<el-radio :label="2">驳回</el-radio>
<el-radio :label="3">转审</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="下一级审批人" prop="nextApprover" v-if="formData.approvalResult === 1 || formData.approvalResult === 3">
<el-select v-model="formData.nextApprover" placeholder="请选择下一级审批人" filterable clearable style="width: 100%">
<el-option v-for="user in userList" :key="user.id" :label="user.nickname" :value="String(user.id)" />
</el-select>
<div style="color: #909399; font-size: 12px; margin-top: 4px">{{ formData.approvalResult === 1 ? '通过时可指定下一级审批人,不指定则流程结束' : '转审时必须指定审批人' }}</div>
</el-form-item>
<el-form-item label="指定原因" prop="assignReason" v-if="formData.approvalResult === 3">
<el-input v-model="formData.assignReason" type="textarea" :rows="2" placeholder="请输入转审原因" />
</el-form-item>
<el-form-item label="审批意见" prop="comment">
<el-input v-model="formData.comment" type="textarea" :rows="3" placeholder="请输入审批意见" />
</el-form-item>
</el-form>
<!-- 审批信息卡片 -->
<div class="pc-process-info" v-if="selectedRecord">
<div class="pc-process-info__title">审批信息</div>
<el-descriptions :column="2" border size="small">
<el-descriptions-item label="申请人">{{ selectedRecord.applicantName || selectedRecord.applicant }}</el-descriptions-item>
<el-descriptions-item label="当前审批人">{{ selectedRecord.approverName || selectedRecord.approver }}</el-descriptions-item>
<el-descriptions-item label="审批层级">{{ selectedRecord.approvalLevel }}</el-descriptions-item>
<el-descriptions-item label="提交时间">{{ formatDate(selectedRecord.createTime) }}</el-descriptions-item>
</el-descriptions>
</div>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
@@ -122,6 +170,10 @@ import * as UserApi from '@/api/system/user'
import type { UserVO } from '@/api/system/user'
import { formatDate } from '@/utils/formatTime'
import { useUserStore } from '@/store/modules/user'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const userStore = useUserStore()
@@ -299,4 +351,17 @@ defineExpose({ open })
height: auto;
padding: 8px 20px;
}
.pc-process-info {
background: #f0f9eb;
border-radius: 8px;
padding: 14px;
border: 1px solid #e1f3d8;
margin-top: 16px;
&__title {
font-size: 14px;
font-weight: 600;
color: #303133;
margin-bottom: 10px;
}
}
</style>

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="提交审批"
direction="rtl"
@@ -40,13 +42,35 @@
<el-button type="primary" @click="submitForm" :loading="loading">确定</el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" title="提交审批" width="500px" :close-on-press-escape="true" :destroy-on-close="true">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
<el-form-item label="下一级审批人" prop="nextApprover">
<el-select v-model="formData.nextApprover" placeholder="请选择下一级审批人" filterable clearable style="width: 100%">
<el-option v-for="user in userList" :key="user.id" :label="user.nickname" :value="String(user.id)" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" type="textarea" :rows="4" placeholder="请输入备注信息" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="loading">确定</el-button>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { ref, reactive, computed } from 'vue'
import { ApprovalRecordApi } from '@/api/erp/approval'
import * as UserApi from '@/api/system/user'
import type { UserVO } from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const dialogVisible = ref(false)

View File

@@ -1,134 +1,78 @@
<template>
<div class="mobile-approved">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-approved">
<div class="mobile-header">
<div class="mobile-header__search">
<el-select
v-model="queryParams.bizTableName"
placeholder="业务类型"
clearable
style="width: 100%"
@change="handleQuery"
>
<el-option
v-for="item in bizTableOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-select v-model="queryParams.bizTableName" placeholder="业务类型" clearable style="width: 100%" @change="handleQuery"><el-option v-for="item in bizTableOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select>
</div>
<div class="mobile-header__actions"><el-button :icon="Filter" circle @click="filterVisible = true" /></div>
</div>
<!-- 卡片列表 -->
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty">
<el-empty description="暂无已审批记录" />
</div>
<div
v-for="item in list"
:key="item.id"
class="mobile-card"
@click="handleViewRecords(item)"
>
<div class="mobile-card__header">
<span class="mobile-card__no">{{ item.bizId }}</span>
<el-tag :type="getResultTagType(item.approvalResult)" size="small">
{{ getApprovalResultText(item.approvalResult) }}
</el-tag>
</div>
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无已审批记录" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleViewRecords(item)">
<div class="mobile-card__header"><span class="mobile-card__no">{{ item.bizId }}</span><el-tag :type="getResultTagType(item.approvalResult)" size="small">{{ getApprovalResultText(item.approvalResult) }}</el-tag></div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">业务类型</span>
<span class="mobile-card__value">{{ getBizTableLabel(item.bizTableName) }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">申请人</span>
<span class="mobile-card__value">{{ item.applicantName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">审批层级</span>
<span class="mobile-card__value">{{ item.approvalLevel }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">审批意见</span>
<span class="mobile-card__value mobile-card__value--ellipsis">{{ item.comment || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">审批时间</span>
<span class="mobile-card__value">{{ formatDate2(item.approvalTime) }}</span>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="info" @click.stop="handleViewRecords(item)">审批记录</el-button>
<div class="mobile-card__row"><span class="mobile-card__label">业务类型</span><span class="mobile-card__value">{{ getBizTableLabel(item.bizTableName) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">申请人</span><span class="mobile-card__value">{{ item.applicantName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">审批层级</span><span class="mobile-card__value">{{ item.approvalLevel }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">审批意见</span><span class="mobile-card__value mobile-card__value--ellipsis">{{ item.comment || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">审批时间</span><span class="mobile-card__value">{{ formatDate2(item.approvalTime) }}</span></div>
</div>
<div class="mobile-card__footer"><el-button size="small" type="info" @click.stop="handleViewRecords(item)">审批记录</el-button></div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-pagination" v-if="total > 0">
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
:page-sizes="[10, 20]"
layout="total, prev, pager, next"
:pager-count="5"
@pagination="getList"
/>
</div>
<!-- 筛选抽屉 -->
<div class="mobile-pagination" v-if="total > 0"><Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" /></div>
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="审批结果" prop="approvalResult">
<el-select
v-model="queryParams.approvalResult"
placeholder="请选择审批结果"
clearable
style="width: 100%"
>
<el-option label="已通过" :value="1" />
<el-option label="已驳回" :value="2" />
<el-option label="已转审" :value="3" />
</el-select>
</el-form-item>
<el-form-item label="审批时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="审批结果" prop="approvalResult"><el-select v-model="queryParams.approvalResult" placeholder="请选择审批结果" clearable style="width: 100%"><el-option label="已通过" :value="1" /><el-option label="已驳回" :value="2" /><el-option label="已转审" :value="3" /></el-select></el-form-item>
<el-form-item label="审批时间" prop="createTime"><el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width: 100%" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
<template #footer><el-button @click="resetQuery">重置</el-button><el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button></template>
</el-drawer>
<!-- 审批记录对话框 -->
<ApprovalRecordsDialog ref="approvalDialogRef" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="业务类型" prop="bizTableName"><el-select v-model="queryParams.bizTableName" placeholder="请选择业务类型" clearable class="!w-240px"><el-option v-for="item in bizTableOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
<el-form-item label="审批结果" prop="approvalResult"><el-select v-model="queryParams.approvalResult" placeholder="请选择审批结果" clearable class="!w-240px"><el-option label="已通过" :value="1" /><el-option label="已驳回" :value="2" /><el-option label="已转审" :value="3" /></el-select></el-form-item>
<el-form-item label="审批时间" prop="createTime"><el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="业务单号" align="center" prop="bizId" min-width="120" />
<el-table-column label="业务类型" align="center" prop="bizTableName" min-width="150"><template #default="scope">{{ getBizTableLabel(scope.row.bizTableName) }}</template></el-table-column>
<el-table-column label="申请人" align="center" prop="applicantName" min-width="100" />
<el-table-column label="审批层级" align="center" prop="approvalLevel" min-width="100"><template #default="scope">{{ scope.row.approvalLevel }}</template></el-table-column>
<el-table-column label="审批结果" align="center" prop="approvalResult" min-width="100"><template #default="scope"><el-tag :type="getResultTagType(scope.row.approvalResult)">{{ getApprovalResultText(scope.row.approvalResult) }}</el-tag></template></el-table-column>
<el-table-column label="审批意见" align="center" prop="comment" min-width="150" />
<el-table-column label="审批时间" align="center" prop="approvalTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column label="操作" align="center" fixed="right" width="120"><template #default="scope"><el-button link type="info" @click="handleViewRecords(scope.row)">审批记录</el-button></template></el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<ApprovalRecordsDialog ref="approvalDialogRef" />
</template>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { ref, onMounted, computed } from 'vue'
import { Filter } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter } from '@/utils/formatTime'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval'
import { ApprovalRecordsDialog } from '@/components/Approval'
import { useUserStore } from '@/store/modules/user'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'ErpApprovalApproved' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const userStore = useUserStore()
const loading = ref(true)
const list = ref<ApprovalRecordVO[]>([])

View File

@@ -1,68 +1,23 @@
<template>
<div class="mobile-pending">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-pending">
<div class="mobile-header">
<div class="mobile-header__search">
<el-select
v-model="queryParams.bizTableName"
placeholder="业务类型"
clearable
style="width: 100%"
@change="handleQuery"
>
<el-option
v-for="item in bizTableOptions"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</div>
<div class="mobile-header__actions">
<el-button :icon="Refresh" circle @click="resetQuery" />
<el-select v-model="queryParams.bizTableName" placeholder="业务类型" clearable style="width: 100%" @change="handleQuery"><el-option v-for="item in bizTableOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select>
</div>
<div class="mobile-header__actions"><el-button :icon="Refresh" circle @click="resetQuery" /></div>
</div>
<!-- 卡片列表 -->
<div class="mobile-list" v-loading="loading">
<div v-if="filteredList.length === 0 && !loading" class="mobile-empty">
<el-empty description="暂无待审批记录" />
</div>
<div
v-for="item in filteredList"
:key="item.id"
class="mobile-card"
@click="handleProcess(item)"
>
<div class="mobile-card__header">
<span class="mobile-card__no">{{ item.bizId }}</span>
<el-tag type="warning" size="small">待审批</el-tag>
</div>
<div v-if="filteredList.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无待审批记录" /></div>
<div v-for="item in filteredList" :key="item.id" class="mobile-card" @click="handleProcess(item)">
<div class="mobile-card__header"><span class="mobile-card__no">{{ item.bizId }}</span><el-tag type="warning" size="small">待审批</el-tag></div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">业务类型</span>
<span class="mobile-card__value">{{ getBizTableLabel(item.bizTableName) }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">申请人</span>
<span class="mobile-card__value">{{ item.applicantName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">审批层级</span>
<span class="mobile-card__value">{{ item.approvalLevel }}</span>
</div>
<div class="mobile-card__row" v-if="item.assignerName">
<span class="mobile-card__label">指定者</span>
<span class="mobile-card__value">{{ item.assignerName }}</span>
</div>
<div class="mobile-card__row" v-if="item.assignReason">
<span class="mobile-card__label">指定原因</span>
<span class="mobile-card__value mobile-card__value--ellipsis">{{ item.assignReason }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">提交时间</span>
<span class="mobile-card__value">{{ formatDate2(item.createTime) }}</span>
</div>
<div class="mobile-card__row"><span class="mobile-card__label">业务类型</span><span class="mobile-card__value">{{ getBizTableLabel(item.bizTableName) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">申请人</span><span class="mobile-card__value">{{ item.applicantName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">审批层级</span><span class="mobile-card__value">{{ item.approvalLevel }}</span></div>
<div class="mobile-card__row" v-if="item.assignerName"><span class="mobile-card__label">指定者</span><span class="mobile-card__value">{{ item.assignerName }}</span></div>
<div class="mobile-card__row" v-if="item.assignReason"><span class="mobile-card__label">指定原因</span><span class="mobile-card__value mobile-card__value--ellipsis">{{ item.assignReason }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">提交时间</span><span class="mobile-card__value">{{ formatDate2(item.createTime) }}</span></div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="handleProcess(item)">处理审批</el-button>
@@ -70,25 +25,49 @@
</div>
</div>
</div>
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
<!-- 审批记录对话框 -->
<ApprovalRecordsDialog ref="approvalDialogRef" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="业务类型" prop="bizTableName"><el-select v-model="queryParams.bizTableName" placeholder="请选择业务类型" clearable class="!w-240px" @change="handleQuery"><el-option v-for="item in bizTableOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="filteredList" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="业务单号" align="center" prop="bizId" min-width="120" />
<el-table-column label="业务类型" align="center" prop="bizTableName" min-width="150"><template #default="scope">{{ getBizTableLabel(scope.row.bizTableName) }}</template></el-table-column>
<el-table-column label="申请人" align="center" prop="applicantName" min-width="100" />
<el-table-column label="审批层级" align="center" prop="approvalLevel" min-width="100"><template #default="scope">{{ scope.row.approvalLevel }}</template></el-table-column>
<el-table-column label="指定者" align="center" prop="assignerName" min-width="100" />
<el-table-column label="指定原因" align="center" prop="assignReason" min-width="150" />
<el-table-column label="提交时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column label="操作" align="center" fixed="right" width="200"><template #default="scope"><el-button link type="primary" @click="handleProcess(scope.row)">处理审批</el-button><el-button link type="info" @click="handleViewRecords(scope.row)">审批记录</el-button></template></el-table-column>
</el-table>
</ContentWrap>
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
<ApprovalRecordsDialog ref="approvalDialogRef" />
</template>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { Refresh } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter } from '@/utils/formatTime'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval'
import { ProcessApprovalDialog, ApprovalRecordsDialog } from '@/components/Approval'
import { useUserStore } from '@/store/modules/user'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'ErpApprovalPending' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const userStore = useUserStore()
const loading = ref(true)
const list = ref<ApprovalRecordVO[]>([])

View File

@@ -1,35 +1,31 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="编码" prop="no">
<el-input v-model="formData.no" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
</el-form-item>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<el-form-item label="名称" prop="name"><el-input v-model="formData.name" placeholder="请输入名称" /></el-form-item>
<el-form-item label="编码" prop="no"><el-input v-model="formData.no" placeholder="请输入编码" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" placeholder="请输入备注" /></el-form-item>
<el-form-item label="状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="排序" prop="sort"><el-input v-model="formData.sort" placeholder="请输入排序" /></el-form-item>
</div>
</el-form>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="名称" prop="name"><el-input v-model="formData.name" placeholder="请输入名称" /></el-form-item>
<el-form-item label="编码" prop="no"><el-input v-model="formData.no" placeholder="请输入编码" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" placeholder="请输入备注" /></el-form-item>
<el-form-item label="状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="排序" prop="sort"><el-input v-model="formData.sort" placeholder="请输入排序" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
@@ -38,12 +34,17 @@
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
/** ERP 结算 表单 */
defineOptions({ name: 'AccountForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -122,3 +123,9 @@ const resetForm = () => {
formRef.value?.resetFields()
}
</script>
<style lang="scss" scoped>
.mobile-form { padding: 12px; }
.mobile-form-section { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-form__footer { position: sticky; bottom: 0; background: #fff; padding: 12px 16px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid #eee; display: flex; justify-content: flex-end; gap: 12px; margin: 12px -12px -12px; .el-button { flex: 1; height: 40px; font-size: 15px; } }
</style>

View File

@@ -1,71 +1,63 @@
<template>
<doc-alert
title="【财务】采购付款、销售收款"
url="https://doc.iocoder.cn/sale/finance-payment-receipt/"
/>
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-account">
<div class="mobile-header">
<div class="mobile-header__search"><el-input v-model="queryParams.name" placeholder="搜索账户名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:account:create']" />
</div>
</div>
<div class="mobile-quick-actions"><el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:account:export']">导出</el-button></div>
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无账户" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="openForm('update', item.id)">
<div class="mobile-card__header">
<span class="mobile-card__name">{{ item.name }}</span>
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row"><span class="mobile-card__label">编码</span><span class="mobile-card__value">{{ item.no || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">备注</span><span class="mobile-card__value">{{ item.remark || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">排序</span><span class="mobile-card__value">{{ item.sort }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">默认</span><el-switch v-model="item.defaultStatus" :active-value="true" :inactive-value="false" @click.stop @change="handleDefaultStatusChange(item)" /></div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:account:update']">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:account:delete']">删除</el-button>
</div>
</div>
</div>
<div class="mobile-pagination" v-if="total > 0"><Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" /></div>
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="名称" prop="name"><el-input v-model="queryParams.name" placeholder="请输入名称" clearable style="width:100%" /></el-form-item>
<el-form-item label="编码" prop="no"><el-input v-model="queryParams.no" placeholder="请输入编码" clearable style="width:100%" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="queryParams.remark" placeholder="请输入备注" clearable style="width:100%" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
</div>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="编码" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入编码"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:account:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:account:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="名称" prop="name"><el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="编码" prop="no"><el-input v-model="queryParams.no" placeholder="请输入编码" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="queryParams.remark" placeholder="请输入备注" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:account:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:account:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="编码" align="center" prop="no" />
@@ -115,29 +107,30 @@
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<AccountForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import AccountForm from './AccountForm.vue'
import { useWindowSize } from '@vueuse/core'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
/** ERP 结算账户 列表 */
defineOptions({ name: 'ErpAccount' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -154,6 +147,7 @@ const queryParams = reactive({
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const filterVisible = ref(false) // 筛选抽屉
/** 查询列表 */
const getList = async () => {
@@ -175,7 +169,13 @@ const handleQuery = () => {
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
queryFormRef.value?.resetFields()
handleQuery()
}
/** 筛选确认 */
const handleFilterConfirm = () => {
filterVisible.value = false
handleQuery()
}
@@ -254,3 +254,22 @@ onMounted(() => {
getList()
})
</script>
<style lang="scss" scoped>
.mobile-account { padding: 12px; background: #f5f5f5; min-height: 100vh; }
.mobile-header { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
.mobile-header__search { flex: 1; }
.mobile-header__actions { display: flex; gap: 4px; }
.mobile-quick-actions { display: flex; gap: 8px; margin-bottom: 12px; }
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-card__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.mobile-card__name { font-weight: 600; font-size: 15px; color: #303133; }
.mobile-card__body { font-size: 13px; }
.mobile-card__row { display: flex; justify-content: space-between; align-items: center; padding: 3px 0; }
.mobile-card__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
.mobile-card__value { color: #606266; text-align: right; }
.mobile-card__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; padding-top: 10px; border-top: 1px solid #f0f0f0; }
.mobile-pagination { margin-top: 12px; display: flex; justify-content: center; :deep(.el-pagination) { flex-wrap: wrap; justify-content: center; } }
</style>

View File

@@ -1,12 +1,37 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="700px">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
v-loading="formLoading"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">银行流水信息</div>
<el-form-item label="交易流水号" prop="transactionNo"><el-input v-model="formData.transactionNo" placeholder="请输入交易流水号" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" placeholder="请选择结算账户" style="width:100%" @change="handleAccountChange"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="账户号" prop="accountNo"><el-input v-model="formData.accountNo" placeholder="请输入账户号" /></el-form-item>
<el-form-item label="交易机构" prop="transactionInstitution"><el-input v-model="formData.transactionInstitution" placeholder="请输入交易机构" /></el-form-item>
<el-form-item label="交易金额" prop="transactionAmount"><el-input-number v-model="formData.transactionAmount" :precision="2" :min="0" placeholder="请输入交易金额" style="width:100%" /></el-form-item>
<el-form-item label="交易类型" prop="transactionType"><el-radio-group v-model="formData.transactionType"><el-radio :value="1">收入</el-radio><el-radio :value="2">支出</el-radio></el-radio-group></el-form-item>
<el-form-item label="交易对手账户" prop="counterpartyAccount"><el-input v-model="formData.counterpartyAccount" placeholder="请输入交易对手账户" /></el-form-item>
<el-form-item label="交易对手户名" prop="counterpartyName"><el-input v-model="formData.counterpartyName" placeholder="请输入交易对手户名" /></el-form-item>
<el-form-item label="交易对手银行" prop="counterpartyBank"><el-input v-model="formData.counterpartyBank" placeholder="请输入交易对手银行" /></el-form-item>
<el-form-item label="操作柜员" prop="operatorTeller"><el-input v-model="formData.operatorTeller" placeholder="请输入操作柜员" /></el-form-item>
<el-form-item label="交易时间" prop="transactionTime"><el-date-picker v-model="formData.transactionTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择交易时间" style="width:100%" /></el-form-item>
<el-form-item label="摘要" prop="summary"><el-input v-model="formData.summary" placeholder="请输入摘要" /></el-form-item>
<el-form-item label="备注信息" prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入备注信息" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="700px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="交易流水号" prop="transactionNo">
@@ -113,12 +138,17 @@
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { BankTransactionApi, BankTransactionVO } from '@/api/erp/finance/bank'
import { AccountApi } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
/** ERP 银行流水 表单 */
defineOptions({ name: 'BankTransactionForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,52 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="900px">
<el-form
ref="formRef"
v-loading="formLoading"
:model="formData"
:rules="formRules"
:disabled="isDetail"
label-width="100px"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" :disabled="isDetail" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="凭证编号" prop="voucherNo"><el-input v-model="formData.voucherNo" disabled placeholder="系统自动生成" /></el-form-item>
<el-form-item v-if="!isDetail" label="制单日期" prop="voucherDate"><el-date-picker v-model="formData.voucherDate" type="date" placeholder="选择制单日期" value-format="YYYY-MM-DD" style="width:100%" /></el-form-item>
<el-form-item label="系统名" prop="systemName"><el-input v-model="formData.systemName" placeholder="请输入系统名" /></el-form-item>
<el-form-item label="摘要" prop="summary"><el-input v-model="formData.summary" placeholder="请输入摘要" @input="syncSummaryToItems" /></el-form-item>
<el-form-item v-if="formType !== 'create'" label="审核状态" prop="status"><dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="formData.status" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="2" placeholder="请输入备注" /></el-form-item>
</div>
<div class="mobile-form__section">
<div class="mobile-form__section-title">凭证明细</div>
<div v-for="(item, index) in formData.items" :key="index" class="mobile-item-card">
<div class="mobile-item-card__header">
<span class="mobile-item-card__index">#{{ index + 1 }}</span>
<span class="mobile-item-card__name">{{ item.subjectName || '未选择科目' }}</span>
<el-button v-if="!isDetail" :disabled="isDetail" @click="removeItem(index)" link type="danger" size="small">删除</el-button>
</div>
<div class="mobile-item-card__body">
<el-form-item label="摘要"><el-input v-model="item.summary" placeholder="请输入摘要" :disabled="isDetail" /></el-form-item>
<el-form-item label="科目名称"><el-tree-select v-model="item.subjectId" :data="subjectTree" :props="{ label: 'name', value: 'id', children: 'children' }" placeholder="请选择科目名称" check-strictly filterable :disabled="isDetail" style="width:100%" @change="(val) => handleSubjectChange(item, val)" /></el-form-item>
<el-form-item label="借方金额"><el-input-number v-model="item.debitAmount" :precision="2" :min="0" :controls="false" placeholder="借方金额" :disabled="isDetail || (item.creditAmount > 0)" style="width:100%" @change="(val) => handleDebitChange(item, val)" /></el-form-item>
<el-form-item label="贷方金额"><el-input-number v-model="item.creditAmount" :precision="2" :min="0" :controls="false" placeholder="贷方金额" :disabled="isDetail || (item.debitAmount > 0)" style="width:100%" @change="(val) => handleCreditChange(item, val)" /></el-form-item>
</div>
</div>
<div class="mobile-item-add" v-if="!isDetail"><el-button @click="addItem" round>+ 添加明细</el-button></div>
<div class="mobile-item-summary">
<div class="mobile-item-summary__row"><span>借方合计</span><span class="text-red-500">{{ formatAmount(debitTotal) }}</span></div>
<div class="mobile-item-summary__row"><span>贷方合计</span><span class="text-blue-500">{{ formatAmount(creditTotal) }}</span></div>
</div>
<el-alert v-if="!isBalanced && formData.items.length > 0" title="借贷不平衡,请检查金额" type="warning" :closable="false" class="mt-10px" />
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button v-if="!isDetail" type="primary" :disabled="formLoading" @click="submitForm" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else v-model="dialogVisible" :title="dialogTitle" width="900px">
<el-form ref="formRef" v-loading="formLoading" :model="formData" :rules="formRules" :disabled="isDetail" label-width="100px">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="凭证编号" prop="voucherNo">
@@ -146,13 +185,18 @@
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import * as BookkeepingVoucherApi from '@/api/erp/finance/bookkeeping'
import { SubjectApi } from '@/api/erp/finance/subject'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'BookkeepingVoucherForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,12 +1,32 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="120px"
v-loading="formLoading"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">会计期间信息</div>
<el-form-item label="期间编码" prop="periodCode"><el-input v-model="formData.periodCode" placeholder="请输入期间编码yyyyMM格式" /></el-form-item>
<el-form-item label="期间名称" prop="periodName"><el-input v-model="formData.periodName" placeholder="请输入期间名称" /></el-form-item>
<el-form-item label="会计年度" prop="fiscalYear"><el-input v-model="formData.fiscalYear" placeholder="请输入会计年度" /></el-form-item>
<el-form-item label="开始日期" prop="startDate"><el-date-picker v-model="formData.startDate" type="date" placeholder="请选择开始日期" value-format="YYYY-MM-DD" style="width:100%" /></el-form-item>
<el-form-item label="结束日期" prop="endDate"><el-date-picker v-model="formData.endDate" type="date" placeholder="请选择结束日期" value-format="YYYY-MM-DD" style="width:100%" /></el-form-item>
<el-form-item label="状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="是否当前期间" prop="isCurrent"><el-switch v-model="formData.isCurrent" active-text="是" inactive-text="否" /></el-form-item>
<el-form-item label="描述" prop="description"><el-input v-model="formData.description" type="textarea" placeholder="请输入描述" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading">
<el-form-item label="期间编码" prop="periodCode">
<el-input v-model="formData.periodCode" placeholder="请输入期间编码yyyyMM格式" />
</el-form-item>
@@ -63,12 +83,17 @@
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { FiscalPeriodApi, FiscalPeriodVO } from '@/api/erp/finance/fiscal-period'
import { useWindowSize } from '@vueuse/core'
/** ERP 会计期间 表单 */
defineOptions({ name: 'FiscalPeriodForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,12 +1,35 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="110px"
v-loading="formLoading"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">发票信息</div>
<el-form-item label="发票日期" prop="invoiceDate"><el-date-picker v-model="formData.invoiceDate" type="date" value-format="x" placeholder="选择发票日期" style="width:100%" /></el-form-item>
<el-form-item label="发票类别" prop="invoiceCategory"><el-select v-model="formData.invoiceCategory" placeholder="请选择发票类别" style="width:100%"><el-option v-for="dict in getStrDictOptions(DICT_TYPE.ERP_FINANCE_INVOICE_INOUT_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item label="发票类型" prop="invoiceType"><el-select v-model="formData.invoiceType" placeholder="请选择发票类型" style="width:100%"><el-option v-for="dict in getStrDictOptions(DICT_TYPE.ERP_FINANCE_INVOICE_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item label="会计科目" prop="accountSubjects" required><el-select v-model="formData.accountSubjects" placeholder="请选择会计科目" style="width:100%"><el-option v-for="dict in getStrDictOptions(DICT_TYPE.ERP_FINANCE_SUBJECT_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item label="发票号码" prop="invoiceNo"><el-input v-model="formData.invoiceNo" placeholder="发票号码" /></el-form-item>
<el-form-item label="发票方" prop="counterpartyName"><el-input v-model="formData.counterpartyName" placeholder="客户/供应商名称" /></el-form-item>
<el-form-item label="金额(不含税)" prop="amountWithoutTax"><el-input v-model="formData.amountWithoutTax" placeholder="不含税金额" /></el-form-item>
<el-form-item label="税率(%)" prop="taxRate"><el-input v-model="formData.taxRate" placeholder="税率 %" /></el-form-item>
<el-form-item label="发票附件" prop="attachment"><UploadFile v-model="formData.attachment" :limit="1" :fileType="['pdf', 'png', 'jpg', 'jpeg']" :fileSize="10" /></el-form-item>
<el-form-item label="发票状态" prop="invoiceStatus"><el-radio-group v-model="formData.invoiceStatus"><el-radio label="待认证">待认证</el-radio><el-radio label="已认证">已认证</el-radio></el-radio-group></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入备注" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px" v-loading="formLoading">
<el-row :gutter="16">
<el-col :span="12">
<!-- <el-form-item label="发票日期" prop="invoiceDate">
@@ -172,15 +195,20 @@
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { InvoiceApi, Invoice } from '@/api/erp/finance/invoice'
import UploadFile from '@/components/UploadFile/src/UploadFile.vue'
import { getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { SubjectApi } from '@/api/erp/finance/subject'
import { useWindowSize } from '@vueuse/core'
/** 财务发票主 表单 */
defineOptions({ name: 'InvoiceForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,12 +1,31 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">应付单信息</div>
<el-form-item label="采购入库订单" prop="purchaseInNo"><el-input v-model="formData.purchaseInNo" readonly placeholder="请选择采购入库订单"><template #append><el-button @click="openPurchaseInSelect"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="应付单号" prop="apoCode"><el-input v-model="formData.apoCode" placeholder="请输入应付单号" /></el-form-item>
<el-form-item label="供应商" prop="supplier"><el-input v-model="formData.supplier" placeholder="请输入供应商" /></el-form-item>
<el-form-item label="单据日期" prop="billDate"><el-date-picker v-model="formData.billDate" type="date" value-format="x" placeholder="选择单据日期" style="width:100%" /></el-form-item>
<el-form-item label="已付金额" prop="paymentPrice"><el-input v-model="formData.paymentPrice" placeholder="请输入已付金额" /></el-form-item>
<el-form-item label="总金额" prop="totalAmount"><el-input v-model="formData.totalAmount" placeholder="请输入总金额" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" placeholder="请输入备注" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="采购入库订单" prop="purchaseInNo">
<el-input v-model="formData.purchaseInNo" readonly placeholder="请选择采购入库订单">
<template #append>
@@ -94,15 +113,20 @@
<PurchaseInPaymentEnableList ref="purchaseInSelectRef" @success="onPurchaseInSelected" />
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { PayableOrderApi, PayableOrder } from '@/api/erp/finance/payableorder'
import PurchaseInPaymentEnableList from '@/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue'
import { PurchaseInVO } from '@/api/erp/purchase/in'
import { formatToDate } from '@/utils/dateUtil'
import { SubjectApi, SubjectVO } from '@/api/erp/finance/subject'
import { useWindowSize } from '@vueuse/core'
/** 应付单 表单 */
defineOptions({ name: 'PayableOrderForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,156 +1,63 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="付款单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="付款时间" prop="paymentTime"><el-date-picker v-model="formData.paymentTime" type="date" value-format="x" placeholder="选择付款时间" style="width:100%" /></el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" style="width:100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="发票" prop="invoiceNo"><el-input v-model="invoiceDisplay" readonly placeholder="请选择发票"><template #append><el-button @click="openInvoiceSelect"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="财务人员" prop="financeUserId"><el-select v-model="formData.financeUserId" clearable filterable placeholder="请选择财务人员" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<div class="mobile-form__section">
<div class="mobile-form__section-title">采购入库退货单</div>
<FinancePaymentItemForm ref="itemFormRef" :supplier-id="formData.supplierId" :items="formData.items" :disabled="disabled" />
</div>
<div class="mobile-form__section">
<div class="mobile-form__section-title">结算信息</div>
<el-form-item label="付款账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="合计付款" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠金额" prop="discountPrice"><el-input-number v-model="formData.discountPrice" controls-position="right" :precision="4" placeholder="请输入优惠金额" style="width:100%" /></el-form-item>
<el-form-item label="实际付款"><el-input disabled v-model="formData.paymentPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
</div>
</el-form>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="付款单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="付款时间" prop="paymentTime">
<el-date-picker
v-model="formData.paymentTime"
type="date"
value-format="x"
placeholder="选择付款时间"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
clearable
filterable
placeholder="请选择供应商"
class="!w-1/1"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发票" prop="invoiceNo">
<el-input v-model="invoiceDisplay" readonly placeholder="请选择发票">
<template #append>
<el-button @click="openInvoiceSelect">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="财务人员" prop="financeUserId">
<el-select
v-model="formData.financeUserId"
clearable
filterable
placeholder="请选择财务人员"
class="!w-1/1"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="1"
placeholder="请输入备注"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
</el-col>
<el-col :span="8"><el-form-item label="付款单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="付款时间" prop="paymentTime"><el-date-picker v-model="formData.paymentTime" type="date" value-format="x" placeholder="选择付款时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" class="!w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="发票" prop="invoiceNo"><el-input v-model="invoiceDisplay" readonly placeholder="请选择发票"><template #append><el-button @click="openInvoiceSelect"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="财务人员" prop="financeUserId"><el-select v-model="formData.financeUserId" clearable filterable placeholder="请选择财务人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<!-- 子表的表单 -->
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="采购入库、退货单" name="item">
<FinancePaymentItemForm
ref="itemFormRef"
:supplier-id="formData.supplierId"
:items="formData.items"
:disabled="disabled"
/>
</el-tab-pane>
<el-tab-pane label="采购入库、退货单" name="item"><FinancePaymentItemForm ref="itemFormRef" :supplier-id="formData.supplierId" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="付款账户" prop="accountId">
<el-select
v-model="formData.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-1/1"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="合计付款" prop="totalPrice">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="优惠金额" prop="discountPrice">
<el-input-number
v-model="formData.discountPrice"
controls-position="right"
:precision="4"
placeholder="请输入优惠金额"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实际付款">
<el-input
disabled
v-model="formData.paymentPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
</el-col>
<el-col :span="8"><el-form-item label="付款账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合计付款" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠金额" prop="discountPrice"><el-input-number v-model="formData.discountPrice" controls-position="right" :precision="4" placeholder="请输入优惠金额" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="实际付款"><el-input disabled v-model="formData.paymentPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled">
</el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
@@ -164,6 +71,7 @@
/>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { FinancePaymentApi, FinancePaymentVO } from '@/api/erp/finance/payment'
import FinancePaymentItemForm from './components/FinancePaymentItemForm.vue'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
@@ -172,10 +80,14 @@ import * as UserApi from '@/api/system/user'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import InvoiceSelectList from '@/views/erp/finance/invoice/components/InvoiceSelectList.vue'
import { Invoice } from '@/api/erp/finance/invoice'
import { useWindowSize } from '@vueuse/core'
/** ERP 付款单表单 */
defineOptions({ name: 'FinancePaymentForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
fetchInvoicePage: (params: any) => Promise<any>
}>()
@@ -330,3 +242,10 @@ const resetForm = () => {
formRef.value?.resetFields()
}
</script>
<style lang="scss" scoped>
.mobile-form { padding: 0 4px; }
.mobile-form__section { background: #fff; border-radius: 10px; padding: 14px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-form__section-title { font-size: 15px; font-weight: 600; color: #303133; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
.mobile-form__footer { position: sticky; bottom: 0; background: #fff; padding: 12px 16px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid #eee; display: flex; justify-content: flex-end; gap: 12px; z-index: 10; margin: 0 -4px; .el-button { flex: 1; height: 40px; font-size: 15px; } }
</style>

View File

@@ -1,13 +1,34 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div v-for="(row, $index) in formData" :key="$index" class="mobile-item-card">
<div class="mobile-item-card__header">
<span class="mobile-item-card__index">#{{ $index + 1 }}</span>
<span class="mobile-item-card__name">{{ row.bizNo || '未选择单据' }}</span>
<el-button :disabled="disabled" @click="handleDelete($index)" link type="danger" size="small">删除</el-button>
</div>
<div class="mobile-item-card__body">
<div class="mobile-item-card__info-row"><span class="mobile-item-card__info-label">应付金额</span><span class="mobile-item-card__info-value">{{ erpPriceInputFormatter(row.totalPrice) }}</span></div>
<div class="mobile-item-card__info-row"><span class="mobile-item-card__info-label">已付金额</span><span class="mobile-item-card__info-value">{{ erpPriceInputFormatter(row.paidPrice) }}</span></div>
<el-form-item label="本次付款" :prop="`${$index}.paymentPrice`"><el-input-number v-model="row.paymentPrice" controls-position="right" :precision="4" style="width:100%" /></el-form-item>
<el-form-item label="备注" :prop="`${$index}.remark`"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item>
</div>
</div>
<div class="mobile-item-summary" v-if="formData.length > 0">
<div class="mobile-item-summary__row"><span>应付合计</span><span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span></div>
<div class="mobile-item-summary__row"><span>已付合计</span><span>{{ erpPriceInputFormatter(summaryData.paidPrice) }}</span></div>
<div class="mobile-item-summary__row mobile-item-summary__row--total"><span>本次付款合计</span><span>{{ erpPriceInputFormatter(summaryData.paymentPrice) }}</span></div>
</div>
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleOpenPurchaseIn" round>+ 添加采购入库单</el-button>
<el-button @click="handleOpenPurchaseReturn" round>+ 添加采购退货单</el-button>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="采购单据编号" min-width="200">
@@ -69,7 +90,7 @@
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3" v-if="!disabled">
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3">
<el-button @click="handleOpenPurchaseIn" round>+ 添加采购入库单</el-button>
<el-button @click="handleOpenPurchaseReturn" round>+ 添加采购退货单</el-button>
</el-row>
@@ -91,6 +112,7 @@
<PurchaseReturnForm ref="purchaseReturnFormRef" />
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ProductVO } from '@/api/erp/product/product'
import { erpPriceInputFormatter, getSumValue } from '@/utils'
import PurchaseInPaymentEnableList from '@/views/erp/purchase/in/components/PurchaseInPaymentEnableList.vue'
@@ -100,6 +122,10 @@ import PurchaseReturnForm from '@/views/erp/purchase/return/PurchaseReturnForm.v
import { PurchaseInVO } from '@/api/erp/purchase/in'
import { ErpBizType } from '@/utils/constants'
import { PurchaseReturnVO } from '@/api/erp/purchase/return'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -125,21 +151,25 @@ watch(
{ immediate: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
totalPrice: getSumValue(formData.value.map((item) => Number(item.totalPrice))),
paidPrice: getSumValue(formData.value.map((item) => Number(item.paidPrice))),
paymentPrice: getSumValue(formData.value.map((item) => Number(item.paymentPrice)))
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) {
sums[index] = '合计'
return
}
if (index === 0) { sums[index] = '合计'; return }
if (['totalPrice', 'paidPrice', 'paymentPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = erpPriceInputFormatter(sum)
} else {
sums[index] = ''
}
} else { sums[index] = '' }
})
return sums
}

View File

@@ -1,27 +1,63 @@
<template>
<doc-alert
title="【财务】采购付款、销售收款"
url="https://doc.iocoder.cn/sale/finance-payment-receipt/"
/>
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-payment">
<div class="mobile-header">
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索付款单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:finance-payment:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 20 }" @click="handleQuickFilter(20)">已审核</div>
</div>
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无付款记录" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleRowClickMobile(item)">
<div class="mobile-card__header">
<span class="mobile-card__no">{{ item.no }}</span>
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row"><span class="mobile-card__label">供应商</span><span class="mobile-card__value">{{ item.supplierName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">付款时间</span><span class="mobile-card__value">{{ formatDate2(item.paymentTime) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">财务人员</span><span class="mobile-card__value">{{ item.financeUserName || '-' }}</span></div>
<div class="mobile-card__nums">
<div class="mobile-card__num-item"><div class="mobile-card__num-val">{{ erpPriceTableColumnFormatter(null,null,item.totalPrice,null) }}</div><div class="mobile-card__num-label">合计付款</div></div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val mobile-card__num-val--price">{{ erpPriceTableColumnFormatter(null,null,item.paymentPrice,null) }}</div><div class="mobile-card__num-label">实际付款</div></div>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" @click.stop="openForm('detail', item.id)" v-hasPermi="['erp:finance-payment:query']">详情</el-button>
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:finance-payment:update']" :disabled="item.status === 20">编辑</el-button>
<el-button size="small" type="primary" @click.stop="handleUpdateStatus(item.id, 20)" v-hasPermi="['erp:finance-payment:update-status']" v-if="item.status === 10">审批</el-button>
<el-button size="small" type="danger" @click.stop="handleUpdateStatus(item.id, 10)" v-hasPermi="['erp:finance-payment:update-status']" v-else>反审批</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete([item.id])" v-hasPermi="['erp:finance-payment:delete']">删除</el-button>
</div>
</div>
</div>
<div class="mobile-pagination" v-if="total > 0"><Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" /></div>
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="70%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="供应商" prop="supplierId"><el-select v-model="queryParams.supplierId" clearable filterable placeholder="请选择供应商" style="width:100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="付款时间" prop="paymentTime"><el-date-picker v-model="queryParams.paymentTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始" end-placeholder="结束" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width:100%" /></el-form-item>
<el-form-item label="付款账户" prop="accountId"><el-select v-model="queryParams.accountId" clearable filterable placeholder="请选择付款账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width:100%"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
</div>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="付款单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入付款单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="付款单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入付款单号" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="付款时间" prop="paymentTime">
<el-date-picker
v-model="queryParams.paymentTime"
@@ -252,22 +288,18 @@
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<FinancePaymentForm ref="formRef" :fetch-invoice-page="fetchInvoicePage" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { FinancePaymentApi, FinancePaymentVO } from '@/api/erp/finance/payment'
import FinancePaymentForm from './FinancePaymentForm.vue'
@@ -277,9 +309,14 @@ import * as UserApi from '@/api/system/user'
import { erpPriceTableColumnFormatter } from '@/utils'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
/** ERP 付款单列表 */
defineOptions({ name: 'ErpPurchaseOrder' })
defineOptions({ name: 'ErpFinancePayment' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -302,6 +339,7 @@ const queryParams = reactive({
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const filterVisible = ref(false) // 筛选抽屉
const supplierList = ref<SupplierVO[]>([]) // 供应商列表
const userList = ref<UserVO[]>([]) // 用户列表
const accountList = ref<AccountVO[]>([]) // 账户列表
@@ -329,10 +367,29 @@ const handleQuery = () => {
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
queryFormRef.value?.resetFields()
handleQuery()
}
/** 筛选确认 */
const handleFilterConfirm = () => {
filterVisible.value = false
handleQuery()
}
/** 快捷筛选 */
const handleQuickFilter = (status: number | undefined) => {
queryParams.status = status
queryParams.pageNo = 1
getList()
}
/** 移动端行点击 */
const handleRowClickMobile = (row: FinancePaymentVO) => {
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
@@ -420,6 +477,30 @@ onMounted(async () => {
userList.value = await UserApi.getSimpleUserList()
accountList.value = await AccountApi.getAccountSimpleList()
})
// TODO 芋艿:可优化功能:列表界面,支持导入
// TODO 芋艿:可优化功能:详情界面,支持打印
</script>
<style lang="scss" scoped>
.mobile-payment { padding: 12px; background: #f5f5f5; min-height: 100vh; }
.mobile-header { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
.mobile-header__search { flex: 1; }
.mobile-header__actions { display: flex; gap: 4px; }
.mobile-header__quick-filter { display: flex; gap: 12px; margin: 8px 0; }
.quick-filter-item { padding: 4px 12px; font-size: 14px; border-radius: 20px; cursor: pointer; color: #909399; background: transparent; transition: all 0.2s; }
.quick-filter-item.active { color: #fff; background: #409eff; }
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-card__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.mobile-card__no { font-weight: 600; font-size: 15px; color: #303133; }
.mobile-card__body { font-size: 13px; }
.mobile-card__row { display: flex; justify-content: space-between; padding: 3px 0; }
.mobile-card__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
.mobile-card__value { color: #606266; text-align: right; }
.mobile-card__nums { display: flex; justify-content: space-around; margin-top: 10px; padding: 10px 0; border-top: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0; }
.mobile-card__num-item { text-align: center; }
.mobile-card__num-val { font-size: 15px; font-weight: 600; color: #303133; }
.mobile-card__num-val--price { color: #e6a23c; }
.mobile-card__num-label { font-size: 11px; color: #909399; margin-top: 2px; }
.mobile-card__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.mobile-pagination { margin-top: 12px; display: flex; justify-content: center; :deep(.el-pagination) { flex-wrap: wrap; justify-content: center; } }
</style>

View File

@@ -1,167 +1,72 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="100px"
v-loading="formLoading"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="收款单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="收款时间" prop="receiptTime"><el-date-picker v-model="formData.receiptTime" type="date" value-format="x" placeholder="选择收款时间" style="width:100%" /></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" style="width:100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="发票" prop="invoiceNo"><el-input v-model="invoiceDisplay" readonly placeholder="请选择发票"><template #append><el-button @click="openInvoiceSelect"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="财务人员" prop="financeUserId"><el-select v-model="formData.financeUserId" clearable filterable placeholder="请选择财务人员" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<div class="mobile-form__section">
<div class="mobile-form__section-title">销售出库退货单</div>
<FinanceReceiptItemForm ref="itemFormRef" :customer-id="formData.customerId" :items="formData.items" :disabled="disabled" />
</div>
<div class="mobile-form__section">
<div class="mobile-form__section-title">结算信息</div>
<el-form-item label="收款账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="合计收款" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠金额" prop="discountPrice"><el-input-number v-model="formData.discountPrice" controls-position="right" :precision="4" placeholder="请输入优惠金额" style="width:100%" /></el-form-item>
<el-form-item label="实际收款"><el-input disabled v-model="formData.receiptPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
</div>
</el-form>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="收款单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="收款时间" prop="receiptTime">
<el-date-picker
v-model="formData.receiptTime"
type="date"
value-format="x"
placeholder="选择收款时间"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="客户" prop="customerId">
<el-select
v-model="formData.customerId"
clearable
filterable
placeholder="请选择客户"
class="!w-1/1"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="发票" prop="invoiceNo">
<el-input v-model="invoiceDisplay" readonly placeholder="请选择发票">
<template #append>
<el-button @click="openInvoiceSelect"> <Icon icon="ep:search" /> 选择 </el-button>
</template>
</el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="财务人员" prop="financeUserId">
<el-select
v-model="formData.financeUserId"
clearable
filterable
placeholder="请选择财务人员"
class="!w-1/1"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="1"
placeholder="请输入备注"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
</el-col>
<el-col :span="8"><el-form-item label="收款单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="收款时间" prop="receiptTime"><el-date-picker v-model="formData.receiptTime" type="date" value-format="x" placeholder="选择收款时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="发票" prop="invoiceNo"><el-input v-model="invoiceDisplay" readonly placeholder="请选择发票"><template #append><el-button @click="openInvoiceSelect"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="财务人员" prop="financeUserId"><el-select v-model="formData.financeUserId" clearable filterable placeholder="请选择财务人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<!-- 子表的表单 -->
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="采购入库、退货单" name="item">
<FinanceReceiptItemForm
ref="itemFormRef"
:customer-id="formData.customerId"
:items="formData.items"
:disabled="disabled"
/>
</el-tab-pane>
<el-tab-pane label="销售出库、退货单" name="item"><FinanceReceiptItemForm ref="itemFormRef" :customer-id="formData.customerId" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="收款账户" prop="accountId">
<el-select
v-model="formData.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-1/1"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="合计收款" prop="totalPrice">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="优惠金额" prop="discountPrice">
<el-input-number
v-model="formData.discountPrice"
controls-position="right"
:precision="4"
placeholder="请输入优惠金额"
class="!w-1/1"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="实际收款">
<el-input
disabled
v-model="formData.receiptPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
</el-col>
<el-col :span="8"><el-form-item label="收款账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合计收款" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠金额" prop="discountPrice"><el-input-number v-model="formData.discountPrice" controls-position="right" :precision="4" placeholder="请输入优惠金额" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="实际收款"><el-input disabled v-model="formData.receiptPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled">
</el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 发票选择弹窗 -->
<InvoiceSelectList
ref="invoiceSelectRef"
:invoice-category="2"
:fetch-invoice-page="props.fetchInvoicePage"
@success="handleInvoiceSelect"
/>
<InvoiceSelectList ref="invoiceSelectRef" :invoice-category="2" :fetch-invoice-page="props.fetchInvoicePage" @success="handleInvoiceSelect" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { FinanceReceiptApi, FinanceReceiptVO } from '@/api/erp/finance/receipt'
import FinanceReceiptItemForm from './components/FinanceReceiptItemForm.vue'
import { erpPriceInputFormatter } from '@/utils'
@@ -170,10 +75,14 @@ import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import InvoiceSelectList from '@/views/erp/finance/invoice/components/InvoiceSelectList.vue'
import { Invoice } from '@/api/erp/finance/invoice'
import { useWindowSize } from '@vueuse/core'
/** ERP 收款单表单 */
defineOptions({ name: 'FinanceReceiptForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
fetchInvoicePage: (params: any) => Promise<any>
}>()
@@ -324,3 +233,10 @@ const resetForm = () => {
formRef.value?.resetFields()
}
</script>
<style lang="scss" scoped>
.mobile-form { padding: 0 4px; }
.mobile-form__section { background: #fff; border-radius: 10px; padding: 14px; margin-bottom: 12px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-form__section-title { font-size: 15px; font-weight: 600; color: #303133; margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid #f0f0f0; }
.mobile-form__footer { position: sticky; bottom: 0; background: #fff; padding: 12px 16px; padding-bottom: calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid #eee; display: flex; justify-content: flex-end; gap: 12px; z-index: 10; margin: 0 -4px; .el-button { flex: 1; height: 40px; font-size: 15px; } }
</style>

View File

@@ -1,13 +1,34 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-width="0px"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div v-for="(row, $index) in formData" :key="$index" class="mobile-item-card">
<div class="mobile-item-card__header">
<span class="mobile-item-card__index">#{{ $index + 1 }}</span>
<span class="mobile-item-card__name">{{ row.bizNo || '未选择单据' }}</span>
<el-button :disabled="disabled" @click="handleDelete($index)" link type="danger" size="small">删除</el-button>
</div>
<div class="mobile-item-card__body">
<div class="mobile-item-card__info-row"><span class="mobile-item-card__info-label">应收金额</span><span class="mobile-item-card__info-value">{{ erpPriceInputFormatter(row.totalPrice) }}</span></div>
<div class="mobile-item-card__info-row"><span class="mobile-item-card__info-label">已收金额</span><span class="mobile-item-card__info-value">{{ erpPriceInputFormatter(row.receiptedPrice) }}</span></div>
<el-form-item label="本次收款" :prop="`${$index}.receiptPrice`"><el-input-number v-model="row.receiptPrice" controls-position="right" :precision="4" style="width:100%" /></el-form-item>
<el-form-item label="备注" :prop="`${$index}.remark`"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item>
</div>
</div>
<div class="mobile-item-summary" v-if="formData.length > 0">
<div class="mobile-item-summary__row"><span>应收合计</span><span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span></div>
<div class="mobile-item-summary__row"><span>已收合计</span><span>{{ erpPriceInputFormatter(summaryData.receiptedPrice) }}</span></div>
<div class="mobile-item-summary__row mobile-item-summary__row--total"><span>本次收款合计</span><span>{{ erpPriceInputFormatter(summaryData.receiptPrice) }}</span></div>
</div>
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleOpenSaleOut" round>+ 添加销售出库单</el-button>
<el-button @click="handleOpenSaleReturn" round>+ 添加销售退货单</el-button>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="销售单据编号" min-width="200">
@@ -69,7 +90,7 @@
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3" v-if="!disabled">
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3">
<el-button @click="handleOpenSaleOut" round>+ 添加销售出库单</el-button>
<el-button @click="handleOpenSaleReturn" round>+ 添加销售退货单</el-button>
</el-row>
@@ -85,6 +106,7 @@
<SaleReturnForm ref="saleReturnFormRef" />
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { ProductVO } from '@/api/erp/product/product'
import { erpPriceInputFormatter, getSumValue } from '@/utils'
import SaleOutReceiptEnableList from '@/views/erp/sale/out/components/SaleOutReceiptEnableList.vue'
@@ -94,6 +116,10 @@ import SaleReturnForm from '@/views/erp/sale/return/SaleReturnForm.vue'
import { SaleOutVO } from '@/api/erp/sale/out'
import { ErpBizType } from '@/utils/constants'
import { SaleReturnVO } from '@/api/erp/sale/return'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -119,21 +145,25 @@ watch(
{ immediate: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
totalPrice: getSumValue(formData.value.map((item) => Number(item.totalPrice))),
receiptedPrice: getSumValue(formData.value.map((item) => Number(item.receiptedPrice))),
receiptPrice: getSumValue(formData.value.map((item) => Number(item.receiptPrice)))
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) {
sums[index] = '合计'
return
}
if (index === 0) { sums[index] = '合计'; return }
if (['totalPrice', 'receiptedPrice', 'receiptPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = erpPriceInputFormatter(sum)
} else {
sums[index] = ''
}
} else { sums[index] = '' }
})
return sums
}

View File

@@ -1,27 +1,63 @@
<template>
<doc-alert
title="【财务】采购付款、销售收款"
url="https://doc.iocoder.cn/sale/finance-payment-receipt/"
/>
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-receipt">
<div class="mobile-header">
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索收款单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:finance-receipt:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 20 }" @click="handleQuickFilter(20)">已审核</div>
</div>
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无收款记录" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleRowClickMobile(item)">
<div class="mobile-card__header">
<span class="mobile-card__no">{{ item.no }}</span>
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row"><span class="mobile-card__label">客户</span><span class="mobile-card__value">{{ item.customerName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">收款时间</span><span class="mobile-card__value">{{ formatDate2(item.receiptTime) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">财务人员</span><span class="mobile-card__value">{{ item.financeUserName || '-' }}</span></div>
<div class="mobile-card__nums">
<div class="mobile-card__num-item"><div class="mobile-card__num-val">{{ erpPriceTableColumnFormatter(null,null,item.totalPrice,null) }}</div><div class="mobile-card__num-label">合计收款</div></div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val mobile-card__num-val--price">{{ erpPriceTableColumnFormatter(null,null,item.receiptPrice,null) }}</div><div class="mobile-card__num-label">实际收款</div></div>
</div>
</div>
<div class="mobile-card__footer">
<el-button size="small" @click.stop="openForm('detail', item.id)" v-hasPermi="['erp:finance-receipt:query']">详情</el-button>
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:finance-receipt:update']" :disabled="item.status === 20">编辑</el-button>
<el-button size="small" type="primary" @click.stop="handleUpdateStatus(item.id, 20)" v-hasPermi="['erp:finance-receipt:update-status']" v-if="item.status === 10">审批</el-button>
<el-button size="small" type="danger" @click.stop="handleUpdateStatus(item.id, 10)" v-hasPermi="['erp:finance-receipt:update-status']" v-else>反审批</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete([item.id])" v-hasPermi="['erp:finance-receipt:delete']">删除</el-button>
</div>
</div>
</div>
<div class="mobile-pagination" v-if="total > 0"><Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" /></div>
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="70%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="客户" prop="customerId"><el-select v-model="queryParams.customerId" clearable filterable placeholder="请选择客户" style="width:100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="收款时间" prop="receiptTime"><el-date-picker v-model="queryParams.receiptTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始" end-placeholder="结束" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width:100%" /></el-form-item>
<el-form-item label="收款账户" prop="accountId"><el-select v-model="queryParams.accountId" clearable filterable placeholder="请选择收款账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width:100%"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
</div>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="收款单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入收款单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="收款单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入收款单号" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="收款时间" prop="receiptTime">
<el-date-picker
v-model="queryParams.receiptTime"
@@ -252,22 +288,18 @@
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<FinanceReceiptForm ref="formRef" :fetch-invoice-page="fetchInvoicePage" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { FinanceReceiptApi, FinanceReceiptVO } from '@/api/erp/finance/receipt'
import FinanceReceiptForm from './FinanceReceiptForm.vue'
@@ -277,9 +309,14 @@ import * as UserApi from '@/api/system/user'
import { erpPriceTableColumnFormatter } from '@/utils'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
/** ERP 收款单列表 */
defineOptions({ name: 'ErpPurchaseOrder' })
defineOptions({ name: 'ErpFinanceReceipt' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -302,6 +339,7 @@ const queryParams = reactive({
})
const queryFormRef = ref() // 搜索的表单
const exportLoading = ref(false) // 导出的加载中
const filterVisible = ref(false) // 筛选抽屉
const customerList = ref<CustomerVO[]>([]) // 客户列表
const userList = ref<UserVO[]>([]) // 用户列表
const accountList = ref<AccountVO[]>([]) // 账户列表
@@ -329,10 +367,29 @@ const handleQuery = () => {
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
queryFormRef.value?.resetFields()
handleQuery()
}
/** 筛选确认 */
const handleFilterConfirm = () => {
filterVisible.value = false
handleQuery()
}
/** 快捷筛选 */
const handleQuickFilter = (status: number | undefined) => {
queryParams.status = status
queryParams.pageNo = 1
getList()
}
/** 移动端行点击 */
const handleRowClickMobile = (row: FinanceReceiptVO) => {
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
@@ -420,6 +477,30 @@ onMounted(async () => {
userList.value = await UserApi.getSimpleUserList()
accountList.value = await AccountApi.getAccountSimpleList()
})
// TODO 芋艿:可优化功能:列表界面,支持导入
// TODO 芋艿:可优化功能:详情界面,支持打印
</script>
<style lang="scss" scoped>
.mobile-receipt { padding: 12px; background: #f5f5f5; min-height: 100vh; }
.mobile-header { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
.mobile-header__search { flex: 1; }
.mobile-header__actions { display: flex; gap: 4px; }
.mobile-header__quick-filter { display: flex; gap: 12px; margin: 8px 0; }
.quick-filter-item { padding: 4px 12px; font-size: 14px; border-radius: 20px; cursor: pointer; color: #909399; background: transparent; transition: all 0.2s; }
.quick-filter-item.active { color: #fff; background: #409eff; }
.mobile-list { display: flex; flex-direction: column; gap: 10px; }
.mobile-empty { padding: 40px 0; }
.mobile-card { background: #fff; border-radius: 10px; padding: 14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06); }
.mobile-card__header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.mobile-card__no { font-weight: 600; font-size: 15px; color: #303133; }
.mobile-card__body { font-size: 13px; }
.mobile-card__row { display: flex; justify-content: space-between; padding: 3px 0; }
.mobile-card__label { color: #909399; flex-shrink: 0; margin-right: 12px; }
.mobile-card__value { color: #606266; text-align: right; }
.mobile-card__nums { display: flex; justify-content: space-around; margin-top: 10px; padding: 10px 0; border-top: 1px solid #f0f0f0; border-bottom: 1px solid #f0f0f0; }
.mobile-card__num-item { text-align: center; }
.mobile-card__num-val { font-size: 15px; font-weight: 600; color: #303133; }
.mobile-card__num-val--price { color: #67c23a; }
.mobile-card__num-label { font-size: 11px; color: #909399; margin-top: 2px; }
.mobile-card__footer { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.mobile-pagination { margin-top: 12px; display: flex; justify-content: center; :deep(.el-pagination) { flex-wrap: wrap; justify-content: center; } }
</style>

View File

@@ -1,12 +1,31 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-width="110px"
v-loading="formLoading"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">应收单信息</div>
<el-form-item label="销售出库订单" prop="saleOrderNo"><el-input v-model="formData.saleOrderNo" readonly placeholder="请选择销售出库订单"><template #append><el-button @click="openSaleOutSelect"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="应收单号" prop="aroCode"><el-input v-model="formData.aroCode" placeholder="请输入应收单号" /></el-form-item>
<el-form-item label="客户" prop="customer"><el-input v-model="formData.customer" placeholder="请选择客户" /></el-form-item>
<el-form-item label="单据日期" prop="billDate"><el-date-picker v-model="formData.billDate" type="date" value-format="x" placeholder="选择单据日期" style="width:100%" /></el-form-item>
<el-form-item label="已收金额" prop="receiptPrice"><el-input v-model="formData.receiptPrice" placeholder="请输入已收金额" /></el-form-item>
<el-form-item label="总金额" prop="totalAmount"><el-input v-model="formData.totalAmount" placeholder="请输入总金额" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" placeholder="请输入备注" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="110px" v-loading="formLoading">
<el-form-item label="销售出库订单" prop="saleOrderNo">
<el-input v-model="formData.saleOrderNo" readonly placeholder="请选择销售出库订单">
<template #append>
@@ -103,15 +122,20 @@
/>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { ReceivableOrderApi, ReceivableOrder } from '@/api/erp/finance/receivableorder'
import SaleOutReceiptEnableList from '@/views/erp/sale/out/components/SaleOutReceiptEnableList.vue'
import { SaleOutVO } from '@/api/erp/sale/out'
import { formatToDate } from '@/utils/dateUtil'
import { SubjectApi, SubjectVO } from '@/api/erp/finance/subject'
import { useWindowSize } from '@vueuse/core'
/** 应收单 表单 */
defineOptions({ name: 'ReceivableOrderForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,5 +1,31 @@
<template>
<Dialog :title="dialogTitle" v-model="dialogVisible">
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">会计科目信息</div>
<el-form-item label="上级科目" prop="parentId"><el-tree-select v-model="formData.parentId" :data="subjectTree" placeholder="请选择上级科目" :props="{ label: 'name', value: 'id', children: 'children' }" check-strictly clearable style="width:100%" /></el-form-item>
<el-form-item label="科目编码" prop="code"><el-input v-model="formData.code" placeholder="请输入科目编码" /></el-form-item>
<el-form-item label="科目名称" prop="name"><el-input v-model="formData.name" placeholder="请输入科目名称" /></el-form-item>
<el-form-item label="科目类型" prop="type"><el-select v-model="formData.type" placeholder="请选择科目类型" style="width:100%"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_FINANCE_SUBJECT_TYPE)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item label="余额方向" prop="direction"><el-select v-model="formData.direction" placeholder="请选择余额方向" style="width:100%"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.ERP_FINANCE_SUBJECT_DIRECTION)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item label="状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="排序" prop="sort"><el-input-number v-model="formData.sort" :min="0" style="width:100%" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input v-model="formData.remark" type="textarea" placeholder="请输入备注" /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form
ref="formRef"
:model="formData"
@@ -68,12 +94,17 @@
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { SubjectApi, SubjectVO } from '@/api/erp/finance/subject'
import { useWindowSize } from '@vueuse/core'
/** ERP 会计科目 表单 */
defineOptions({ name: 'SubjectForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端使用抽屉 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
@@ -10,23 +12,11 @@
class="mobile-form-drawer"
>
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="上级分类" prop="parentId">
<el-tree-select
v-model="formData.parentId"
:data="productCategoryTree"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择上级分类"
/>
<el-tree-select v-model="formData.parentId" :data="productCategoryTree" :props="defaultProps" check-strictly default-expand-all placeholder="请选择上级分类" />
</el-form-item>
<el-form-item label="分类名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入分类名称" clearable />
@@ -38,40 +28,63 @@
<el-input-number v-model="formData.sort" placeholder="请输入排序" :precision="0" controls-position="right" />
</el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端使用对话框 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="上级编号" prop="parentId">
<el-tree-select v-model="formData.parentId" :data="productCategoryTree" :props="defaultProps" check-strictly default-expand-all placeholder="请选择上级编号" />
</el-form-item>
<el-form-item label="名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入名称" />
</el-form-item>
<el-form-item label="编码" prop="code">
<el-input v-model="formData.code" placeholder="请输入编码" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="formData.sort" placeholder="请输入排序" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import { defaultProps, handleTree } from '@/utils/tree'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品分类 表单 */
defineOptions({ name: 'ProductCategoryForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-product-category">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-product-category">
<!-- 搜索操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -70,13 +71,65 @@
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="分类名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入分类名称" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="开启状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择开启状态" clearable class="!w-240px">
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:product-category:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-category:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button type="danger" plain @click="toggleExpandAll">
<Icon icon="ep:sort" class="mr-5px" /> 展开/折叠
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" row-key="id" :default-expand-all="isExpandAll" v-if="refreshTable" @row-click="handleRowClick">
<el-table-column label="编码" align="center" prop="code" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:product-category:update']">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:product-category:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<ProductCategoryForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
@@ -84,10 +137,14 @@ import { handleTree } from '@/utils/tree'
import download from '@/utils/download'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import ProductCategoryForm from './ProductCategoryForm.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品分类 列表 */
defineOptions({ name: 'ErpProductCategory' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -193,9 +250,20 @@ const handleExport = async () => {
/** 展开/折叠操作 */
const isExpandAll = ref(true) // 是否展开,默认全部展开
const toggleExpandAll = () => {
const refreshTable = ref(true) // PC端重新渲染表格状态
const toggleExpandAll = async () => {
isExpandAll.value = !isExpandAll.value
// 移动端
flattenTree()
// PC端
refreshTable.value = false
await nextTick()
refreshTable.value = true
}
/** PC端行点击操作 */
const handleRowClick = (row: ProductCategoryVO) => {
openForm('update', row.id)
}
/** 初始化 **/

View File

@@ -1,161 +1,76 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端使用抽屉 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="产品名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入产品名称" clearable />
</el-form-item>
<el-form-item label="产品条码" prop="barCode">
<el-input v-model="formData.barCode" placeholder="请输入产品条码" clearable />
</el-form-item>
<el-form-item label="产品分类" prop="categoryId">
<el-tree-select
v-model="formData.categoryId"
:data="categoryList"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择产品分类"
/>
</el-form-item>
<el-form-item label="产品单位" prop="unitId">
<el-select v-model="formData.unitId" clearable placeholder="请选择产品单位">
<el-option
v-for="unit in unitList"
:key="unit.id"
:label="unit.name"
:value="unit.id"
/>
</el-select>
</el-form-item>
<el-form-item label="产品规格" prop="standard">
<el-input v-model="formData.standard" placeholder="请输入产品规格" clearable />
</el-form-item>
<el-form-item label="产品名称" prop="name"><el-input v-model="formData.name" placeholder="请输入产品名称" clearable /></el-form-item>
<el-form-item label="产品条码" prop="barCode"><el-input v-model="formData.barCode" placeholder="请输入产品条码" clearable /></el-form-item>
<el-form-item label="产品分类" prop="categoryId"><el-tree-select v-model="formData.categoryId" :data="categoryList" :props="defaultProps" check-strictly default-expand-all placeholder="请选择产品分类" /></el-form-item>
<el-form-item label="产品单位" prop="unitId"><el-select v-model="formData.unitId" clearable placeholder="请选择产品单位"><el-option v-for="unit in unitList" :key="unit.id" :label="unit.name" :value="unit.id" /></el-select></el-form-item>
<el-form-item label="产品规格" prop="standard"><el-input v-model="formData.standard" placeholder="请输入产品规格" clearable /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">价格信息</div>
<el-form-item label="采购价格(元)" prop="purchasePrice">
<el-input-number
v-model="formData.purchasePrice"
placeholder="请输入采购价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="销售价格(元)" prop="salePrice">
<el-input-number
v-model="formData.salePrice"
placeholder="请输入销售价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="货值(元)" prop="minPrice">
<el-input-number
v-model="formData.minPrice"
placeholder="请输入最低价格"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="采购价格(元)" prop="purchasePrice"><el-input-number v-model="formData.purchasePrice" placeholder="请输入采购价格" :min="0" :precision="4" controls-position="right" /></el-form-item>
<el-form-item label="销售价格(元)" prop="salePrice"><el-input-number v-model="formData.salePrice" placeholder="请输入销售价格" :min="0" :precision="4" controls-position="right" /></el-form-item>
<el-form-item label="货值(元)" prop="minPrice"><el-input-number v-model="formData.minPrice" placeholder="请输入最低价格" :min="0" :precision="4" controls-position="right" /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">库存信息</div>
<el-form-item label="库存预警数量" prop="stockAlertCount">
<el-input-number
v-model="formData.stockAlertCount"
placeholder="请输入库存预警数量"
:min="0"
:precision="2"
controls-position="right"
/>
</el-form-item>
<el-form-item label="保质期天数" prop="expiryDay">
<el-input-number
v-model="formData.expiryDay"
placeholder="请输入保质期天数"
:min="0"
:precision="0"
controls-position="right"
/>
</el-form-item>
<el-form-item label="重量kg" prop="weight">
<el-input-number
v-model="formData.weight"
placeholder="请输入重量"
:min="0"
controls-position="right"
/>
</el-form-item>
<el-form-item label="库存预警数量" prop="stockAlertCount"><el-input-number v-model="formData.stockAlertCount" placeholder="请输入库存预警数量" :min="0" :precision="2" controls-position="right" /></el-form-item>
<el-form-item label="保质期天数" prop="expiryDay"><el-input-number v-model="formData.expiryDay" placeholder="请输入保质期天数" :min="0" :precision="0" controls-position="right" /></el-form-item>
<el-form-item label="重量kg" prop="weight"><el-input-number v-model="formData.weight" placeholder="请输入重量" :min="0" controls-position="right" /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">供应商信息</div>
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商">
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">其他信息</div>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="3" />
</el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="3" /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="开启状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端使用对话框 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12"><el-form-item label="名称" prop="name"><el-input v-model="formData.name" placeholder="请输入名称" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="条码" prop="barCode"><el-input v-model="formData.barCode" placeholder="请输入条码" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="分类" prop="categoryId"><el-tree-select v-model="formData.categoryId" :data="categoryList" :props="defaultProps" check-strictly default-expand-all placeholder="请选择分类" class="w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="单位" prop="unitId"><el-select v-model="formData.unitId" clearable placeholder="请选择单位" class="w-1/1"><el-option v-for="unit in unitList" :key="unit.id" :label="unit.name" :value="unit.id" /></el-select></el-form-item></el-col>
<el-col :span="12"><el-form-item label="状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item></el-col>
<el-col :span="12"><el-form-item label="规格" prop="standard"><el-input v-model="formData.standard" placeholder="请输入规格" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="保质期天数" prop="expiryDay"><el-input-number v-model="formData.expiryDay" placeholder="请输入保质期天数" :min="0" :precision="0" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="重量kg" prop="weight"><el-input-number v-model="formData.weight" placeholder="请输入重量kg" :min="0" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="采购价格" prop="purchasePrice"><el-input-number v-model="formData.purchasePrice" placeholder="请输入采购价格,单位:元" :min="0" :precision="4" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="销售价格" prop="salePrice"><el-input-number v-model="formData.salePrice" placeholder="请输入销售价格,单位:元" :min="0" :precision="4" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="货值" prop="minPrice"><el-input-number v-model="formData.minPrice" placeholder="请输入最低价格,单位:元" :min="0" :precision="4" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="库存预警" prop="stockAlertCount"><el-input-number v-model="formData.stockAlertCount" placeholder="请输入库存预警数量" :min="0" :precision="2" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" class="w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit'
@@ -163,10 +78,14 @@ import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { CommonStatusEnum } from '@/utils/constants'
import { defaultProps, handleTree } from '@/utils/tree'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品 表单 */
defineOptions({ name: 'ProductForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,6 +1,6 @@
<template>
<div class="mobile-product">
<!-- 搜索操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-product">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索产品名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
@@ -10,73 +10,37 @@
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:product:create']" />
</div>
</div>
<!-- 快捷操作 -->
<div class="mobile-quick-actions">
<el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product:export']">导出</el-button>
</div>
<!-- 卡片列表 -->
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty">
<el-empty description="暂无产品" />
</div>
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无产品" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleCardClick(item)">
<div class="mobile-card__header">
<span class="mobile-card__name">{{ item.name || '-' }}</span>
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">条码</span>
<span class="mobile-card__value">{{ item.barCode || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">规格</span>
<span class="mobile-card__value">{{ item.standard || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">分类</span>
<span class="mobile-card__value">{{ item.categoryName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">单位</span>
<span class="mobile-card__value">{{ item.unitName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">供应商</span>
<span class="mobile-card__value">{{ item.supplierName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">货值</span>
<span class="mobile-card__value">{{ formatPrice(item.minPrice) }}</span>
</div>
<div class="mobile-card__row"><span class="mobile-card__label">条码</span><span class="mobile-card__value">{{ item.barCode || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">规格</span><span class="mobile-card__value">{{ item.standard || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">分类</span><span class="mobile-card__value">{{ item.categoryName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">单位</span><span class="mobile-card__value">{{ item.unitName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">供应商</span><span class="mobile-card__value">{{ item.supplierName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">货值</span><span class="mobile-card__value">{{ formatPrice(item.minPrice) }}</span></div>
</div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product:update']" :disabled="item.name === '番茄' || item.name === '甜菊糖' || item.name === '番茄酱' || item.name === '甜叶菊'">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product:delete']" :disabled="item.name === '番茄' || item.name === '甜菊糖' || item.name === '番茄酱' || item.name === '甜叶菊'">删除</el-button>
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product:update']" :disabled="isProtectedProduct(item.name)">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product:delete']" :disabled="isProtectedProduct(item.name)">删除</el-button>
</div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-pagination" v-if="total > 0">
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" />
</div>
<!-- 筛选抽屉 -->
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="产品分类" prop="categoryId">
<el-tree-select
v-model="queryParams.categoryId"
:data="categoryList"
:props="defaultProps"
check-strictly
default-expand-all
placeholder="请选择分类"
style="width:100%"
/>
<el-tree-select v-model="queryParams.categoryId" :data="categoryList" :props="defaultProps" check-strictly default-expand-all placeholder="请选择分类" style="width:100%" />
</el-form-item>
</el-form>
<template #footer>
@@ -84,13 +48,57 @@
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<ProductForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="分类" prop="categoryId">
<el-tree-select v-model="queryParams.categoryId" :data="categoryList" :props="defaultProps" check-strictly default-expand-all placeholder="请输入分类" class="!w-240px" />
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:product:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="条码" align="center" prop="barCode" />
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="规格" align="center" prop="standard" />
<el-table-column label="分类" align="center" prop="categoryName" />
<el-table-column label="单位" align="center" prop="unitName" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="货值" align="center" prop="minPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="库存预警" align="center" prop="stockAlertCount" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope"><dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /></template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column label="操作" align="center" width="110">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:product:update']" :disabled="isProtectedProduct(scope.row.name)">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:product:delete']" :disabled="isProtectedProduct(scope.row.name)">删除</el-button>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<ProductForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
@@ -98,12 +106,16 @@ import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { ProductCategoryApi, ProductCategoryVO } from '@/api/erp/product/category'
import ProductForm from './ProductForm.vue'
import { DICT_TYPE } from '@/utils/dict'
import { useWindowSize } from '@vueuse/core'
import { defaultProps, handleTree } from '@/utils/tree'
import { erpPriceTableColumnFormatter } from '@/utils'
/** ERP 产品列表 */
defineOptions({ name: 'ErpProduct' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -151,9 +163,20 @@ const handleFilterConfirm = () => {
handleQuery()
}
/** 卡片点击 */
/** 判断是否为受保护产品 */
const isProtectedProduct = (name: string) => {
return name === '番茄' || name === '甜菊糖' || name === '番茄酱' || name === '甜叶菊'
}
/** 卡片点击(移动端) */
const handleCardClick = (row: ProductVO) => {
if (row.name === '番茄' || row.name === '甜菊糖' || row.name === '番茄酱' || row.name === '甜叶菊') return
if (isProtectedProduct(row.name)) return
openForm('update', row.id)
}
/** 行点击(PC端) */
const handleRowClick = (row: ProductVO) => {
if (isProtectedProduct(row.name)) return
openForm('update', row.id)
}

View File

@@ -1,60 +1,49 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端使用抽屉 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="单位名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入单位名称" clearable />
</el-form-item>
<el-form-item label="单位名称" prop="name"><el-input v-model="formData.name" placeholder="请输入单位名称" clearable /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="开启状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="开启状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端使用对话框 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="单位名字" prop="name"><el-input v-model="formData.name" placeholder="请输入单位名字" /></el-form-item>
<el-form-item label="单位状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { ProductUnitApi } from '@/api/erp/product/unit'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品单位表单 */
defineOptions({ name: 'ProductUnitForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,85 +1,84 @@
<template>
<div class="mobile-product-unit">
<!-- 搜索操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-product-unit">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索单位名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.name" placeholder="搜索单位名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:product-unit:create']" />
</div>
</div>
<!-- 快捷操作 -->
<div class="mobile-quick-actions">
<el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-unit:export']">导出</el-button>
</div>
<!-- 卡片列表 -->
<div class="mobile-quick-actions"><el-button size="small" type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-unit:export']">导出</el-button></div>
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty">
<el-empty description="暂无产品单位" />
</div>
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无产品单位" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleCardClick(item)">
<div class="mobile-card__header">
<span class="mobile-card__name">{{ item.name || '-' }}</span>
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" />
</div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">创建时间</span>
<span class="mobile-card__value">{{ formatDate(item.createTime) }}</span>
</div>
</div>
<div class="mobile-card__header"><span class="mobile-card__name">{{ item.name || '-' }}</span><dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="item.status" /></div>
<div class="mobile-card__body"><div class="mobile-card__row"><span class="mobile-card__label">创建时间</span><span class="mobile-card__value">{{ formatDate(item.createTime) }}</span></div></div>
<div class="mobile-card__footer">
<el-button size="small" type="primary" @click.stop="openForm('update', item.id)" v-hasPermi="['erp:product-unit:update']">编辑</el-button>
<el-button size="small" type="danger" @click.stop="handleDelete(item.id)" v-hasPermi="['erp:product-unit:delete']">删除</el-button>
</div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-pagination" v-if="total > 0">
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" />
</div>
<!-- 筛选抽屉 -->
<div class="mobile-pagination" v-if="total > 0"><Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" /></div>
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="50%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="单位状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择单位状态" clearable style="width:100%">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
<el-form-item label="单位状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择单位状态" clearable style="width:100%"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
</el-form>
<template #footer><el-button @click="resetQuery">重置</el-button><el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button></template>
</el-drawer>
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="单位名字" prop="name"><el-input v-model="queryParams.name" placeholder="请输入单位名字" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="单位状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择单位状态" clearable class="!w-240px"><el-option v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :label="dict.label" :value="dict.value" /></el-select></el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:product-unit:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:product-unit:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="handleFilterConfirm">确认筛选</el-button>
</template>
</el-drawer>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="名字" align="center" prop="name" />
<el-table-column label="状态" align="center" prop="status"><template #default="scope"><dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /></template></el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" :formatter="dateFormatter" width="180px" sortable />
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:product-unit:update']">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:product-unit:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<ProductUnitForm ref="formRef" @success="getList" />
</div>
<!-- 表单弹窗添加/修改 -->
<ProductUnitForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import { ProductUnitApi, ProductUnitVO } from '@/api/erp/product/unit'
import ProductUnitForm from './ProductUnitForm.vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品单位列表 */
defineOptions({ name: 'ErpProductUnit' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -145,11 +144,16 @@ const handleDelete = async (id: number) => {
} catch {}
}
/** 卡片点击 */
/** 卡片点击(移动端) */
const handleCardClick = (row: ProductUnitVO) => {
openForm('update', row.id)
}
/** 行点击(PC端) */
const handleRowClick = (row: ProductUnitVO) => {
openForm('update', row.id)
}
/** 格式化日期 */
const formatDate = (date: any) => {
if (!date) return '-'

View File

@@ -1,73 +1,63 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle" width="100%" fullscreen class="mobile-eval-form-dialog">
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form-wrapper" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基本信息</div>
<el-form-item label="供应商" prop="supplierName">
<el-input v-model="formData.supplierName" disabled />
</el-form-item>
<el-form-item label="订单单号" prop="orderNo">
<el-input v-model="formData.orderNo" disabled />
</el-form-item>
<el-form-item label="供应商" prop="supplierName"><el-input v-model="formData.supplierName" disabled /></el-form-item>
<el-form-item label="订单单号" prop="orderNo"><el-input v-model="formData.orderNo" disabled /></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">评分标准满分10分</div>
<el-form-item label="质量评分" prop="qualityScore">
<div class="rating-container">
<el-rate v-model="formData.qualityScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">产品质量规格符合度缺陷率等</div>
</div>
</el-form-item>
<el-form-item label="服务评分" prop="serviceScore">
<div class="rating-container">
<el-rate v-model="formData.serviceScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">售前售后服务响应速度专业程度等</div>
</div>
</el-form-item>
<el-form-item label="价格评分" prop="priceScore">
<div class="rating-container">
<el-rate v-model="formData.priceScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">价格合理性性价比优惠政策等</div>
</div>
</el-form-item>
<el-form-item label="交付评分" prop="deliveryScore">
<div class="rating-container">
<el-rate v-model="formData.deliveryScore" :max="10" show-score score-template="{value}分" allow-half />
<div class="rating-desc">交付及时性包装质量物流配送等</div>
</div>
</el-form-item>
<el-form-item label="质量评分" prop="qualityScore"><div class="rating-container"><el-rate v-model="formData.qualityScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">产品质量规格符合度缺陷率等</div></div></el-form-item>
<el-form-item label="服务评分" prop="serviceScore"><div class="rating-container"><el-rate v-model="formData.serviceScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">售前售后服务响应速度专业程度等</div></div></el-form-item>
<el-form-item label="价格评分" prop="priceScore"><div class="rating-container"><el-rate v-model="formData.priceScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">价格合理性性价比优惠政策等</div></div></el-form-item>
<el-form-item label="交付评分" prop="deliveryScore"><div class="rating-container"><el-rate v-model="formData.deliveryScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">交付及时性包装质量物流配送等</div></div></el-form-item>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">综合评分</div>
<div class="total-score">
<span class="score-value">{{ totalScore.toFixed(1) }}</span>
<span class="score-level">{{ getScoreLevel(totalScore) }}</span>
</div>
<div class="total-score"><span class="score-value">{{ totalScore.toFixed(1) }}</span><span class="score-level">{{ getScoreLevel(totalScore) }}</span></div>
</div>
<div class="mobile-form-section">
<div class="mobile-form-section__title">评价备注</div>
<el-form-item prop="remark">
<el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入评价备注(可选)" maxlength="500" show-word-limit />
</el-form-item>
<el-form-item prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入评价备注(可选)" maxlength="500" show-word-limit /></el-form-item>
</div>
</el-form>
</div>
<template #footer>
<div class="mobile-form-footer">
<el-button @click="dialogVisible = false" style="flex:1">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading" style="flex:1">确定</el-button>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else v-model="dialogVisible" :title="dialogTitle" width="600px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="供应商" prop="supplierName"><el-input v-model="formData.supplierName" disabled /></el-form-item>
<el-form-item label="订单单号" prop="orderNo"><el-input v-model="formData.orderNo" disabled /></el-form-item>
<el-divider content-position="left">评分标准满分10分</el-divider>
<el-form-item label="质量评分" prop="qualityScore"><div class="rating-container"><el-rate v-model="formData.qualityScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">产品质量规格符合度缺陷率等</div></div></el-form-item>
<el-form-item label="服务评分" prop="serviceScore"><div class="rating-container"><el-rate v-model="formData.serviceScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">售前售后服务响应速度专业程度等</div></div></el-form-item>
<el-form-item label="价格评分" prop="priceScore"><div class="rating-container"><el-rate v-model="formData.priceScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">价格合理性性价比优惠政策等</div></div></el-form-item>
<el-form-item label="交付评分" prop="deliveryScore"><div class="rating-container"><el-rate v-model="formData.deliveryScore" :max="10" show-score score-template="{value}分" allow-half /><div class="rating-desc">交付及时性包装质量物流配送等</div></div></el-form-item>
<el-form-item label="综合评分" prop="totalScore"><div class="total-score"><span class="score-value">{{ totalScore.toFixed(1) }}</span><span class="score-level">{{ getScoreLevel(totalScore) }}</span></div></el-form-item>
<el-form-item label="评价备注" prop="remark"><el-input v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入评价备注(可选)" maxlength="500" show-word-limit /></el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading">确定</el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SupplierEvaluationApi, SupplierEvaluationVO } from '@/api/erp/purchase/supplierEvaluation'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
interface SupplierEvaluationForm {
id?: number
@@ -222,10 +212,19 @@ defineExpose({ open })
border-bottom: 1px solid #f0f0f0;
}
}
.mobile-form-footer {
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
padding: 0 4px;
z-index: 10;
margin: 0 -4px -12px;
.el-button { flex: 1; height: 40px; font-size: 15px; }
}
.rating-container {
display: flex;

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-evaluation">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-evaluation">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -135,11 +136,96 @@
<!-- 供应商汇总表弹窗 -->
<SupplierSummaryTable ref="summaryRef" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="queryParams.supplierId" clearable filterable placeholder="请选择供应商" class="!w-240px">
<el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="采购订单" prop="purchaseOrderId">
<el-input v-model="queryParams.purchaseOrderNo" placeholder="请输入采购订单号" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="评价时间" prop="createTime">
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
</el-form-item>
<el-form-item label="评分范围" prop="scoreRange">
<el-select v-model="queryParams.scoreRange" placeholder="请选择评分范围" clearable class="!w-240px">
<el-option label="优秀 (9.0-10.0)" value="excellent" />
<el-option label="良好 (8.0-8.9)" value="good" />
<el-option label="一般 (7.0-7.9)" value="average" />
<el-option label="及格 (6.0-6.9)" value="pass" />
<el-option label="不及格 (0-5.9)" value="fail" />
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select v-model="queryParams.creator" clearable filterable placeholder="请选择创建人" class="!w-240px">
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:supplier-evaluation:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
<el-button type="info" plain @click="showStatistics = !showStatistics"><Icon icon="ep:data-analysis" class="mr-5px" /> {{ showStatistics ? '隐藏统计' : '显示统计' }}</el-button>
<el-button type="primary" plain @click="openSupplierSummary" v-hasPermi="['erp:supplier-evaluation:query']"><Icon icon="ep:grid" class="mr-5px" /> 供应商汇总表</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 统计信息 -->
<ContentWrap v-if="showStatistics">
<el-row :gutter="20" class="mb-4">
<el-col :span="6"><el-card class="statistics-card"><div class="statistics-content"><div class="statistics-value">{{ statistics.totalEvaluations }}</div><div class="statistics-label">总评价数</div></div><Icon icon="ep:document" class="statistics-icon" /></el-card></el-col>
<el-col :span="6"><el-card class="statistics-card"><div class="statistics-content"><div class="statistics-value">{{ statistics.avgTotalScore }}</div><div class="statistics-label">平均总分</div></div><Icon icon="ep:star" class="statistics-icon" /></el-card></el-col>
<el-col :span="6"><el-card class="statistics-card"><div class="statistics-content"><div class="statistics-value">{{ statistics.excellentCount }}</div><div class="statistics-label">优秀评价</div></div><Icon icon="ep:trophy" class="statistics-icon" /></el-card></el-col>
<el-col :span="6"><el-card class="statistics-card"><div class="statistics-content"><div class="statistics-value">{{ statistics.supplierCount }}</div><div class="statistics-label">评价供应商</div></div><Icon icon="ep:office-building" class="statistics-icon" /></el-card></el-col>
</el-row>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange">
<el-table-column width="30" label="选择" type="selection" />
<el-table-column label="供应商" align="center" prop="supplierName" min-width="120" />
<el-table-column label="采购订单号" align="center" prop="orderNo" min-width="140" />
<el-table-column label="质量评分" align="center" prop="qualityScore" width="80"><template #default="scope"><el-tag :type="getScoreTagType(scope.row.qualityScore)">{{ scope.row.qualityScore }}</el-tag></template></el-table-column>
<el-table-column label="服务评分" align="center" prop="serviceScore" width="80"><template #default="scope"><el-tag :type="getScoreTagType(scope.row.serviceScore)">{{ scope.row.serviceScore }}</el-tag></template></el-table-column>
<el-table-column label="价格评分" align="center" prop="priceScore" width="80"><template #default="scope"><el-tag :type="getScoreTagType(scope.row.priceScore)">{{ scope.row.priceScore }}</el-tag></template></el-table-column>
<el-table-column label="交付评分" align="center" prop="deliveryScore" width="80"><template #default="scope"><el-tag :type="getScoreTagType(scope.row.deliveryScore)">{{ scope.row.deliveryScore }}</el-tag></template></el-table-column>
<el-table-column label="综合评分" align="center" prop="totalScore" width="100"><template #default="scope"><div class="total-score-cell"><el-tag :type="getScoreTagType(scope.row.totalScore)" size="large">{{ scope.row.totalScore }}</el-tag><div class="score-level">{{ getScoreLevel(scope.row.totalScore) }}</div></div></template></el-table-column>
<el-table-column label="评价备注" align="center" prop="remark" min-width="150"><template #default="scope"><span v-if="scope.row.remark">{{ scope.row.remark }}</span><span v-else class="text-gray-400">无备注</span></template></el-table-column>
<el-table-column label="评价时间" align="center" prop="createTime" :formatter="dateFormatter2" width="120px" sortable />
<el-table-column label="评价人" align="center" prop="creatorName" width="100" />
<el-table-column label="操作" align="center" fixed="right" width="160">
<template #default="scope">
<el-button link @click="openDetail(scope.row)" v-hasPermi="['erp:supplier-evaluation:query']">详情</el-button>
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:supplier-evaluation:update']">编辑</el-button>
<el-button link type="danger" @click="handleDelete([scope.row.id])" v-hasPermi="['erp:supplier-evaluation:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<!-- 表单弹窗编辑 -->
<SupplierEvaluationForm ref="formRef" @success="getList" />
<!-- 详情弹窗 -->
<SupplierEvaluationDetail ref="detailRef" />
<!-- 供应商汇总表弹窗 -->
<SupplierSummaryTable ref="summaryRef" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, DataAnalysis } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { SupplierEvaluationApi, SupplierEvaluationVO } from '@/api/erp/purchase/supplierEvaluation'
import SupplierEvaluationForm from './SupplierEvaluationForm.vue'
@@ -148,10 +234,14 @@ import SupplierSummaryTable from './SupplierSummaryTable.vue'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
/** ERP 供应商评价记录列表 */
defineOptions({ name: 'ErpSupplierEvaluationList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const { t } = useI18n()
@@ -267,6 +357,9 @@ const handleExport = async () => {
}
const selectionList = ref<SupplierEvaluationVO[]>([])
const handleSelectionChange = (rows: SupplierEvaluationVO[]) => {
selectionList.value = rows
}
const getScoreTagType = (score: number) => {
if (score >= 9) return 'success'

View File

@@ -1,175 +1,37 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="入库单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="入库时间" prop="inTime">
<el-date-picker
v-model="formData.inTime"
type="date"
value-format="x"
placeholder="选择入库时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input readonly>
<template #prefix>
<el-link
v-if="formData.orderNo && formData.orderId"
type="primary"
:underline="false"
@click.stop="openPurchaseOrderDetail"
>
{{ formData.orderNo }}
</el-link>
</template>
<template #append>
<el-button @click="openPurchaseOrderInEnableList">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
clearable
filterable
disabled
placeholder="请选择供应商"
style="width: 100%"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="入库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="入库时间" prop="inTime"><el-date-picker v-model="formData.inTime" type="date" value-format="x" placeholder="选择入库时间" style="width:100%" /></el-form-item>
<el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderNo && formData.orderId" type="primary" :underline="false" @click.stop="openPurchaseOrderDetail">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openPurchaseOrderInEnableList"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable disabled placeholder="请选择供应商" style="width:100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 入库产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">入库产品清单</div>
<PurchaseInItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 费用信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">费用信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number
v-model="formData.discountPercent"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入优惠率"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="付款优惠" prop="discountPrice">
<el-input
disabled
v-model="formData.discountPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
<el-form-item label="优惠后金额">
<el-input
disabled
:model-value="formData.totalPrice - formData.otherPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
<el-form-item label="其它费用" prop="otherPrice">
<el-input-number
v-model="formData.otherPrice"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入其它费用"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="formData.accountId"
clearable
filterable
placeholder="请选择结算账户"
style="width: 100%"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="应付金额">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="付款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width:100%" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="应付金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
</div>
<!-- 审核信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">审核信息</div>
<el-form-item label="审核状态">
<el-tag
:type="formData.status === 10 ? 'info' : (formData.isQualified ? 'success' : 'danger')"
>
{{ formData.status === 10 ? '未审核' : (formData.isQualified ? '已审核' : '不合格') }}
</el-tag>
</el-form-item>
<el-form-item label="返回方式" v-if="formData.status !== 10 && !formData.isQualified">
<span>{{ RETURN_TYPE_OPTIONS.find(item => item.value === formData.returnType)?.label || '-' }}</span>
</el-form-item>
<el-form-item label="返回备注" v-if="formData.status !== 10 && !formData.isQualified">
<el-input
type="textarea"
v-model="formData.returnRemark"
:rows="3"
disabled
placeholder="无"
/>
</el-form-item>
<el-form-item label="审核状态"><el-tag :type="formData.status === 10 ? 'info' : (formData.isQualified ? 'success' : 'danger')">{{ formData.status === 10 ? '未审核' : (formData.isQualified ? '已审核' : '不合格') }}</el-tag></el-form-item>
<el-form-item label="返回方式" v-if="formData.status !== 10 && !formData.isQualified"><span>{{ RETURN_TYPE_OPTIONS.find(item => item.value === formData.returnType)?.label || '-' }}</span></el-form-item>
<el-form-item label="返回备注" v-if="formData.status !== 10 && !formData.isQualified"><el-input type="textarea" v-model="formData.returnRemark" :rows="3" disabled placeholder="无" /></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
@@ -177,12 +39,44 @@
</div>
</el-drawer>
<!-- 可入库的订单列表 -->
<PurchaseOrderInEnableList
ref="purchaseOrderInEnableListRef"
@success="handlePurchaseOrderChange"
/>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="入库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="入库时间" prop="inTime"><el-date-picker v-model="formData.inTime" type="date" value-format="x" placeholder="选择入库时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderNo && formData.orderId" type="primary" :underline="false" @click.stop="openPurchaseOrderDetail" class="order-link">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openPurchaseOrderInEnableList"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable disabled placeholder="请选择供应商" class="!w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="入库产品清单" name="item"><PurchaseInItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="付款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="应付金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="审核状态"><el-tag :type="formData.status === 10 ? 'info' : (formData.isQualified ? 'success' : 'danger')">{{ formData.status === 10 ? '未审核' : (formData.isQualified ? '已审核' : '不合格') }}</el-tag></el-form-item></el-col>
<el-col :span="8" v-if="formData.status !== 10 && !formData.isQualified"><el-form-item label="返回方式"><span>{{ RETURN_TYPE_OPTIONS.find(item => item.value === formData.returnType)?.label || '-' }}</span></el-form-item></el-col>
<el-col :span="16" v-if="formData.status !== 10 && !formData.isQualified"><el-form-item label="返回备注"><el-input type="textarea" v-model="formData.returnRemark" :rows="2" disabled placeholder="无" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 可入库的订单列表 -->
<PurchaseOrderInEnableList ref="purchaseOrderInEnableListRef" @success="handlePurchaseOrderChange" />
<!-- 采购订单详情弹窗 -->
<PurchaseOrderForm ref="purchaseOrderFormRef" />
</template>
@@ -200,10 +94,14 @@ import { PurchaseOrderVO } from '@/api/erp/purchase/order'
import * as UserApi from '@/api/system/user'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { ElTag } from 'element-plus'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售入库表单 */
/** ERP 采购入库表单 */
defineOptions({ name: 'PurchaseInForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -254,7 +152,7 @@ const formRef = ref() // 表单 Ref
const supplierList = ref<SupplierVO[]>([]) // 供应商列表
const accountList = ref<AccountVO[]>([]) // 账户列表
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
const subTabsName = ref('item')
const itemFormRef = ref()
/** 计算 discountPrice、totalPrice 价格 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -123,25 +116,37 @@
</div>
<!-- 合计 -->
<div class="mobile-item-summary" v-if="formData.length > 0">
<div class="mobile-item-summary__row">
<span>合计数量</span>
<span>{{ erpCountInputFormatter(summaryData.count) }}</span>
</div>
<div class="mobile-item-summary__row">
<span>合计金额</span>
<span>{{ erpPriceInputFormatter(summaryData.totalProductPrice) }}</span>
</div>
<div class="mobile-item-summary__row">
<span>合计税额</span>
<span>{{ erpPriceInputFormatter(summaryData.taxPrice) }}</span>
</div>
<div class="mobile-item-summary__row mobile-item-summary__row--total">
<span>税额合计</span>
<span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span>
</div>
<div class="mobile-item-summary__row"><span>合计数量</span><span>{{ erpCountInputFormatter(summaryData.count) }}</span></div>
<div class="mobile-item-summary__row"><span>合计金额</span><span>{{ erpPriceInputFormatter(summaryData.totalProductPrice) }}</span></div>
<div class="mobile-item-summary__row"><span>合计税额</span><span>{{ erpPriceInputFormatter(summaryData.taxPrice) }}</span></div>
<div class="mobile-item-summary__row mobile-item-summary__row--total"><span>税额合计</span><span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span></div>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-else ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125">
<template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template>
</el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productName" /></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="原数量" fixed="right" min-width="80" v-if="formData[0]?.totalCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.totalCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="已入库" fixed="right" min-width="80" v-if="formData[0]?.inCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.inCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button :disabled="formData.length === 1" @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
import { computed } from 'vue'
@@ -153,6 +158,10 @@ import {
getSumValue
} from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -208,7 +217,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -219,6 +228,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: any) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,22 +1,13 @@
<template>
<div class="mobile-purchase-in">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-purchase-in">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索入库单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索入库单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:purchase-in:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -160,40 +151,256 @@
<!-- 表单弹窗添加/修改 -->
<PurchaseInForm ref="formRef" @success="getList" />
<!-- 审核弹窗 -->
<!-- 审核弹窗(移动端) -->
<el-dialog v-model="auditVisible" title="采购入库审核" width="90%" append-to-body destroy-on-close>
<el-form ref="auditFormRef" :model="auditForm" :rules="auditRules" label-position="top">
<el-form-item label="是否合格" prop="isQualified">
<el-switch v-model="auditForm.isQualified" :active-value="true" :inactive-value="false" @change="handleQualifiedChange" />
</el-form-item>
<el-form-item label="返回方式" prop="returnType">
<el-select v-model="auditForm.returnType" placeholder="请选择返回方式" clearable style="width:100%" :disabled="auditForm.isQualified">
<el-option v-for="option in RETURN_TYPE_OPTIONS" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</el-form-item>
<el-form-item label="返回备注" prop="returnRemark">
<el-input v-model="auditForm.returnRemark" type="textarea" placeholder="请输入返回方式备注" :rows="3" :disabled="auditForm.isQualified" />
</el-form-item>
<el-form-item label="是否合格" prop="isQualified"><el-switch v-model="auditForm.isQualified" :active-value="true" :inactive-value="false" @change="handleQualifiedChange" /></el-form-item>
<el-form-item label="返回方式" prop="returnType"><el-select v-model="auditForm.returnType" placeholder="请选择返回方式" clearable style="width:100%" :disabled="auditForm.isQualified"><el-option v-for="option in RETURN_TYPE_OPTIONS" :key="option.value" :label="option.label" :value="option.value" /></el-select></el-form-item>
<el-form-item label="返回备注" prop="returnRemark"><el-input v-model="auditForm.returnRemark" type="textarea" placeholder="请输入返回方式备注" :rows="3" :disabled="auditForm.isQualified" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="auditVisible = false">取消</el-button>
<el-button type="primary" @click="submitAudit" :loading="auditLoading">确定</el-button>
</template>
<template #footer><el-button @click="auditVisible = false">取消</el-button><el-button type="primary" @click="submitAudit" :loading="auditLoading">确定</el-button></template>
</el-dialog>
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="入库单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入入库单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="入库时间" prop="inTime">
<el-date-picker
v-model="queryParams.inTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="queryParams.supplierId"
clearable
filterable
placeholder="请选择供供应商"
class="!w-240px"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入关联订单"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="queryParams.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-240px"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="付款状态" prop="paymentStatus">
<el-select
v-model="queryParams.paymentStatus"
placeholder="请选择有款状态"
clearable
class="!w-240px"
>
<el-option label="未付款" value="0" />
<el-option label="部分付款" value="1" />
<el-option label="全部付款" value="2" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择审核状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:purchase-in:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:purchase-in:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:purchase-in:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange" @row-click="handleRowClick">
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="入库单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="入库时间" align="center" prop="inTime" :formatter="dateFormatter2" width="120px" sortable />
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="应付金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="已付金额" align="center" prop="paymentPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="未付金额" align="center"><template #default="scope"><span v-if="scope.row.paymentPrice === scope.row.totalPrice">0</span><el-tag type="danger" v-else>{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.paymentPrice) }}</el-tag></template></el-table-column>
<el-table-column label="审核状态" align="center" prop="status" width="120"><template #default="scope"><el-tag :type="scope.row.status === 10 ? 'info' : (scope.row.isQualified ? 'success' : 'danger')">{{ scope.row.status === 10 ? '未审核' : (scope.row.isQualified ? '已审核' : '不合格') }}</el-tag></template></el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button link type="primary" @click="openForm('detail', scope.row.id)" v-hasPermi="['erp:purchase-in:query']">详情</el-button>
<el-button v-if="scope.row.status === 10" link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:purchase-in:update']">修改</el-button>
<el-button v-if="scope.row.status === 10" link type="primary" @click="handleUpdateStatus(scope.row.id, scope.row.status)" v-hasPermi="['erp:purchase-in:update-status']">审核</el-button>
<el-button v-if="scope.row.status === 20 || scope.row.status === 30" link type="warning" @click="handleUpdateStatus(scope.row.id, scope.row.status)" v-hasPermi="['erp:purchase-in:update-status']">反审核</el-button>
<el-button v-if="scope.row.status === 10" link type="danger" @click="handleDelete([scope.row.id])" v-hasPermi="['erp:purchase-in:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<!-- 审核弹窗(PC端) -->
<el-dialog v-model="auditVisible" title="采购入库审核" width="500px" append-to-body destroy-on-close>
<el-form ref="auditFormRef" :model="auditForm" :rules="auditRules" label-width="100px">
<el-form-item label="是否合格" prop="isQualified"><el-switch v-model="auditForm.isQualified" :active-value="true" :inactive-value="false" @change="handleQualifiedChange" /></el-form-item>
<el-form-item label="返回方式" prop="returnType"><el-select v-model="auditForm.returnType" placeholder="请选择返回方式" clearable style="width:100%" :disabled="auditForm.isQualified"><el-option v-for="option in RETURN_TYPE_OPTIONS" :key="option.value" :label="option.label" :value="option.value" /></el-select></el-form-item>
<el-form-item label="返回备注" prop="returnRemark"><el-input v-model="auditForm.returnRemark" type="textarea" placeholder="请输入返回方式备注" :rows="3" :disabled="auditForm.isQualified" /></el-form-item>
</el-form>
<template #footer><el-button @click="auditVisible = false"> </el-button><el-button type="primary" @click="submitAudit" :loading="auditLoading"> </el-button></template>
</el-dialog>
</template>
<!-- 表单弹窗添加/修改 -->
<PurchaseInForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { PurchaseInApi, PurchaseInVO, RETURN_TYPE_OPTIONS } from '@/api/erp/purchase/in'
import PurchaseInForm from './PurchaseInForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
@@ -201,6 +408,7 @@ import { ElMessage, ElMessageBox } from 'element-plus'
import { useMessage } from '@/hooks/web/useMessage'
import { useI18n } from '@/hooks/web/useI18n'
import { ref, reactive, onMounted, onActivated } from 'vue'
import { useWindowSize } from '@vueuse/core'
interface AuditFormData {
id: number
@@ -213,6 +421,9 @@ interface AuditFormData {
/** ERP 销售入库列表 */
defineOptions({ name: 'ErpPurchaseIn' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const { t } = useI18n()
const loading = ref(true)
@@ -311,9 +522,40 @@ const handleDelete = async (ids: number[]) => {
await PurchaseInApi.deletePurchaseIn(ids)
message.success(t('common.delSuccess'))
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<PurchaseInVO[]>([])
const handleSelectionChange = (rows: PurchaseInVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: PurchaseInVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20 || row.status === 30) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const exportParams = selectionList.value.length > 0 ? { ids: selectionList.value.map(item => item.id) } : queryParams
const data = await PurchaseInApi.exportPurchaseIn(exportParams)
download.excel(data, '采购入库.xls')
} catch {} finally {
exportLoading.value = false
}
}
// 审核弹窗相关
const auditVisible = ref(false)
const auditLoading = ref(false)

View File

@@ -1,132 +1,81 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="比价单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="询价时间" prop="inquiryTime">
<el-date-picker
v-model="formData.inquiryTime"
type="date"
value-format="x"
placeholder="选择询价时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="截止日期" prop="deadline">
<el-date-picker
v-model="formData.deadline"
type="date"
value-format="x"
placeholder="选择截止日期"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="formData.productId"
clearable
filterable
placeholder="请选择产品"
style="width: 100%"
@change="onChangeProduct"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="比价单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="询价时间" prop="inquiryTime"><el-date-picker v-model="formData.inquiryTime" type="date" value-format="x" placeholder="选择询价时间" style="width: 100%" /></el-form-item>
<el-form-item label="截止日期" prop="deadline"><el-date-picker v-model="formData.deadline" type="date" value-format="x" placeholder="选择截止日期" style="width: 100%" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="formData.productId" clearable filterable placeholder="请选择产品" style="width: 100%" @change="onChangeProduct"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<div class="mobile-form__input-group">
<el-form-item label="需求数量" prop="requireCount">
<el-input-number
v-model="formData.requireCount"
controls-position="right"
:min="0.0001"
:precision="4"
placeholder="需求数量"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="预算金额" prop="budgetPrice">
<el-input-number
v-model="formData.budgetPrice"
controls-position="right"
:min="0"
:precision="2"
placeholder="预算金额"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="需求数量" prop="requireCount"><el-input-number v-model="formData.requireCount" controls-position="right" :min="0.0001" :precision="4" placeholder="需求数量" style="width: 100%" /></el-form-item>
<el-form-item label="预算金额" prop="budgetPrice"><el-input-number v-model="formData.budgetPrice" controls-position="right" :min="0" :precision="2" placeholder="预算金额" style="width: 100%" /></el-form-item>
</div>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
</div>
<!-- 供应商报价 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">供应商报价</div>
<InquiryQuoteForm ref="quoteFormRef" :quotes="formData.quotes" :disabled="disabled" :require-count="formData.requireCount" />
</div>
<!-- 比价汇总 -->
<div class="mobile-form__section" v-if="formData.quotes && formData.quotes.length > 0">
<div class="mobile-form__section-title">比价汇总</div>
<div class="mobile-form__info-row">
<span class="mobile-form__info-label">报价数量</span>
<span class="mobile-form__info-value">{{ formData.quotes.length }}</span>
</div>
<div class="mobile-form__info-row">
<span class="mobile-form__info-label">最低报价</span>
<span class="mobile-form__info-value" style="color: #67c23a">{{ erpPriceInputFormatter(minQuotePrice) }}</span>
</div>
<div class="mobile-form__info-row">
<span class="mobile-form__info-label">最高报价</span>
<span class="mobile-form__info-value" style="color: #e6a23c">{{ erpPriceInputFormatter(maxQuotePrice) }}</span>
</div>
<div class="mobile-form__info-row"><span class="mobile-form__info-label">报价数量</span><span class="mobile-form__info-value">{{ formData.quotes.length }}</span></div>
<div class="mobile-form__info-row"><span class="mobile-form__info-label">最低报价</span><span class="mobile-form__info-value" style="color: #67c23a">{{ erpPriceInputFormatter(minQuotePrice) }}</span></div>
<div class="mobile-form__info-row"><span class="mobile-form__info-label">最高报价</span><span class="mobile-form__info-value" style="color: #e6a23c">{{ erpPriceInputFormatter(maxQuotePrice) }}</span></div>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1200">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="比价单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="询价时间" prop="inquiryTime"><el-date-picker v-model="formData.inquiryTime" type="date" value-format="x" placeholder="选择询价时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="截止日期" prop="deadline"><el-date-picker v-model="formData.deadline" type="date" value-format="x" placeholder="选择截止日期" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="产品" prop="productId"><el-select v-model="formData.productId" clearable filterable placeholder="请选择产品" class="!w-1/1" @change="onChangeProduct"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="需求数量" prop="requireCount"><el-input-number v-model="formData.requireCount" controls-position="right" :min="0.0001" :precision="4" placeholder="请输入需求数量" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="预算金额" prop="budgetPrice"><el-input-number v-model="formData.budgetPrice" controls-position="right" :min="0" :precision="2" placeholder="请输入预算金额" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="供应商报价" name="quote"><InquiryQuoteForm ref="quoteFormRef" :quotes="formData.quotes" :disabled="disabled" :require-count="formData.requireCount" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20" v-if="formData.quotes && formData.quotes.length > 0">
<el-col :span="8"><el-form-item label="报价数量"><el-input disabled :value="formData.quotes.length" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="最低报价"><el-input disabled :value="minQuotePrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="最高报价"><el-input disabled :value="maxQuotePrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { nextTick } from 'vue'
import { nextTick, computed } from 'vue'
import { PurchaseInquiryApi, PurchaseInquiryVO } from '@/api/erp/purchase/inquiry'
import InquiryQuoteForm from './components/InquiryQuoteForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { erpPriceInputFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
/** ERP 采购比价表单 */
defineOptions({ name: 'InquiryForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -166,7 +115,7 @@ const formRules = reactive({
const disabled = computed(() => formType.value === 'detail')
const formRef = ref() // 表单 Ref
const productList = ref<ProductVO[]>([]) // 产品列表
const subTabsName = ref('quote') // PC端子表标签
const quoteFormRef = ref()
/** 计算最低报价 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-quote-list">
<div
v-for="(row, $index) in formData"
@@ -118,20 +111,50 @@
</div>
<!-- 添加按钮 -->
<div class="mobile-quote-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加供应商报价</el-button>
</div>
<div class="mobile-quote-add" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加供应商报价</el-button></div>
</div>
</el-form>
<!-- PC端布局 -->
<template v-else>
<el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px" :row-class-name="tableRowClassName">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="选中" width="70" align="center"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.isSelected`" class="mb-0px!"><el-checkbox v-model="row.isSelected" @change="onSelectChange(row, $index)" /></el-form-item></template></el-table-column>
<el-table-column label="供应商" min-width="200"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.supplierId`" :rules="formRules.supplierId" class="mb-0px!"><el-select v-model="row.supplierId" clearable filterable @change="onChangeSupplier($event, row)" placeholder="请选择供应商" class="!w-full"><template #prefix v-if="!disabled"><el-button type="primary" link size="small" @click.stop="openQuickSupplierForm($index)" title="快速新增供应商" class="!p-0 !m-0"><Icon icon="ep:plus" /></el-button></template><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="联系人" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.contactName`" class="mb-0px!"><el-input v-model="row.contactName" placeholder="联系人" /></el-form-item></template></el-table-column>
<el-table-column label="联系电话" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.contactPhone`" class="mb-0px!"><el-input v-model="row.contactPhone" placeholder="联系电话" /></el-form-item></template></el-table-column>
<el-table-column label="报价日期" min-width="160"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.quoteDate`" class="mb-0px!"><el-date-picker v-model="row.quoteDate" type="date" value-format="x" placeholder="报价日期" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="单价" prop="unitPrice" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.unitPrice`" :rules="formRules.unitPrice" class="mb-0px!"><el-input-number v-model="row.unitPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" placeholder="单价" /></el-form-item></template></el-table-column>
<el-table-column label="总价" prop="totalPrice" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="付款条件" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.paymentTerms`" class="mb-0px!"><el-select v-model="row.paymentTerms" placeholder="付款条件" clearable><el-option label="款到发货" value="款到发货" /><el-option label="货到付款" value="货到付款" /><el-option label="月结30天" value="月结30天" /><el-option label="月结60天" value="月结60天" /><el-option label="月结90天" value="月结90天" /><el-option label="预付30%" value="预付30%" /><el-option label="预付50%" value="预付50%" /><el-option label="其他" value="其他" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="交货周期(天)" min-width="130"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.deliveryCycle`" class="mb-0px!"><el-input-number v-model="row.deliveryCycle" controls-position="right" :min="0" :precision="0" class="!w-100%" placeholder="天数" /></el-form-item></template></el-table-column>
<el-table-column label="资质文件" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.qualificationFile`" class="mb-0px!"><UploadFile :is-show-tip="false" v-model="row.qualificationFile" :limit="1" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column label="质量评分" width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.qualityScore`" class="mb-0px!"><el-input-number v-model="row.qualityScore" controls-position="right" :min="0" :max="100" :precision="0" class="!w-100%" placeholder="0-100" /></el-form-item></template></el-table-column>
<el-table-column label="服务评分" width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.serviceScore`" class="mb-0px!"><el-input-number v-model="row.serviceScore" controls-position="right" :min="0" :max="100" :precision="0" class="!w-100%" placeholder="0-100" /></el-form-item></template></el-table-column>
<el-table-column label="价格得分" width="90" align="center"><template #default="{ row }"><span :class="row.priceScore >= 100 ? 'text-green-600 font-bold' : ''">{{ row.priceScore?.toFixed(2) ?? '-' }}</span></template></el-table-column>
<el-table-column label="交付得分" width="90" align="center"><template #default="{ row }"><span :class="row.deliveryScore >= 100 ? 'text-green-600 font-bold' : ''">{{ row.deliveryScore?.toFixed(2) ?? '-' }}</span></template></el-table-column>
<el-table-column label="综合得分" width="100" align="center"><template #default="{ row }"><el-tag v-if="row.totalScore != null" :type="row.isSelected ? 'success' : 'info'">{{ row.totalScore?.toFixed(2) }}</el-tag><span v-else class="text-gray-400">-</span></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加供应商报价</el-button></el-row>
</template>
<!-- 快速新增供应商弹窗 -->
<QuickSupplierForm ref="quickSupplierFormRef" @success="onQuickSupplierSuccess" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { SupplierEvaluationApi } from '@/api/erp/purchase/supplierEvaluation'
import { erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { PurchaseInquiryQuoteVO } from '@/api/erp/purchase/inquiry'
import QuickSupplierForm from './QuickSupplierForm.vue'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = withDefaults(
defineProps<{
@@ -241,11 +264,25 @@ watch(
}
)
/** 合计总价 */
/** 合计总价 - 移动端 */
const summaryTotalPrice = computed(() => {
return getSumValue(formData.value.map((item) => Number(item.totalPrice || 0)))
})
/** 合计 - PC端 */
const getSummaries = (param: any) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row: PurchaseInquiryQuoteVO = {

View File

@@ -1,34 +1,13 @@
<template>
<el-drawer
v-model="dialogVisible"
title="快速新增供应商"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" title="快速新增供应商" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true">
<div class="mobile-quick-supplier" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<el-form-item label="供应商名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入供应商名称" />
</el-form-item>
<el-form-item label="联系人" prop="contact">
<el-input v-model="formData.contact" placeholder="请输入联系人" />
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="formData.mobile" placeholder="请输入手机号码" />
</el-form-item>
<el-form-item label="联系电话" prop="telephone">
<el-input v-model="formData.telephone" placeholder="请输入联系电话" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="2" />
</el-form-item>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<el-form-item label="供应商名称" prop="name"><el-input v-model="formData.name" placeholder="请输入供应商名称" /></el-form-item>
<el-form-item label="联系人" prop="contact"><el-input v-model="formData.contact" placeholder="请输入联系人" /></el-form-item>
<el-form-item label="手机号码" prop="mobile"><el-input v-model="formData.mobile" placeholder="请输入手机号码" /></el-form-item>
<el-form-item label="联系电话" prop="telephone"><el-input v-model="formData.telephone" placeholder="请输入联系电话" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="2" /></el-form-item>
</el-form>
</div>
<template #footer>
@@ -36,14 +15,34 @@
<el-button @click="submitForm" type="primary" :loading="formLoading"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="快速新增供应商" v-model="dialogVisible" width="500px">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="供应商名称" prop="name"><el-input v-model="formData.name" placeholder="请输入供应商名称" /></el-form-item>
<el-form-item label="联系人" prop="contact"><el-input v-model="formData.contact" placeholder="请输入联系人" /></el-form-item>
<el-form-item label="手机号码" prop="mobile"><el-input v-model="formData.mobile" placeholder="请输入手机号码" /></el-form-item>
<el-form-item label="联系电话" prop="telephone"><el-input v-model="formData.telephone" placeholder="请输入联系电话" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="2" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :loading="formLoading"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'QuickSupplierForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const dialogVisible = ref(false)

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-purchase-inquiry">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-purchase-inquiry">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -12,41 +13,15 @@
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
:class="{ active: queryParams.status === undefined }"
@click="handleQuickFilter(undefined)"
>
全部订单
</div>
<div
class="quick-filter-item"
:class="{ active: queryParams.status === 10 }"
@click="handleQuickFilter(10)"
>
待询价
</div>
<div
class="quick-filter-item"
:class="{ active: queryParams.status === 20 }"
@click="handleQuickFilter(20)"
>
询价中
</div>
<div
class="quick-filter-item"
:class="{ active: queryParams.status === 30 }"
@click="handleQuickFilter(30)"
>
已完成
</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部订单</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待询价</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 20 }" @click="handleQuickFilter(20)">询价中</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 30 }" @click="handleQuickFilter(30)">已完成</div>
</div>
<!-- 卡片列表 -->
<div class="mobile-list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-empty">
<el-empty description="暂无比价记录" />
</div>
<div v-if="list.length === 0 && !loading" class="mobile-empty"><el-empty description="暂无比价记录" /></div>
<div v-for="item in list" :key="item.id" class="mobile-card" @click="handleCardClick(item)">
<div class="mobile-card__header">
<span class="mobile-card__no">{{ item.no }}</span>
@@ -55,39 +30,15 @@
<el-tag v-else-if="item.status === 30" type="success" size="small">已完成</el-tag>
</div>
<div class="mobile-card__body">
<div class="mobile-card__row">
<span class="mobile-card__label">产品</span>
<span class="mobile-card__value">{{ item.productName || '-' }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">询价时间</span>
<span class="mobile-card__value">{{ formatDate2(item.inquiryTime) }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">截止日期</span>
<span class="mobile-card__value">{{ formatDate2(item.deadline) }}</span>
</div>
<div class="mobile-card__row">
<span class="mobile-card__label">创建人</span>
<span class="mobile-card__value">{{ item.creatorName || '-' }}</span>
</div>
<div class="mobile-card__row"><span class="mobile-card__label">产品</span><span class="mobile-card__value">{{ item.productName || '-' }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">询价时间</span><span class="mobile-card__value">{{ formatDate2(item.inquiryTime) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">截止日期</span><span class="mobile-card__value">{{ formatDate2(item.deadline) }}</span></div>
<div class="mobile-card__row"><span class="mobile-card__label">创建人</span><span class="mobile-card__value">{{ item.creatorName || '-' }}</span></div>
<div class="mobile-card__nums">
<div class="mobile-card__num-item">
<div class="mobile-card__num-val">{{ erpCountInputFormatter(item.requireCount) }}</div>
<div class="mobile-card__num-label">需求数量</div>
</div>
<div class="mobile-card__num-item">
<div class="mobile-card__num-val mobile-card__num-val--price">¥{{ erpPriceInputFormatter(item.budgetPrice) }}</div>
<div class="mobile-card__num-label">预算金额</div>
</div>
<div class="mobile-card__num-item">
<div class="mobile-card__num-val">{{ item.quoteCount || 0 }}</div>
<div class="mobile-card__num-label">报价数</div>
</div>
<div class="mobile-card__num-item">
<div class="mobile-card__num-val" style="color:#67c23a">¥{{ erpPriceInputFormatter(item.minQuotePrice) }}</div>
<div class="mobile-card__num-label">最低报价</div>
</div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val">{{ erpCountInputFormatter(item.requireCount) }}</div><div class="mobile-card__num-label">需求数量</div></div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val mobile-card__num-val--price">¥{{ erpPriceInputFormatter(item.budgetPrice) }}</div><div class="mobile-card__num-label">预算金额</div></div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val">{{ item.quoteCount || 0 }}</div><div class="mobile-card__num-label">报价数</div></div>
<div class="mobile-card__num-item"><div class="mobile-card__num-val" style="color:#67c23a">¥{{ erpPriceInputFormatter(item.minQuotePrice) }}</div><div class="mobile-card__num-label">最低报价</div></div>
</div>
</div>
<div class="mobile-card__footer">
@@ -109,26 +60,10 @@
<!-- 筛选抽屉 -->
<el-drawer v-model="filterVisible" title="筛选条件" direction="btt" size="60%">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="产品" prop="productId">
<el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" style="width:100%">
<el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="询价时间" prop="inquiryTime">
<el-date-picker v-model="queryParams.inquiryTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始" end-placeholder="结束" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width:100%" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width:100%">
<el-option label="待询价" :value="10" />
<el-option label="询价中" :value="20" />
<el-option label="已完成" :value="30" />
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select v-model="queryParams.creator" clearable filterable placeholder="请选择创建人" style="width:100%">
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" style="width:100%"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="询价时间" prop="inquiryTime"><el-date-picker v-model="queryParams.inquiryTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始" end-placeholder="结束" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width:100%" /></el-form-item>
<el-form-item label="状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择状态" clearable style="width:100%"><el-option label="待询价" :value="10" /><el-option label="询价中" :value="20" /><el-option label="已完成" :value="30" /></el-select></el-form-item>
<el-form-item label="创建人" prop="creator"><el-select v-model="queryParams.creator" clearable filterable placeholder="请选择创建人" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
@@ -141,11 +76,73 @@
<!-- 自动比价弹窗 -->
<AutoCompareDialog ref="autoCompareRef" @success="getList" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="比价单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入比价单号" clearable @keyup.enter="handleQuery" class="!w-240px" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-240px"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="询价时间" prop="inquiryTime"><el-date-picker v-model="queryParams.inquiryTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" /></el-form-item>
<el-form-item label="状态" prop="status"><el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px"><el-option label="待询价" :value="10" /><el-option label="询价中" :value="20" /><el-option label="已完成" :value="30" /></el-select></el-form-item>
<el-form-item label="创建人" prop="creator"><el-select v-model="queryParams.creator" clearable filterable placeholder="请选择创建人" class="!w-240px"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:purchase-inquiry:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:purchase-inquiry:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
<el-button type="danger" plain @click="handleDelete(selectionList.map((item) => item.id))" v-hasPermi="['erp:purchase-inquiry:delete']" :disabled="selectionList.length === 0"><Icon icon="ep:delete" class="mr-5px" /> 删除</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange" @row-click="handleRowClick">
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="比价单号" align="center" prop="no" />
<el-table-column label="产品名称" align="center" prop="productName" min-width="150" />
<el-table-column label="需求数量" align="center" prop="requireCount" :formatter="erpCountTableColumnFormatter" width="100" />
<el-table-column label="预算金额" align="center" prop="budgetPrice" :formatter="erpPriceTableColumnFormatter" width="120" />
<el-table-column label="询价时间" align="center" prop="inquiryTime" :formatter="dateFormatter2" width="120" sortable />
<el-table-column label="截止日期" align="center" prop="deadline" :formatter="dateFormatter2" width="120" sortable />
<el-table-column label="报价数量" align="center" prop="quoteCount" width="100" />
<el-table-column label="最低报价" align="center" prop="minQuotePrice" :formatter="erpPriceTableColumnFormatter" width="120" />
<el-table-column label="创建人" align="center" prop="creatorName" width="100" />
<el-table-column label="状态" align="center" fixed="right" width="100" prop="status">
<template #default="scope">
<el-tag v-if="scope.row.status === 10" type="info">待询价</el-tag>
<el-tag v-else-if="scope.row.status === 20" type="warning">询价中</el-tag>
<el-tag v-else-if="scope.row.status === 30" type="success">已完成</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="300">
<template #default="scope">
<el-button link @click="openForm('detail', scope.row.id)" v-hasPermi="['erp:purchase-inquiry:query']">详情</el-button>
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:purchase-inquiry:update']" :disabled="scope.row.status === 30">编辑</el-button>
<el-button link type="primary" @click="handleUpdateStatus(scope.row.id, 20)" v-hasPermi="['erp:purchase-inquiry:update-status']" v-if="scope.row.status === 10">询价</el-button>
<el-button link type="warning" @click="openAutoCompare(scope.row.id)" v-hasPermi="['erp:purchase-inquiry:update']" v-if="scope.row.status === 20 && scope.row.quoteCount >= 2">比价</el-button>
<el-button link type="success" @click="handleUpdateStatus(scope.row.id, 30)" v-hasPermi="['erp:purchase-inquiry:update-status']" v-if="scope.row.status === 20">完成</el-button>
<el-button link type="danger" @click="handleDelete([scope.row.id])" v-hasPermi="['erp:purchase-inquiry:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<InquiryForm ref="formRef" @success="getList" />
<!-- 自动比价弹窗 -->
<AutoCompareDialog ref="autoCompareRef" @success="getList" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { PurchaseInquiryApi, PurchaseInquiryVO } from '@/api/erp/purchase/inquiry'
import InquiryForm from './InquiryForm.vue'
@@ -153,11 +150,15 @@ import AutoCompareDialog from './AutoCompareDialog.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
/** ERP 采购比价列表 */
defineOptions({ name: 'ErpPurchaseInquiry' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const { t } = useI18n()
@@ -251,7 +252,10 @@ const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await PurchaseInquiryApi.exportPurchaseInquiry(queryParams)
const exportParams = selectionList.value.length > 0
? { ids: selectionList.value.map(item => item.id) }
: queryParams
const data = await PurchaseInquiryApi.exportPurchaseInquiry(exportParams)
download.excel(data, '采购比价.xls')
} catch {
} finally {
@@ -259,6 +263,25 @@ const handleExport = async () => {
}
}
/** 选中操作 */
const selectionList = ref<PurchaseInquiryVO[]>([])
const handleSelectionChange = (rows: PurchaseInquiryVO[]) => {
selectionList.value = rows
}
/** 行点击操作 */
const handleRowClick = (row: PurchaseInquiryVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) {
return
}
if (row.status === 30) {
openForm('detail', row.id)
} else {
openForm('update', row.id)
}
}
onMounted(async () => {
await getList()
productList.value = await ProductApi.getProductSimpleList()

View File

@@ -1,164 +1,30 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="订单单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="订单时间" prop="orderTime">
<el-date-picker
v-model="formData.orderTime"
type="date"
value-format="x"
placeholder="选择订单时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="关联请购单" prop="purchaseRequisitionNo">
<el-input readonly>
<template #prefix>
<el-link
v-if="formData.purchaseRequisitionId"
type="primary"
:underline="false"
@click.stop="openRequisitionDetail"
>
{{ formData.purchaseRequisitionNo }}
</el-link>
</template>
<template #append>
<el-button @click="openRequisitionSelect">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
<!-- <el-form-item label="关联请购单" prop="purchaseRequisitionNo">-->
<!-- <div class="mobile-form__requisition">-->
<!-- <el-link-->
<!-- v-if="formData.purchaseRequisitionNo && formData.purchaseRequisitionId"-->
<!-- type="primary"-->
<!-- :underline="false"-->
<!-- @click.stop="openRequisitionDetail"-->
<!-- >-->
<!-- {{ formData.purchaseRequisitionNo }}-->
<!-- </el-link>-->
<!-- <span v-else class="mobile-form__requisition-empty">未选择</span>-->
<!-- <el-button size="small" @click="openRequisitionSelect" :disabled="disabled">选择</el-button>-->
<!-- </div>-->
<!-- </el-form-item>-->
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
clearable
filterable
placeholder="请选择供应商"
style="width: 100%"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<div class="mobile-form__tip">*如果没有供应商请忽略此项填写</div>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="3"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="订单单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="formData.orderTime" type="date" value-format="x" placeholder="选择订单时间" style="width:100%" /></el-form-item>
<el-form-item label="关联请购单" prop="purchaseRequisitionNo"><el-input readonly><template #prefix><el-link v-if="formData.purchaseRequisitionId" type="primary" :underline="false" @click.stop="openRequisitionDetail">{{ formData.purchaseRequisitionNo }}</el-link></template><template #append><el-button @click="openRequisitionSelect"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" style="width:100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select><div class="mobile-form__tip">*如果没有供应商请忽略此项填写</div></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="3" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">订单产品清单</div>
<PurchaseOrderItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 费用信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">费用信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number
v-model="formData.discountPercent"
controls-position="right"
:min="0"
:precision="2"
placeholder="请输入优惠率"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="付款优惠" prop="discountPrice">
<el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠后金额">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="formData.accountId"
clearable
filterable
placeholder="请选择结算账户"
style="width: 100%"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="支付订金" prop="depositPrice">
<el-input-number
v-model="formData.depositPrice"
controls-position="right"
:min="0"
:precision="2"
placeholder="请输入支付订金"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="2" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="付款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="支付订金" prop="depositPrice"><el-input-number v-model="formData.depositPrice" controls-position="right" :min="0" :precision="2" placeholder="请输入支付订金" style="width:100%" /></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
@@ -166,13 +32,43 @@
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="订单单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="formData.orderTime" type="date" value-format="x" placeholder="选择订单时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联请购单" prop="purchaseRequisitionNo"><el-input readonly><template #prefix><el-link v-if="formData.purchaseRequisitionNo && formData.purchaseRequisitionId" type="primary" :underline="false" @click.stop="openRequisitionDetail" class="requisition-link">{{ formData.purchaseRequisitionNo }}</el-link></template><template #append><el-button @click="openRequisitionSelect" :disabled="disabled"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" class="!w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select><div style="margin-top:4px;font-size:12px;color:var(--el-color-danger);">*如果没有供应商请忽略此项填写</div></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="3" placeholder="请输入备注(如果有额外的内容填写,请在此文本框里面填写)" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="订单产品清单" name="item"><PurchaseOrderItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="2" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="付款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="支付订金" prop="depositPrice"><el-input-number v-model="formData.depositPrice" controls-position="right" :min="0" :precision="2" placeholder="请输入支付订金" class="!w-1/1" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 请购单选择弹窗 -->
<PurchaseRequisitionTableSelect ref="requisitionSelectRef" @change="onRequisitionSelected" />
<!-- 请购单详情弹窗 -->
<PurchaseRequisitionForm ref="requisitionFormRef" />
</template>
<script setup lang="ts">
import { nextTick } from 'vue'
import { nextTick, computed } from 'vue'
import { PurchaseOrderApi, PurchaseOrderVO } from '@/api/erp/purchase/order'
import PurchaseOrderItemForm from './components/PurchaseOrderItemForm.vue'
import PurchaseRequisitionTableSelect from './components/PurchaseRequisitionTableSelect.vue'
@@ -182,10 +78,14 @@ import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils'
import * as UserApi from '@/api/system/user'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { PurchaseRequisitionApi, PurchaseRequisition } from '@/api/erp/purchaserequisition'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售订单表单 */
/** ERP 采购订单表单 */
defineOptions({ name: 'PurchaseOrderForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -243,7 +143,7 @@ const accountList = ref<AccountVO[]>([]) // 账户列表
const userList = ref<UserApi.UserVO[]>([]) // 用户列表
const requisitionSelectRef = ref() // 请购单选择弹窗Ref
const requisitionFormRef = ref() // 请购单详情弹窗Ref
const subTabsName = ref('item')
const itemFormRef = ref()
/** 计算 discountPrice、totalPrice 价格 */

View File

@@ -1,6 +1,8 @@
<!-- 可入库的订单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择采购订单(仅展示可入库)"
direction="rtl"
@@ -111,15 +113,50 @@
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择采购订单(仅展示可入库)" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1080">
<ContentWrap>
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" class="-mb-15px">
<el-form-item label="订单单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入订单单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="queryParams.orderTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" width="65"><template #default="{ row }"><el-radio :value="row.id" v-model="currentRowValue" @change="handleCurrentChange(row)">&nbsp;</el-radio></template></el-table-column>
<el-table-column label="订单单号" align="center" prop="no" min-width="180" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="订单时间" align="center" prop="orderTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="入库数量" align="center" prop="inCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="金额合计" align="center" prop="totalProductPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="含税金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!currentRow" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { PurchaseOrderApi, PurchaseOrderVO } from '@/api/erp/purchase/order'
import { formatDate } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'ErpPurchaseOrderOutEnableList' })
defineOptions({ name: 'ErpPurchaseOrderInEnableList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const list = ref<PurchaseOrderVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -139,11 +132,32 @@
</div>
<!-- 添加按钮 -->
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加采购产品</el-button>
</div>
<div class="mobile-item-add" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加采购产品</el-button></div>
</div>
</el-form>
<!-- PC端布局 -->
<template v-else>
<el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="供应商" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.supplierName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" :rules="formRules.productPrice" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input-number v-model="row.totalPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" @change="onChangeTotalPrice(row)" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加采购产品</el-button></el-row>
</template>
</template>
<script setup lang="ts">
import { ProductApi, ProductVO } from '@/api/erp/product/product'
@@ -155,6 +169,10 @@ import {
getSumValue
} from '@/utils'
import { computed } from 'vue'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = withDefaults(
defineProps<{
@@ -231,7 +249,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value || []
return {
@@ -242,6 +260,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: any) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row: any = {

View File

@@ -1,6 +1,8 @@
<!-- 可退货的订单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择采购订单(仅展示可退货)"
direction="rtl"
@@ -115,17 +117,53 @@
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择采购订单(仅展示可退货)" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1100">
<ContentWrap>
<el-form :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px" class="-mb-15px">
<el-form-item label="订单单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入订单单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="queryParams.orderTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" width="65"><template #default="{ row }"><el-radio :value="row.id" v-model="currentRowValue" @change="handleCurrentChange(row)">&nbsp;</el-radio></template></el-table-column>
<el-table-column label="订单单号" align="center" prop="no" min-width="180" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="订单时间" align="center" prop="orderTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="入库数量" align="center" prop="inCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="退货数量" align="center" prop="returnCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="金额合计" align="center" prop="totalProductPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="含税金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!currentRow" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { PurchaseOrderApi, PurchaseOrderVO } from '@/api/erp/purchase/order'
import { formatDate } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'PurchaseOrderReturnEnableList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const list = ref<PurchaseOrderVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
const loading = ref(false) // 列表的加载中

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择请购单"
direction="rtl"
@@ -103,16 +105,52 @@
</template>
</el-drawer>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择请购单" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1080">
<ContentWrap>
<el-form :model="queryParams" ref="filterFormRef" :inline="true" label-width="68px" class="-mb-15px">
<el-form-item label="请购单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入请购单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="请购人" prop="requesterName"><el-input v-model="queryParams.requesterName" placeholder="请输入请购人" clearable class="!w-160px" /></el-form-item>
<el-form-item label="请购时间" prop="requestTime"><el-date-picker v-model="queryParams.requestTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" width="65"><template #default="{ row }"><el-radio :value="row.id" v-model="selectedId" @change="handleSingleSelected(row)">&nbsp;</el-radio></template></el-table-column>
<el-table-column label="请购单号" align="center" prop="no" min-width="180" />
<el-table-column label="类型" align="center" prop="type" width="80"><template #default="scope"><el-tag size="small" :type="getTypeTagType(scope.row.type)">{{ getTypeLabel(scope.row.type) }}</el-tag></template></el-table-column>
<el-table-column label="优先级" align="center" prop="priority" width="80"><template #default="scope"><el-tag size="small" :type="getPriorityTagType(scope.row.priority)">{{ getPriorityLabel(scope.row.priority) }}</el-tag></template></el-table-column>
<el-table-column label="请购人" align="center" prop="requesterNickname" width="100" />
<el-table-column label="请购部门" align="center" prop="requesterDeptName" width="120" />
<el-table-column label="请购时间" align="center" prop="requestTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="合计数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="合计金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!currentRow" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { PurchaseRequisitionApi, PurchaseRequisition } from '@/api/erp/purchaserequisition'
import { CHANGE_EVENT } from 'element-plus'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'PurchaseRequisitionTableSelect' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const total = ref(0)
const list = ref<PurchaseRequisition[]>([])
const loading = ref(false)
@@ -128,6 +166,7 @@ const queryParams = ref({
requestTime: []
})
const selectedId = ref()
const currentRow = ref<PurchaseRequisition>()
const formatDate2 = (date: any) => {
if (!date) return '-'
@@ -138,6 +177,7 @@ const formatDate2 = (date: any) => {
const open = (currentNo?: string) => {
dialogVisible.value = true
selectedId.value = undefined
currentRow.value = undefined
if (currentNo) {
queryParams.value.no = currentNo
} else {
@@ -180,9 +220,20 @@ const resetQuery = () => {
/** 单选中时触发 */
const handleSingleSelected = (row: PurchaseRequisition) => {
emits(CHANGE_EVENT, row)
dialogVisible.value = false
if (isMobile.value) {
emits(CHANGE_EVENT, row)
dialogVisible.value = false
}
selectedId.value = row.id
currentRow.value = row
}
/** 提交选择 */
const submitForm = () => {
if (currentRow.value) {
emits(CHANGE_EVENT, currentRow.value)
}
dialogVisible.value = false
}
const emits = defineEmits<{

View File

@@ -1,28 +1,13 @@
<template>
<div class="mobile-purchase-order">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-purchase-order">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索订单单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索订单单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:purchase-order:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:purchase-order:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -195,12 +180,334 @@
<!-- 供应商评价对话框 -->
<SupplierEvaluationDialog ref="supplierEvaluationDialogRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="订单单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入订单单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="订单时间" prop="orderTime">
<el-date-picker
v-model="queryParams.orderTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="queryParams.supplierId"
clearable
filterable
placeholder="请选择供供应商"
class="!w-240px"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="入库数量" prop="inStatus">
<el-select
v-model="queryParams.inStatus"
placeholder="请选择入库数量"
clearable
class="!w-240px"
>
<el-option label="未入库" value="0" />
<el-option label="部分入库" value="1" />
<el-option label="全部入库" value="2" />
</el-select>
</el-form-item>
<el-form-item label="退货数量" prop="returnStatus">
<el-select
v-model="queryParams.returnStatus"
placeholder="请选择退货数量"
clearable
class="!w-240px"
>
<el-option label="未退货" value="0" />
<el-option label="部分退货" value="1" />
<el-option label="全部退货" value="2" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:purchase-order:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:purchase-order:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:purchase-order:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="订单单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column
label="订单时间"
align="center"
prop="orderTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<!-- <el-table-column label="审核人" align="center" prop="auditorName" />-->
<el-table-column
label="总数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="入库数量"
align="center"
prop="inCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="退货数量"
align="center"
prop="returnCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额合计"
align="center"
prop="totalProductPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="含税金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="支付订金"
align="center"
prop="depositPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="380">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:purchase-order:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:purchase-order:update']"
:disabled="scope.row.status === 20 || scope.row.hasApprovalRecords"
>
编辑
</el-button>
<el-button
link
type="success"
@click="handleSubmitApproval(scope.row.id)"
v-hasPermi="['erp:purchase-order:submit-approval']"
v-if="scope.row.status === 10 && !scope.row.hasApprovalRecords"
>
提交审批
</el-button>
<el-button
link
type="info"
@click="handleViewApproval(scope.row.id)"
v-hasPermi="['erp:purchase-order:query-approval']"
v-if="scope.row.hasApprovalRecords"
>
审批记录
</el-button>
<el-button
link
type="primary"
@click="handleProcessApproval(scope.row.id)"
v-hasPermi="['erp:approval-record:process']"
v-if="scope.row.hasApprovalRecords && scope.row.status !== 20"
>
处理审批
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:purchase-order:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:purchase-order:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="warning"
@click="handleSupplierEvaluation(scope.row)"
v-hasPermi="['erp:supplier-evaluation:create']"
v-if="scope.row.status === 20"
>
供应商评价
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:purchase-order:delete']"
:disabled="scope.row.hasApprovalRecords"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<PurchaseOrderForm ref="formRef" @success="getList" />
<SubmitApprovalDialog ref="submitApprovalDialogRef" @success="getList" />
<ApprovalRecordsDialog ref="approvalDialogRef" />
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
<SupplierEvaluationDialog ref="supplierEvaluationDialogRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { PurchaseOrderApi, PurchaseOrderVO } from '@/api/erp/purchase/order'
import PurchaseOrderForm from './PurchaseOrderForm.vue'
@@ -209,13 +516,17 @@ import { SubmitApprovalDialog, ApprovalRecordsDialog, ProcessApprovalDialog } fr
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval/index'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售订单列表 */
defineOptions({ name: 'ErpPurchaseOrder' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -339,16 +650,31 @@ const handleSupplierEvaluation = (row: PurchaseOrderVO) => {
/** 删除按钮操作 */
const handleDelete = async (ids: number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await PurchaseOrderApi.deletePurchaseOrder(ids)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<PurchaseOrderVO[]>([])
const handleSelectionChange = (rows: PurchaseOrderVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: PurchaseOrderVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
/** 审批/反审批操作 */
const handleUpdateStatus = async (id: number, status: number) => {
try {

View File

@@ -1,157 +1,69 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="退货单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="退货时间" prop="returnTime">
<el-date-picker
v-model="formData.returnTime"
type="date"
value-format="x"
placeholder="选择退货时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input readonly>
<template #prefix>
<el-link
v-if="formData.orderId"
type="primary"
:underline="false"
@click.stop="openPurchaseOrderDetail"
>
{{ formData.orderNo }}
</el-link>
</template>
<template #append>
<el-button @click="openPurchaseOrderReturnEnableList">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
clearable
filterable
disabled
placeholder="请选择供应商"
style="width: 100%"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="3"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="退货单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="退货时间" prop="returnTime"><el-date-picker v-model="formData.returnTime" type="date" value-format="x" placeholder="选择退货时间" style="width:100%" /></el-form-item>
<el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderId" type="primary" :underline="false" @click.stop="openPurchaseOrderDetail">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openPurchaseOrderReturnEnableList"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable disabled placeholder="请选择供应商" style="width:100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="3" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">退货产品清单</div>
<PurchaseReturnItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 费用信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">费用信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number
v-model="formData.discountPercent"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入优惠率"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="退款优惠" prop="discountPrice">
<el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="其它费用" prop="otherPrice">
<el-input-number
v-model="formData.otherPrice"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入其它费用"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="优惠后金额">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="formData.accountId"
clearable
filterable
placeholder="请选择结算账户"
style="width: 100%"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="退款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width:100%" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled">
</el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- 可退货的订单列表 -->
<PurchaseOrderReturnEnableList
ref="purchaseOrderReturnEnableListRef"
@success="handlePurchaseOrderChange"
/>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="退货单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="退货时间" prop="returnTime"><el-date-picker v-model="formData.returnTime" type="date" value-format="x" placeholder="选择退货时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderId" type="primary" :underline="false" @click.stop="openPurchaseOrderDetail">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openPurchaseOrderReturnEnableList"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable disabled placeholder="请选择供应商" class="!w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="退货产品清单" name="item"><PurchaseReturnItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="退款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 可退货的订单列表 -->
<PurchaseOrderReturnEnableList ref="purchaseOrderReturnEnableListRef" @success="handlePurchaseOrderChange" />
<!-- 采购订单详情弹窗 -->
<PurchaseOrderForm ref="purchaseOrderFormRef" />
</template>
@@ -167,8 +79,12 @@ import PurchaseOrderReturnEnableList from '@/views/erp/purchase/order/components
import PurchaseOrderForm from '@/views/erp/purchase/order/PurchaseOrderForm.vue'
import { PurchaseOrderVO } from '@/api/erp/purchase/order'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'PurchaseReturnForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n()
const message = useMessage()
@@ -211,6 +127,7 @@ const itemFormRef = ref()
const supplierList = ref<SupplierVO[]>([])
const accountList = ref<AccountVO[]>([])
const userList = ref<UserApi.UserVO[]>([])
const subTabsName = ref('item')
/** 计算价格 */
watch(

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -148,25 +141,35 @@
<!-- 合计 -->
<div class="mobile-item-summary" v-if="formData.length > 0">
<div class="mobile-item-summary__row">
<span>合计数量</span>
<span>{{ erpCountInputFormatter(summaryData.count) }}</span>
</div>
<div class="mobile-item-summary__row">
<span>合计金额</span>
<span>{{ erpPriceInputFormatter(summaryData.totalProductPrice) }}</span>
</div>
<div class="mobile-item-summary__row">
<span>合计税额</span>
<span>{{ erpPriceInputFormatter(summaryData.taxPrice) }}</span>
</div>
<div class="mobile-item-summary__row mobile-item-summary__row--total">
<span>税额合计</span>
<span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span>
</div>
<div class="mobile-item-summary__row"><span>合计数量</span><span>{{ erpCountInputFormatter(summaryData.count) }}</span></div>
<div class="mobile-item-summary__row"><span>合计金额</span><span>{{ erpPriceInputFormatter(summaryData.totalProductPrice) }}</span></div>
<div class="mobile-item-summary__row"><span>合计税额</span><span>{{ erpPriceInputFormatter(summaryData.taxPrice) }}</span></div>
<div class="mobile-item-summary__row mobile-item-summary__row--total"><span>税额合计</span><span>{{ erpPriceInputFormatter(summaryData.totalPrice) }}</span></div>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-else ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productName" /></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="已出库" fixed="right" min-width="80" v-if="formData[0]?.inCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.inCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="已退货" fixed="right" min-width="80" v-if="formData[0]?.returnCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.returnCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button :disabled="formData.length === 1" @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
@@ -174,6 +177,10 @@ import { ref, reactive, watch, onMounted, computed } from 'vue'
import { StockApi } from '@/api/erp/stock/stock'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{ items: any; disabled: boolean }>()
const formData = ref([])
@@ -216,7 +223,7 @@ watch(
{ deep: true }
)
// 合计
// 合计 - 移动端
const summaryData = computed(() =>
formData.value.reduce(
(acc, item) => {
@@ -230,6 +237,20 @@ const summaryData = computed(() =>
)
)
// 合计 - PC端
const getSummaries = (param: any) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
// 新增/删除/仓库切换
const handleAdd = () => {
formData.value.push({

View File

@@ -1,56 +1,80 @@
<!-- 可退款的采购退货单列表 -->
<template>
<Dialog
title="选择采购退货(仅展示可退款)"
v-model="dialogVisible"
:appendToBody="true"
:scroll="true"
width="1080"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" title="选择采购退货(仅展示可退款)" direction="rtl" size="100%" :append-to-body="true" class="mobile-enable-drawer">
<!-- 搜索栏 -->
<div class="mobile-enable__search">
<el-input v-model="queryParams.no" placeholder="搜索退货单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
<el-button :icon="Filter" circle @click="enableFilterVisible = true" />
</div>
<!-- 卡片列表 -->
<div class="mobile-enable__list" v-loading="loading">
<div v-if="list.length === 0 && !loading" class="mobile-enable__empty"><el-empty description="暂无可退款退货单" /></div>
<div v-for="item in list" :key="item.id" class="mobile-enable__card" :class="{ 'mobile-enable__card--selected': isSelected(item) }" @click="toggleSelect(item)">
<div class="mobile-enable__card-check"><el-checkbox :model-value="isSelected(item)" @click.stop /></div>
<div class="mobile-enable__card-content">
<div class="mobile-enable__card-header"><span class="mobile-enable__card-no">{{ item.no }}</span></div>
<div class="mobile-enable__card-row"><span class="mobile-enable__card-label">供应商</span><span class="mobile-enable__card-value">{{ item.supplierName || '-' }}</span></div>
<div class="mobile-enable__card-row"><span class="mobile-enable__card-label">产品</span><span class="mobile-enable__card-value mobile-enable__card-value--ellipsis">{{ item.productNames || '-' }}</span></div>
<div class="mobile-enable__card-row"><span class="mobile-enable__card-label">退货时间</span><span class="mobile-enable__card-value">{{ formatDate2(item.returnTime) }}</span></div>
<div class="mobile-enable__card-row"><span class="mobile-enable__card-label">创建人</span><span class="mobile-enable__card-value">{{ item.creatorName || '-' }}</span></div>
<div class="mobile-enable__card-nums">
<div class="mobile-enable__card-num"><div class="mobile-enable__card-num-val">¥{{ erpPriceInputFormatter(item.totalPrice) }}</div><div class="mobile-enable__card-num-label">应退</div></div>
<div class="mobile-enable__card-num"><div class="mobile-enable__card-num-val" style="color:#67c23a">¥{{ erpPriceInputFormatter(item.refundPrice) }}</div><div class="mobile-enable__card-num-label">已退</div></div>
<div class="mobile-enable__card-num"><div class="mobile-enable__card-num-val" :style="{ color: item.refundPrice === item.totalPrice ? '#909399' : '#f56c6c' }">¥{{ erpPriceInputFormatter(item.totalPrice - item.refundPrice) }}</div><div class="mobile-enable__card-num-label">未退</div></div>
</div>
</div>
</div>
</div>
<!-- 分页 -->
<div class="mobile-enable__pagination" v-if="total > 0">
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" :page-sizes="[10, 20]" layout="total, prev, pager, next" :pager-count="5" @pagination="getList" />
</div>
<!-- 筛选抽屉 -->
<el-drawer v-model="enableFilterVisible" title="筛选条件" direction="btt" size="50%" :append-to-body="true">
<el-form :model="queryParams" ref="queryFormRef" label-position="top">
<el-form-item label="产品" prop="productId">
<el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" style="width:100%"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select>
</el-form-item>
<el-form-item label="退货时间" prop="returnTime">
<el-date-picker v-model="queryParams.returnTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始" end-placeholder="结束" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" style="width:100%" />
</el-form-item>
</el-form>
<template #footer>
<el-button @click="resetQuery">重置</el-button>
<el-button type="primary" @click="enableFilterVisible = false; handleQuery()">确认筛选</el-button>
</template>
</el-drawer>
<template #footer>
<div class="mobile-enable__footer">
<span class="mobile-enable__footer-info">已选 {{ selectionList.length }} </span>
<div>
<el-button @click="dialogVisible = false"> </el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
</div>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择采购退货(仅展示可退款)" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1080">
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="退货单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入退货单号"
clearable
@keyup.enter="handleQuery"
class="!w-160px"
/>
<el-input v-model="queryParams.no" placeholder="请输入退货单号" clearable @keyup.enter="handleQuery" class="!w-160px" />
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-160px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
<el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px">
<el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="退货时间" prop="orderTime">
<el-date-picker
v-model="queryParams.returnTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-160px"
/>
<el-date-picker v-model="queryParams.returnTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" />
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
@@ -60,71 +84,65 @@
</ContentWrap>
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:show-overflow-tooltip="true"
:stripe="true"
@selection-change="handleSelectionChange"
>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true" @selection-change="handleSelectionChange">
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="退货单号" align="center" prop="no" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column
label="退货时间"
align="center"
prop="returnTime"
:formatter="dateFormatter2"
width="120px"
/>
<el-table-column label="退货时间" align="center" prop="returnTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="退金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="已退金额"
align="center"
prop="refundPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="应退金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="退金额" align="center" prop="refundPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="未退金额" align="center">
<template #default="scope">
<span v-if="scope.row.refundPrice === scope.row.totalPrice">0</span>
<el-tag type="danger" v-else>
{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.refundPrice) }}
</el-tag>
<el-tag type="danger" v-else>{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.refundPrice) }}</el-tag>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
v-model:limit="queryParams.pageSize"
v-model:page="queryParams.pageNo"
:total="total"
@pagination="getList"
/>
<Pagination v-model:limit="queryParams.pageSize" v-model:page="queryParams.pageNo" :total="total" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm">
</el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { ref, reactive, computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { ElTable } from 'element-plus'
import { dateFormatter2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate } from '@/utils/formatTime'
import { erpPriceInputFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { PurchaseReturnApi, PurchaseReturnVO } from '@/api/erp/purchase/return'
import { SaleReturnVO } from '@/api/erp/sale/return'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'PurchaseInPaymentEnableList' })
defineOptions({ name: 'PurchaseReturnRefundEnableList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const enableFilterVisible = ref(false)
const formatDate2 = (date: any) => {
if (!date) return '-'
return formatDate(new Date(date), 'YYYY-MM-DD')
}
/** 移动端选中操作 */
const isSelected = (item: PurchaseReturnVO) => {
return selectionList.value.some((s) => s.id === item.id)
}
const toggleSelect = (item: PurchaseReturnVO) => {
const idx = selectionList.value.findIndex((s) => s.id === item.id)
if (idx >= 0) {
selectionList.value.splice(idx, 1)
} else {
selectionList.value.push(item)
}
}
const list = ref<PurchaseReturnVO[]>([]) // 列表的数据
const total = ref(0) // 列表的总页数
@@ -198,3 +216,109 @@ const handleQuery = () => {
getList()
}
</script>
<style lang="scss" scoped>
.mobile-enable__search {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 12px;
.el-input { flex: 1; }
}
.mobile-enable__list {
display: flex;
flex-direction: column;
gap: 10px;
}
.mobile-enable__empty {
padding: 40px 0;
}
.mobile-enable__card {
display: flex;
gap: 10px;
background: #fff;
border-radius: 10px;
padding: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
border: 2px solid transparent;
transition: border-color 0.2s;
&--selected {
border-color: #409eff;
background: #f0f7ff;
}
}
.mobile-enable__card-check {
display: flex;
align-items: flex-start;
padding-top: 2px;
}
.mobile-enable__card-content {
flex: 1;
min-width: 0;
}
.mobile-enable__card-header {
margin-bottom: 6px;
}
.mobile-enable__card-no {
font-weight: 600;
font-size: 14px;
color: #303133;
}
.mobile-enable__card-row {
display: flex;
justify-content: space-between;
padding: 2px 0;
font-size: 13px;
}
.mobile-enable__card-label {
color: #909399;
flex-shrink: 0;
margin-right: 12px;
}
.mobile-enable__card-value {
color: #606266;
text-align: right;
&--ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 180px;
}
}
.mobile-enable__card-nums {
display: flex;
justify-content: space-around;
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #f0f0f0;
}
.mobile-enable__card-num {
text-align: center;
}
.mobile-enable__card-num-val {
font-size: 14px;
font-weight: 600;
color: #303133;
}
.mobile-enable__card-num-label {
font-size: 11px;
color: #909399;
margin-top: 2px;
}
.mobile-enable__pagination {
margin-top: 12px;
display: flex;
justify-content: center;
:deep(.el-pagination) { flex-wrap: wrap; justify-content: center; }
}
.mobile-enable__footer {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.mobile-enable__footer-info {
font-size: 13px;
color: #909399;
}
</style>

View File

@@ -1,16 +1,13 @@
<template>
<div class="mobile-purchase-return">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-purchase-return">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input v-model="queryParams.no" placeholder="搜索退货单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索退货单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:purchase-return:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -138,29 +135,251 @@
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<PurchaseReturnForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="退货单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入退货单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="退货时间" prop="inTime">
<el-date-picker
v-model="queryParams.inTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="queryParams.supplierId"
clearable
filterable
placeholder="请选择供供应商"
class="!w-240px"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入关联订单"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="queryParams.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-240px"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="退款状态" prop="refundStatus">
<el-select
v-model="queryParams.refundStatus"
placeholder="请选择退款状态"
clearable
class="!w-240px"
>
<el-option label="未退款" value="0" />
<el-option label="部分退款" value="1" />
<el-option label="全部退款" value="2" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择审核状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:purchase-return:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:purchase-return:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:purchase-return:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange" @row-click="handleRowClick">
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="退货单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column label="退货时间" align="center" prop="returnTime" :formatter="dateFormatter2" width="120px" sortable />
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="应退金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="已退金额" align="center" prop="refundPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="未退金额" align="center"><template #default="scope"><span v-if="scope.row.refundPrice === scope.row.totalPrice">0</span><el-tag type="danger" v-else>{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.refundPrice) }}</el-tag></template></el-table-column>
<el-table-column label="审核状态" align="center" fixed="right" width="90" prop="status"><template #default="scope"><dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" /></template></el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button link @click="openForm('detail', scope.row.id)" v-hasPermi="['erp:purchase-return:query']">详情</el-button>
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:purchase-return:update']" :disabled="scope.row.status === 20">编辑</el-button>
<el-button link type="primary" @click="handleUpdateStatus(scope.row.id, 20)" v-hasPermi="['erp:purchase-return:update-status']" v-if="scope.row.status === 10">审批</el-button>
<el-button link type="danger" @click="handleUpdateStatus(scope.row.id, 10)" v-hasPermi="['erp:purchase-return:update-status']" v-if="scope.row.status === 20">反审批</el-button>
<el-button link type="danger" @click="handleDelete([scope.row.id])" v-hasPermi="['erp:purchase-return:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<PurchaseReturnForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { PurchaseReturnApi, PurchaseReturnVO } from '@/api/erp/purchase/return'
import PurchaseReturnForm from './PurchaseReturnForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
/** ERP 采购退货列表 */
defineOptions({ name: 'ErpPurchaseReturn' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const { t } = useI18n()
@@ -242,9 +461,27 @@ const handleDelete = async (ids: number[]) => {
await PurchaseReturnApi.deletePurchaseReturn(ids)
message.success(t('common.delSuccess'))
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<PurchaseReturnVO[]>([])
const handleSelectionChange = (rows: PurchaseReturnVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: PurchaseReturnVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
const handleUpdateStatus = async (id: number, status: number) => {
try {
await message.confirm(`确定${status === 20 ? '审批' : '反审批'}该退货吗?`)

View File

@@ -1,22 +1,8 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="名称" prop="name">
@@ -251,15 +237,62 @@
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="800px" class="supplier-form-dialog">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" class="supplier-form" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="24"><el-divider class="supplier-section-divider">基础信息</el-divider></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="名称" prop="name"><el-input v-model="formData.name" placeholder="请输入名称" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="企业性质" prop="enterpriseNature"><el-select v-model="formData.enterpriseNature" placeholder="请选择企业性质" class="!w-1/1"><el-option v-for="item in enterpriseNatureOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="供应商类型" prop="type"><el-select v-model="formData.type" placeholder="请选择供应商类型" class="!w-1/1"><el-option label="生产型" :value="1" /><el-option label="贸易型" :value="2" /><el-option label="服务型" :value="3" /><el-option label="其他" :value="4" /></el-select></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="注册资金" prop="registeredCapital"><el-input-number v-model="formData.registeredCapital" :min="0" :precision="2" placeholder="请输入注册资金" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="使用/营业期限" prop="validPeriod"><el-input v-model="formData.validPeriod" placeholder="请输入使用/营业期限" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="邮编" prop="zipCode"><el-input v-model="formData.zipCode" placeholder="请输入邮编" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="联系人" prop="contact"><el-input v-model="formData.contact" placeholder="请输入联系人" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="手机号码" prop="mobile"><el-input v-model="formData.mobile" placeholder="请输入手机号码" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="联系电话" prop="telephone"><el-input v-model="formData.telephone" placeholder="请输入联系电话" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="电子邮箱" prop="email"><el-input v-model="formData.email" placeholder="请输入电子邮箱" /></el-form-item></el-col>
<el-col :span="24"><el-divider /></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="纳税人识别号" prop="taxNo"><el-input v-model="formData.taxNo" placeholder="请输入纳税人识别号" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="税率(%)" prop="taxPercent"><el-input-number v-model="formData.taxPercent" :min="0" :precision="4" placeholder="请输入税率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="开户行" prop="bankName"><el-input v-model="formData.bankName" placeholder="请输入开户行" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="开户账号" prop="bankAccount"><el-input v-model="formData.bankAccount" placeholder="请输入开户账号" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="开户地址" prop="bankAddress"><el-input v-model="formData.bankAddress" placeholder="请输入开户地址" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="银行行号" prop="bankLineNo"><el-input v-model="formData.bankLineNo" placeholder="请输入银行行号" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="付款条件" prop="paymentTerms"><el-select v-model="formData.paymentTerms" placeholder="请选择付款条件" class="!w-1/1"><el-option v-for="item in paymentTermsOptions" :key="item.value" :label="item.label" :value="item.value" /></el-select></el-form-item></el-col>
<el-col :span="24"><el-divider /></el-col>
<el-col :span="24"><el-form-item label="生产/经营范围" prop="productScope"><el-input type="textarea" v-model="formData.productScope" placeholder="请输入生产产品范围/经营范围" /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="生产厂地址" prop="factoryAddress"><el-input type="textarea" v-model="formData.factoryAddress" placeholder="请输入生产厂地址" /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="年度订单数" prop="annualOrderNums"><el-input :model-value="formatInteger(formData.annualOrderNums)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="年度订单额" prop="annualOrderAmounts"><el-input :model-value="formatAmount(formData.annualOrderAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="年度已付款" prop="annualPaidAmounts"><el-input :model-value="formatAmount(formData.annualPaidAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12" :xs="24" :sm="12"><el-form-item label="累计未付款" prop="totalUnpaidAmounts"><el-input :model-value="formatAmount(formData.totalUnpaidAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="24"><el-divider class="supplier-section-divider">状态信息</el-divider></el-col>
<el-col :span="12" :xs="12" :sm="12"><el-form-item label="开启状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item></el-col>
<el-col :span="12" :xs="12" :sm="12"><el-form-item label="排序" prop="sort"><el-input-number v-model="formData.sort" placeholder="请输入排序" class="!w-1/1" :precision="0" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
/** ERP 表单 */
defineOptions({ name: 'SupplierForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -527,4 +560,18 @@ const resetForm = () => {
:deep(.el-date-editor) {
width: 100% !important;
}
/* PC端样式 */
:deep(.supplier-form .el-form-item__label) {
white-space: nowrap !important;
overflow: hidden;
text-overflow: ellipsis;
}
:deep(.supplier-form .supplier-section-divider) {
margin: 16px 0 12px;
}
:deep(.supplier-form-dialog .el-dialog__body) {
padding-left: 12px;
padding-right: 12px;
}
</style>

View File

@@ -1,11 +1,8 @@
<template>
<div class="mobile-supplier">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-supplier">
<!-- 搜索操作栏 -->
<div class="mobile-header">
<!-- <div class="mobile-navbar__back" @click="router.back()">-->
<!-- <Icon icon="ep:arrow-left" />-->
<!-- <span>返回</span>-->
<!-- </div>-->
<div class="mobile-header__search">
<el-input v-model="queryParams.name" placeholder="搜索供应商名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" />
</div>
@@ -83,18 +80,84 @@
<!-- 表单弹窗添加/修改 -->
<SupplierForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="名称" prop="name">
<el-input v-model="queryParams.name" placeholder="请输入名称" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="手机号码" prop="mobile">
<el-input v-model="queryParams.mobile" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item label="联系电话" prop="telephone">
<el-input v-model="queryParams.telephone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" class="!w-240px" />
</el-form-item>
<el-form-item>
<el-button @click="handleQuery">
<Icon icon="ep:search" class="mr-5px" /> 搜索
</el-button>
<el-button @click="resetQuery">
<Icon icon="ep:refresh" class="mr-5px" /> 重置
</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:supplier:create']">
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:supplier:export']">
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="名称" align="center" prop="name" />
<el-table-column label="联系人" align="center" prop="contact" />
<el-table-column label="手机号码" align="center" prop="mobile" />
<el-table-column label="联系电话" align="center" prop="telephone" />
<el-table-column label="电子邮箱" align="center" prop="email" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:supplier:update']" :disabled="scope.row.name === '-'">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:supplier:delete']" :disabled="scope.row.name === '-'">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<SupplierForm ref="formRef" @success="getList" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { DICT_TYPE } from '@/utils/dict'
import download from '@/utils/download'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import SupplierForm from './SupplierForm.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 供应商 列表 */
defineOptions({ name: 'ErpSupplier' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const router = useRouter()
const message = useMessage()
const { t } = useI18n()
@@ -179,6 +242,16 @@ const handleExport = async () => {
}
}
/** 行点击操作 */
const handleRowClick = (row: SupplierVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) {
return
}
if (row.name === '-') return
openForm('update', row.id)
}
/** 初始化 **/
onMounted(() => {
getList()

View File

@@ -1,5 +1,95 @@
<template>
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="800">
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="过磅单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="原料" prop="productId">
<el-select v-model="formData.productId" placeholder="请选择原料" filterable style="width:100%" @change="handleProductChange" clearable>
<el-option v-for="item in productOptions" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<template v-if="isTomato">
<el-form-item label="交售农户" prop="supplierName">
<el-select v-model="formData.supplierName" filterable remote :remote-method="remoteSupplierFarmerMethod" :loading="supplierLoadingFarmer" placeholder="请选择交售农户" @change="handleSupplierChange" clearable style="width:100%">
<el-option v-for="item in supplierOptionsFarmer" :key="item.id" :label="item.name" :value="item.name" />
</el-select>
</el-form-item>
<el-form-item label="农户身份证号" prop="idCardNumber"><el-input v-model="formData.idCardNumber" placeholder="农户身份证号" disabled /></el-form-item>
<el-form-item label="手机号码" prop="mobile"><el-input v-model="formData.mobile" placeholder="请输入手机号码" /></el-form-item>
</template>
<div class="mobile-form__input-group">
<el-form-item label="毛重(t)" prop="grossWeight"><el-input-number style="width:100%" v-model="formData.grossWeight" :precision="2" :step="0.1" :min="0" @change="calculateNetWeight" /></el-form-item>
<el-form-item label="皮重(t)" prop="tareWeight"><el-input-number style="width:100%" v-model="formData.tareWeight" :precision="2" :step="0.1" :min="0" @change="calculateNetWeight" /></el-form-item>
</div>
<el-form-item label="承运司机" prop="driver">
<el-select v-model="formData.driver" filterable remote :remote-method="remoteDriverMethod" :loading="driverLoading" placeholder="请选择承运司机" @change="handleDriverChange" clearable allow-create default-first-option style="width:100%">
<el-option v-for="item in driverOptions" :key="item.id" :label="item.driverName" :value="item.driverName" />
</el-select>
</el-form-item>
<el-form-item label="车号" prop="vehicleNumber"><el-input v-model="formData.vehicleNumber" placeholder="请输入车号" /></el-form-item>
<div class="mobile-form__input-group">
<el-form-item label="净重(t)" prop="netWeight"><el-input-number style="width:100%" v-model="formData.netWeight" :precision="2" :step="0.1" :min="0" disabled /></el-form-item>
<el-form-item label="扣杂率(%)" prop="impurityRate"><el-input-number style="width:100%" v-model="formData.impurityRate" :precision="2" :step="0.1" :min="0" :max="100" @change="calculatePlannedWeight" /></el-form-item>
</div>
<template v-if="isTomato"><el-form-item label="产地凭证号" prop="originCertificateNumber"><el-input v-model="formData.originCertificateNumber" placeholder="请输入产地凭证号" /></el-form-item></template>
<div class="mobile-form__input-group">
<el-form-item label="计划重量(t)" prop="plannedWeight"><el-input-number style="width:100%" v-model="formData.plannedWeight" :precision="2" :step="0.1" :min="0" disabled /></el-form-item>
<el-form-item label="剩余重量(t)" prop="remainingWeight"><el-input-number style="width:100%" v-model="formData.remainingWeight" :precision="2" :step="0.1" :min="0" disabled /></el-form-item>
</div>
<template v-if="isStevia">
<el-form-item label="供应商" prop="supplierName2">
<el-select v-model="formData.supplierName2" filterable remote :remote-method="remoteSupplierVendorMethod" :loading="supplierLoadingVendor" placeholder="请选择供应商" @change="handleSupplierChange2" clearable style="width:100%">
<el-option v-for="item in supplierOptionsVendor" :key="item.id" :label="item.name" :value="item.name" />
</el-select>
</el-form-item>
</template>
<template v-if="isTomato"><el-form-item label="管理员" prop="administrator"><el-input v-model="formData.administrator" placeholder="请输入管理员姓名" /></el-form-item></template>
<el-form-item label="司磅员" prop="weigher"><el-input v-model="formData.weigher" placeholder="请输入司磅员姓名" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
</div>
<template v-if="isStevia">
<div class="mobile-form__section">
<div class="mobile-form__section-title">检验信息</div>
<el-form-item label="取样日期" prop="sampleDate"><el-date-picker v-model="formData.sampleDate" type="date" placeholder="请选择取样日期" style="width:100%" /></el-form-item>
<el-form-item label="取样地点" prop="sampleLocation"><el-input v-model="formData.sampleLocation" placeholder="请输入取样地点" /></el-form-item>
<div class="mobile-form__input-group">
<el-form-item label="代表重量(kg)" prop="representativeWeight"><el-input-number style="width:100%" v-model="formData.representativeWeight" :precision="2" :step="0.1" :min="0" /></el-form-item>
<el-form-item label="样品重量(kg)" prop="sampleWeight"><el-input-number style="width:100%" v-model="formData.sampleWeight" :precision="2" :step="0.1" :min="0" /></el-form-item>
</div>
<div class="mobile-form__input-group">
<el-form-item label="杂质重量(kg)" prop="impurityWeight"><el-input-number style="width:100%" v-model="formData.impurityWeight" :precision="2" :step="0.1" :min="0" /></el-form-item>
<el-form-item label="沙土重量(kg)" prop="sandWeight"><el-input-number style="width:100%" v-model="formData.sandWeight" :precision="2" :step="0.1" :min="0" /></el-form-item>
</div>
<div class="mobile-form__input-group">
<el-form-item label="感官" prop="sensoryEvaluation"><el-input v-model="formData.sensoryEvaluation" placeholder="请输入感官评价" /></el-form-item>
<el-form-item label="合格率(%)" prop="qualificationRate"><el-input v-model="formData.qualificationRate" placeholder="请输入合格率" /></el-form-item>
</div>
<div class="mobile-form__input-group">
<el-form-item label="水分(%)" prop="moistureContent"><el-input v-model="formData.moistureContent" placeholder="请输入水分含量" /></el-form-item>
<el-form-item label="含糖(%)" prop="sugarContent"><el-input v-model="formData.sugarContent" placeholder="请输入含糖量" /></el-form-item>
</div>
<div class="mobile-form__input-group">
<el-form-item label="RA值" prop="raValue"><el-input v-model="formData.raValue" placeholder="请输入RA值" /></el-form-item>
<el-form-item label="STV值" prop="stvValue"><el-input v-model="formData.stvValue" placeholder="请输入STV值" /></el-form-item>
</div>
<el-form-item label="化验员" prop="labTechnician"><el-input v-model="formData.labTechnician" placeholder="请输入化验员姓名" /></el-form-item>
<el-form-item label="检验备注" prop="inspectionRemark"><el-input type="textarea" v-model="formData.inspectionRemark" :rows="2" placeholder="请输入检验相关备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
</template>
</el-form>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submitForm" :loading="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" :title="dialogTitle" width="800">
<el-form
ref="formRef"
:model="formData"
@@ -406,6 +496,10 @@ import { FarmerApi } from '@/api/erp/purchase/farmer'
import { WeighApi } from '@/api/erp/purchase/weigh'
import { getCarPage } from '@/api/erp/purchase/car'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
// 定义供应商数据类型
interface SupplierItem {
@@ -755,7 +849,7 @@ defineExpose({
})
</script>
<style scoped>
<style lang="scss" scoped>
.dialog-footer {
display: flex;
justify-content: flex-end;
@@ -768,4 +862,47 @@ defineExpose({
font-size: 16px;
color: #606266;
}
.mobile-form {
padding: 12px;
}
.mobile-form__section {
background: #fff;
border-radius: 10px;
padding: 14px;
margin-bottom: 12px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}
.mobile-form__section-title {
font-size: 15px;
font-weight: 600;
color: #303133;
margin-bottom: 12px;
padding-bottom: 8px;
border-bottom: 1px solid #f0f0f0;
}
.mobile-form__input-group {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 8px;
}
.mobile-form__footer {
position: sticky;
bottom: 0;
background: #fff;
padding: 12px 16px;
padding-bottom: calc(12px + constant(safe-area-inset-bottom));
padding-bottom: calc(12px + env(safe-area-inset-bottom));
border-top: 1px solid #eee;
display: flex;
justify-content: flex-end;
gap: 12px;
z-index: 10;
margin: 0 -12px -12px;
.el-button {
flex: 1;
height: 40px;
font-size: 15px;
}
}
</style>

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-weigh">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-weigh">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -137,11 +138,7 @@
<el-descriptions-item label="管理员">{{ detailData?.administrator || '-' }}</el-descriptions-item>
<el-descriptions-item label="司磅员">{{ detailData?.weigher || '-' }}</el-descriptions-item>
<el-descriptions-item label="产地证明号">{{ detailData?.originCertificateNumber || '-' }}</el-descriptions-item>
<el-descriptions-item label="入库状态">
<el-tag :type="(detailData?.inStatus === 1) ? 'success' : 'info'">
{{ (detailData?.inStatus === 1) ? '已入库' : '未入库' }}
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="入库状态"><el-tag :type="(detailData?.inStatus === 1) ? 'success' : 'info'">{{ (detailData?.inStatus === 1) ? '已入库' : '未入库' }}</el-tag></el-descriptions-item>
<el-descriptions-item label="创建时间">{{ detailData?.createTime ? formatDateTime(detailData.createTime) : '-' }}</el-descriptions-item>
<el-descriptions-item label="备注">{{ detailData?.remark || '-' }}</el-descriptions-item>
</el-descriptions>
@@ -170,9 +167,229 @@
</template>
</el-dialog>
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="交售农户" prop="supplierName">
<el-input
v-model="queryParams.supplierName"
placeholder="请输入交售农户"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="车号" prop="vehicleNumber">
<el-input
v-model="queryParams.vehicleNumber"
placeholder="请输入车号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="管理员" prop="administrator">
<el-input
v-model="queryParams.administrator"
placeholder="请输入管理员姓名"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
type="daterange"
value-format="YYYY-MM-DD HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:weigh:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:weigh:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="编号" align="center" prop="no" width="150px"/>
<el-table-column label="原料" align="center" prop="productName" />
<el-table-column label="毛重(kg)" align="center" prop="grossWeight" />
<el-table-column label="皮重(kg)" align="center" prop="tareWeight" />
<el-table-column label="净重(kg)" align="center" prop="netWeight" />
<el-table-column label="扣杂率(%)" align="center" prop="impurityRate" />
<el-table-column label="计划重量(kg)" align="center" prop="plannedWeight" width="140"/>
<el-table-column label="剩余重量(kg)" align="center" prop="remainingWeight" width="140"/>
<el-table-column label="承运司机" align="center" prop="driver" />
<el-table-column label="管理员" align="center" prop="administrator" />
<el-table-column label="司磅员" align="center" prop="weigher" />
<el-table-column label="入库状态" align="center">
<template #default="scope">
<el-tag :type="(scope.row.inStatus === 1) ? 'success' : 'info'">
{{ (scope.row.inStatus === 1) ? '已入库' : '未入库' }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="170" sortable>
<template #default="scope">
{{ formatDateTime(scope.row.createTime) }}
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="220px">
<template #default="scope">
<el-button
v-if="scope.row.inStatus !== 1"
link
type="primary"
@click.stop="openForm('update', scope.row.id)"
v-hasPermi="['erp:weigh:update']"
>
编辑
</el-button>
<el-button
v-if="scope.row.inStatus !== 0"
link
type="primary"
@click.stop="openDetailDialog(scope.row)"
>
详情
</el-button>
<el-button
v-if="scope.row.inStatus !== 1"
link
type="success"
@click.stop="openWarehouseDialog(scope.row)"
v-hasPermi="['erp:weigh:inbound']"
>
入库
</el-button>
<el-button
v-if="scope.row.inStatus !== 1"
link
type="danger"
@click.stop="handleDelete(scope.row.id)"
v-hasPermi="['erp:weigh:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<WeighForm ref="formRef" @success="getList" />
<!-- 入库选择仓库弹窗 -->
<el-dialog v-model="warehouseDialogVisible" title="选择入库仓库" width="500px">
<div style="margin-bottom:12px;font-size:14px;color:#606266">
<div>原料{{ currentWeigh?.productName || '-' }}</div>
<div>入库数量(kg){{ currentWeigh?.plannedWeight ?? '-' }}</div>
</div>
<el-form label-width="80px">
<el-form-item label="仓库">
<el-select v-model="selectedWarehouseId" placeholder="请选择仓库" style="width:100%" :loading="warehouseLoading">
<el-option v-for="w in warehouseOptions" :key="w.id" :label="w.name" :value="w.id" />
</el-select>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="warehouseDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="inboundLoading" @click="confirmInbound">确认</el-button>
</template>
</el-dialog>
<!-- 详情弹窗 -->
<el-dialog v-model="detailDialogVisible" title="过磅单详情" width="800px">
<el-tabs>
<el-tab-pane label="基本信息">
<el-descriptions :column="2" border>
<el-descriptions-item label="编号">{{ detailData?.no || '-' }}</el-descriptions-item>
<el-descriptions-item label="原料">{{ detailData?.productName || '-' }}</el-descriptions-item>
<el-descriptions-item label="毛重(kg)">{{ detailData?.grossWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="皮重(kg)">{{ detailData?.tareWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="净重(kg)">{{ detailData?.netWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="扣杂率(%)">{{ detailData?.impurityRate || '-' }}</el-descriptions-item>
<el-descriptions-item label="计划重量(kg)">{{ detailData?.plannedWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="交售农户">{{ detailData?.supplierName || '-' }}</el-descriptions-item>
<el-descriptions-item label="身份证号">{{ detailData?.idCardNumber || '-' }}</el-descriptions-item>
<el-descriptions-item label="车号">{{ detailData?.vehicleNumber || '-' }}</el-descriptions-item>
<el-descriptions-item label="承运司机">{{ detailData?.driver || '-' }}</el-descriptions-item>
<el-descriptions-item label="管理员">{{ detailData?.administrator || '-' }}</el-descriptions-item>
<el-descriptions-item label="司磅员">{{ detailData?.weigher || '-' }}</el-descriptions-item>
<el-descriptions-item label="产地证明号">{{ detailData?.originCertificateNumber || '-' }}</el-descriptions-item>
<el-descriptions-item label="入库状态"><el-tag :type="(detailData?.inStatus === 1) ? 'success' : 'info'">{{ (detailData?.inStatus === 1) ? '已入库' : '未入库' }}</el-tag></el-descriptions-item>
<el-descriptions-item label="创建时间">{{ detailData?.createTime ? formatDateTime(detailData.createTime) : '-' }}</el-descriptions-item>
<el-descriptions-item label="备注" :span="2">{{ detailData?.remark || '-' }}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
<el-tab-pane label="检查信息">
<el-descriptions :column="2" border>
<el-descriptions-item label="取样日期">{{ detailData?.sampleDate ? formatDateTime(detailData.sampleDate) : '-' }}</el-descriptions-item>
<el-descriptions-item label="取样地点">{{ detailData?.sampleLocation || '-' }}</el-descriptions-item>
<el-descriptions-item label="代表性重量(kg)">{{ detailData?.representativeWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="样品重量(kg)">{{ detailData?.sampleWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="杂质重量(kg)">{{ detailData?.impurityWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="沙石重量(kg)">{{ detailData?.sandWeight || '-' }}</el-descriptions-item>
<el-descriptions-item label="感官评价">{{ detailData?.sensoryEvaluation || '-' }}</el-descriptions-item>
<el-descriptions-item label="合格率(%)">{{ detailData?.qualificationRate || '-' }}</el-descriptions-item>
<el-descriptions-item label="水分含量(%)">{{ detailData?.moistureContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="糖分含量(%)">{{ detailData?.sugarContent || '-' }}</el-descriptions-item>
<el-descriptions-item label="RA值">{{ detailData?.raValue || '-' }}</el-descriptions-item>
<el-descriptions-item label="STV值">{{ detailData?.stvValue || '-' }}</el-descriptions-item>
<el-descriptions-item label="检验员">{{ detailData?.labTechnician || '-' }}</el-descriptions-item>
<el-descriptions-item label="检验备注">{{ detailData?.inspectionRemark || '-' }}</el-descriptions-item>
</el-descriptions>
</el-tab-pane>
</el-tabs>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
@@ -183,6 +400,10 @@ import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { WeighApi } from '@/api/erp/purchase/weigh'
import { WarehouseApi } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
// 定义过磅单数据结构
interface WeighVO {
@@ -399,6 +620,19 @@ const handleExport = async () => {
}
}
/** 行点击操作 */
const handleRowClick = (row: WeighVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) {
return
}
if (row.inStatus === 1) {
openDetailDialog(row)
} else {
openForm('update', row.id)
}
}
onMounted(() => {
getList()
})

View File

@@ -1,5 +1,7 @@
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
@@ -117,19 +119,59 @@
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1200">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="请购单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="请购类型" prop="type"><el-select v-model="formData.type" placeholder="请选择" class="!w-1/1"><el-option label="请购" :value="1" /><el-option label="补货" :value="2" /><el-option label="其他" :value="3" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优先级" prop="priority"><el-select v-model="formData.priority" placeholder="请选择" class="!w-1/1"><el-option label="低" :value="1" /><el-option label="中" :value="2" /><el-option label="高" :value="3" /><el-option label="紧急" :value="4" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="紧急程度" prop="emergencyDegree"><el-select v-model="formData.emergencyDegree" placeholder="请选择" class="!w-1/1"><el-option label="普通" :value="1" /><el-option label="较急" :value="2" /><el-option label="紧急" :value="3" /><el-option label="特急" :value="4" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="请购人" prop="requesterId"><el-select v-model="formData.requesterId" placeholder="请选择请购人" filterable clearable class="!w-1/1" @change="onRequesterChange"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="请购部门" prop="requesterDeptId"><el-select v-model="formData.requesterDeptId" placeholder="请选择部门" clearable class="!w-1/1" @change="onDeptChange"><el-option v-for="item in deptList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="请购时间" prop="requestTime"><el-date-picker v-model="formData.requestTime" type="date" value-format="x" placeholder="选择时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="期望到货" prop="expectedTime"><el-date-picker v-model="formData.expectedTime" type="date" value-format="x" placeholder="选择时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" placeholder="请选择供应商" filterable clearable class="!w-1/1" @change="onSupplierChange"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="3" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="请购产品清单" name="item"><PurchaseRequisitionItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="合计数量"><span style="font-weight:600">{{ formData.totalCount }}</span></el-form-item></el-col>
<el-col :span="8"><el-form-item label="合计金额"><span style="color:#e6a23c;font-weight:600">{{ erpPriceInputFormatter(formData.totalPrice) }}</span></el-form-item></el-col>
</el-row>
<template v-if="formData.status === 2 || formData.status === 3">
<el-divider content-position="left">审核信息</el-divider>
<el-form-item label="审核意见"><el-input v-model="formData.approveRemark" type="textarea" :rows="2" placeholder="审核意见" :disabled="formType === 'create'" /></el-form-item>
</template>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { nextTick } from 'vue'
import { nextTick, computed } from 'vue'
import { PurchaseRequisitionApi, PurchaseRequisition } from '@/api/erp/purchaserequisition'
import { getSimpleUserList } from '@/api/system/user'
import { getSimpleDeptList } from '@/api/system/dept'
import { SupplierApi } from '@/api/erp/purchase/supplier'
import PurchaseRequisitionItemForm from './components/PurchaseRequisitionItemForm.vue'
import { erpPriceInputFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
/** 请购单 表单 */
defineOptions({ name: 'PurchaseRequisitionForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -177,7 +219,7 @@ const formRules = reactive({
})
const disabled = computed(() => formType.value === 'detail')
const formRef = ref() // 表单 Ref
const subTabsName = ref('item')
const itemFormRef = ref()
/** 计算 totalCount、totalPrice */
@@ -402,6 +444,11 @@ const resetForm = () => {
font-weight: 600;
color: #303133;
}
.mobile-form__tip {
margin-top: 4px;
font-size: 12px;
color: var(--el-color-danger);
}
.mobile-form__footer {
position: sticky;
bottom: 0;

View File

@@ -1,21 +1,12 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div v-for="(row, $index) in formData" :key="$index" class="mobile-item-card">
<div class="mobile-item-card__header">
<div class="mobile-item-card__header-left">
<span class="mobile-item-card__index">#{{ $index + 1 }}</span>
<span class="mobile-item-card__name">{{ row.productName || '未选择产品' }}</span>
</div>
<el-button @click="handleDelete($index)" link type="danger" size="small" :disabled="disabled">删除</el-button>
<span class="mobile-item-card__index">#{{ $index + 1 }}</span>
<span class="mobile-item-card__name">{{ row.productName || '未选择产品' }}</span>
<el-button :disabled="disabled || formData.length === 1" @click="handleDelete($index)" link type="danger" size="small">删除</el-button>
</div>
<div class="mobile-item-card__body">
<el-form-item label="产品" :prop="`${$index}.productId`" :rules="formRules.productId">
@@ -59,20 +50,123 @@
<span>合计数量</span>
<span>{{ summaryData.count }}</span>
</div>
<div class="mobile-item-summary__row">
<div class="mobile-item-summary__row mobile-item-summary__row--total">
<span>合计金额</span>
<span>{{ summaryData.totalPrice }}</span>
</div>
</div>
<!-- 添加按钮 -->
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加请购产品</el-button>
</div>
<div class="mobile-item-add" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加请购产品</el-button></div>
</div>
</el-form>
<!-- PC端布局 -->
<template v-else>
<el-form ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="产品名称" min-width="180">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!">
<el-select
v-model="row.productId"
clearable
filterable
@change="onChangeProduct($event, row)"
placeholder="请选择产品"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="规格" min-width="120">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productSpec" placeholder="规格" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="条码" min-width="150">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productBarCode" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="单位" min-width="80">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input disabled v-model="row.productUnitName" />
</el-form-item>
</template>
</el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!">
<el-input-number
v-model="row.count"
controls-position="right"
:min="0.0001"
:precision="4"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120">
<template #default="{ row, $index }">
<el-form-item
:prop="`${$index}.productPrice`"
:rules="formRules.productPrice"
class="mb-0px!"
>
<el-input-number
v-model="row.productPrice"
controls-position="right"
:min="0"
:precision="4"
class="!w-100%"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="金额" prop="totalPrice" fixed="right" min-width="100">
<template #default="{ row }">
<el-form-item class="mb-0px!">
<el-input
disabled
v-model="row.totalPrice"
:formatter="erpPriceInputFormatter"
/>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="备注" min-width="150">
<template #default="{ row, $index }">
<el-form-item :prop="`${$index}.remark`" class="mb-0px!">
<el-input v-model="row.remark" placeholder="请输入备注" />
</el-form-item>
</template>
</el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60">
<template #default="{ $index }">
<el-button @click="handleDelete($index)" link></el-button>
</template>
</el-table-column>
</el-table>
</el-form>
<el-row justify="center" class="mt-3" v-if="!disabled"><el-button @click="handleAdd" round>+ 添加请购产品</el-button></el-row>
</template>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import {
erpCountInputFormatter,
@@ -80,6 +174,10 @@ import {
erpPriceMultiply,
getSumValue
} from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = withDefaults(
defineProps<{
@@ -125,7 +223,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const countSum = getSumValue(formData.value.map((item) => Number(item.count || 0)))
const priceSum = getSumValue(formData.value.map((item) => Number(item.totalPrice || 0)))
@@ -135,6 +233,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: any) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row: any = {
@@ -194,35 +306,41 @@ onMounted(async () => {
gap: 10px;
}
.mobile-item-card {
background: #fff;
border-radius: 10px;
border: 1px solid #f0f0f0;
background: #f9fafb;
border-radius: 8px;
border: 1px solid #ebeef5;
overflow: hidden;
&__header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 12px;
background: #fafafa;
border-bottom: 1px solid #f0f0f0;
background: #f0f2f5;
gap: 8px;
}
&__header-left {
display: flex;
align-items: center;
gap: 6px;
flex: 1;
overflow: hidden;
}
&__index {
font-weight: 600;
font-size: 13px;
color: #909399;
font-weight: 600;
color: #409eff;
flex-shrink: 0;
}
&__name {
font-weight: 600;
flex: 1;
font-size: 14px;
font-weight: 500;
color: #303133;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
&__body {
padding: 12px;
padding: 10px 12px;
}
&__info-row {
display: flex;
@@ -238,9 +356,11 @@ onMounted(async () => {
}
&__info-label {
color: #909399;
flex-shrink: 0;
}
&__info-value {
color: #606266;
text-align: right;
}
&__input-group {
display: grid;
@@ -250,20 +370,26 @@ onMounted(async () => {
}
.mobile-item-summary {
background: #fff;
border-radius: 10px;
padding: 12px;
border-radius: 8px;
border: 1px solid #ebeef5;
padding: 10px 12px;
&__row {
display: flex;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
color: #303133;
padding: 3px 0;
padding: 4px 0;
font-size: 13px;
color: #606266;
&--total {
font-weight: 600;
color: #303133;
border-top: 1px solid #ebeef5;
padding-top: 8px;
margin-top: 4px;
}
}
}
.mobile-item-add {
display: flex;
justify-content: center;
text-align: center;
padding: 8px 0;
}
</style>

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-requisition">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-requisition">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -179,9 +180,334 @@
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="120px"
>
<el-form-item label="请购单编号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入请购单编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="请购类型" prop="type">
<el-select
v-model="queryParams.type"
placeholder="请选择请购类型"
clearable
class="!w-240px"
>
<el-option label="请购" :value="1" />
<el-option label="补货" :value="2" />
<el-option label="其他" :value="3" />
</el-select>
</el-form-item>
<el-form-item label="优先级" prop="priority">
<el-select
v-model="queryParams.priority"
placeholder="请选择优先级"
clearable
class="!w-240px"
>
<el-option label="低" :value="1" />
<el-option label="中" :value="2" />
<el-option label="高" :value="3" />
<el-option label="紧急" :value="4" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择状态"
clearable
class="!w-240px"
>
<el-option label="待审核" :value="1" />
<el-option label="已审核" :value="2" />
<el-option label="已驳回" :value="3" />
<el-option label="已取消" :value="4" />
<el-option label="已采购" :value="5" />
</el-select>
</el-form-item>
<el-form-item label="请购人" prop="requesterName">
<el-input
v-model="queryParams.requesterName"
placeholder="请输入请购人姓名"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="请购部门" prop="requesterDeptName">
<el-input
v-model="queryParams.requesterDeptName"
placeholder="请输入部门名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="请购时间" prop="requestTime">
<el-date-picker
v-model="queryParams.requestTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="期望到货时间" prop="expectedTime">
<el-date-picker
v-model="queryParams.expectedTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item label="紧急程度" prop="emergencyDegree">
<el-select
v-model="queryParams.emergencyDegree"
placeholder="请选择紧急程度"
clearable
class="!w-240px"
>
<el-option label="普通" :value="1" />
<el-option label="较急" :value="2" />
<el-option label="紧急" :value="3" />
<el-option label="特急" :value="4" />
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-220px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:purchase-requisition:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:purchase-requisition:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
:disabled="isEmpty(checkedIds)"
@click="handleDeleteBatch"
v-hasPermi="['erp:purchase-requisition:delete']"
>
<Icon icon="ep:delete" class="mr-5px" /> 批量删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
row-key="id"
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleRowCheckboxChange"
>
<el-table-column type="selection" width="55" />
<el-table-column label="请购单编号" align="center" prop="no" min-width="120">
<template #default="scope">
<el-link type="primary" @click="viewDetails(scope.row)">
{{ scope.row.no }}
</el-link>
</template>
</el-table-column>
<el-table-column label="请购类型" align="center" prop="type" width="100">
<template #default="scope">
<el-tag :type="getTypeTagType(scope.row.type)">
{{ getTypeLabel(scope.row.type) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="优先级" align="center" prop="priority" width="100">
<template #default="scope">
<el-tag :type="getPriorityTagType(scope.row.priority)">
{{ getPriorityLabel(scope.row.priority) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status" width="100">
<template #default="scope">
<el-tag :type="getStatusTagType(scope.row.status)">
{{ getStatusLabel(scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="请购人" align="center" prop="requesterNickname" width="100" />
<el-table-column label="请购部门" align="center" prop="requesterDeptName" width="120" />
<el-table-column
label="请购时间"
align="center"
prop="requestTime"
:formatter="dateFormatter"
width="160px"
/>
<el-table-column
label="期望到货时间"
align="center"
prop="expectedTime"
:formatter="dateFormatter"
width="160px"
/>
<el-table-column
label="紧急程度"
align="center"
prop="emergencyDegree"
width="100"
>
<template #default="scope">
<el-tag :type="getEmergencyTagType(scope.row.emergencyDegree)">
{{ getEmergencyLabel(scope.row.emergencyDegree) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="160px"
/>
<el-table-column label="操作" align="center" min-width="180px">
<template #default="scope">
<el-button
link
type="primary"
@click="viewDetails(scope.row)"
>
详情
</el-button>
<el-button
link
type="success"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:purchase-requisition:update']"
v-if="scope.row.status === 1"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:purchase-requisition:delete']"
v-if="scope.row.status === 1"
>
删除
</el-button>
<el-button
link
type="success"
@click="handleUpdateStatus(scope.row.id, 2)"
v-if="scope.row.status === 1"
v-hasPermi="['erp:purchase-requisition:update-status']"
>
审核
</el-button>
<el-button
link
type="success"
@click="handleSubmitApproval(scope.row.id)"
v-hasPermi="['erp:purchasere-quisition:submit-approval']"
v-if="scope.row.status === 1 && !scope.row.hasApprovalRecords"
>
提交审批
</el-button>
<el-button
link
type="info"
@click="handleViewApproval(scope.row.id)"
v-hasPermi="['erp:purchasere-quisition:query-approval']"
v-if="scope.row.hasApprovalRecords"
>
审批记录
</el-button>
<el-button
link
type="primary"
@click="handleProcessApproval(scope.row.id)"
v-hasPermi="['erp:approval-record:process']"
v-if="scope.row.hasApprovalRecords && scope.row.status !== 2 && scope.row.status !== 3 && scope.row.status !== 4 && scope.row.status !== 5"
>
处理审批
</el-button>
<el-button
link
type="warning"
@click="handleUpdateStatus(scope.row.id, 3)"
v-if="scope.row.status === 1"
v-hasPermi="['erp:purchase-requisition:approve']"
>
驳回
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改/详情 -->
<PurchaseRequisitionForm ref="formRef" @success="getList" />
<!-- 提交审批对话框 -->
<SubmitApprovalDialog ref="submitApprovalDialogRef" @success="getList" />
<!-- 审批记录对话框 -->
<ApprovalRecordsDialog ref="approvalDialogRef" />
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { isEmpty } from '@/utils/is'
import { dateFormatter, formatDate } from '@/utils/formatTime'
@@ -190,11 +516,14 @@ import { PurchaseRequisitionApi, PurchaseRequisition } from '@/api/erp/purchaser
import PurchaseRequisitionForm from './PurchaseRequisitionForm.vue'
import { SubmitApprovalDialog, ApprovalRecordsDialog, ProcessApprovalDialog } from '@/components/Approval'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval/index'
import { useWindowSize } from '@vueuse/core'
/** 请购单 列表 */
defineOptions({ name: 'PurchaseRequisition' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -455,6 +784,15 @@ const handleQuickFilter = (status: number | undefined) => {
queryParams.pageNo = 1
getList()
}
/** 行点击操作 */
const handleRowClick = (row: PurchaseRequisition, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) {
return
}
viewDetails(row)
}
</script>
<style lang="scss" scoped>

View File

@@ -1,21 +1,8 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<!-- 基础信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">基础信息</div>
@@ -216,7 +203,6 @@
</el-form>
</div>
<!-- 底部按钮 -->
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
@@ -224,15 +210,58 @@
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="800px" class="customer-form-dialog">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading" class="customer-form">
<el-row :gutter="20">
<el-col :span="24"><el-divider class="customer-section-divider">基础信息</el-divider></el-col>
<el-col :span="12"><el-form-item label="名称" prop="name"><el-input v-model="formData.name" placeholder="请输入名称" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="联系人" prop="contact"><el-input v-model="formData.contact" placeholder="请输入联系人" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="手机号码" prop="mobile"><el-input v-model="formData.mobile" placeholder="请输入手机号码" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="联系电话" prop="telephone"><el-input v-model="formData.telephone" placeholder="请输入联系电话" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="电子邮箱" prop="email"><el-input v-model="formData.email" placeholder="请输入电子邮箱" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="企业类型" prop="companyType"><el-select v-model="formData.companyType" placeholder="请选择企业类型" class="!w-1/1"><el-option label="餐饮" :value="1" /><el-option label="食品批发" :value="2" /><el-option label="制造" :value="3" /><el-option label="超市" :value="4" /><el-option label="其他" :value="5" /></el-select></el-form-item></el-col>
<el-col :span="12"><el-form-item label="企业规模" prop="businessScale"><el-input v-model="formData.businessScale" placeholder="请输入企业规模" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="客户来源" prop="leadSourceType"><el-select v-model="formData.leadSourceType" placeholder="请选择来源类型" class="!w-1/1"><el-option label="展会" :value="1" /><el-option label="地推" :value="2" /><el-option label="转介绍" :value="3" /><el-option label="官网" :value="4" /><el-option label="平台" :value="5" /><el-option label="电销" :value="6" /><el-option label="老客户" :value="7" /><el-option label="其他" :value="99" /></el-select></el-form-item></el-col>
<el-col :span="24"><el-divider /></el-col>
<el-col :span="12"><el-form-item label="纳税人识别号" prop="taxNo"><el-input v-model="formData.taxNo" placeholder="请输入纳税人识别号" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="开户行" prop="bankName"><el-input v-model="formData.bankName" placeholder="请输入开户行" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="开户账号" prop="bankAccount"><el-input v-model="formData.bankAccount" placeholder="请输入开户账号" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="开户地址" prop="bankAddress"><el-input v-model="formData.bankAddress" placeholder="请输入开户地址" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="偏好产品" prop="preferredProducts"><el-input v-model="formData.preferredProducts" placeholder="请输入偏好产品或品类" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="偏好包装" prop="preferredPackaging"><el-input v-model="formData.preferredPackaging" placeholder="请输入偏好包装形式" /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="偏好交期" prop="deliveryCyclePrefer"><el-input v-model="formData.deliveryCyclePrefer" placeholder="请输入偏好交期/周期" /></el-form-item></el-col>
<el-col :span="24"><el-divider /></el-col>
<el-col :span="12"><el-form-item label="年度订单数" prop="annualOrderNums"><el-input :model-value="formatInteger(formData.annualOrderNums)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="年度订单额" prop="annualOrderAmounts"><el-input :model-value="formatAmount(formData.annualOrderAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="年度已收款" prop="annualReceivedAmounts"><el-input :model-value="formatAmount(formData.annualReceivedAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="12"><el-form-item label="累计未收款" prop="totalUnreceivedAmounts"><el-input :model-value="formatAmount(formData.totalUnreceivedAmounts)" placeholder="系统自动生成" disabled /></el-form-item></el-col>
<el-col :span="24"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="24"><el-divider class="customer-section-divider">状态信息</el-divider></el-col>
<el-col :span="12"><el-form-item label="开启状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item></el-col>
<el-col :span="12"><el-form-item label="排序" prop="sort"><el-input-number v-model="formData.sort" placeholder="请输入排序" class="!w-1/1" :precision="0" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
/** ERP 客户 表单 */
defineOptions({ name: 'CustomerForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-customer">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-customer">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -91,18 +92,64 @@
<!-- 表单弹窗添加/修改 -->
<CustomerForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="客户名称" prop="name"><el-input v-model="queryParams.name" placeholder="请输入客户名称" clearable @keyup.enter="handleQuery" class="!w-200px" /></el-form-item>
<el-form-item label="手机号码" prop="mobile"><el-input v-model="queryParams.mobile" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="联系电话" prop="telephone"><el-input v-model="queryParams.telephone" placeholder="请输入联系电话" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button type="primary" plain @click="openForm('create')" v-hasPermi="['erp:customer:create']"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button>
<el-button type="success" plain @click="handleExport" :loading="exportLoading" v-hasPermi="['erp:customer:export']"><Icon icon="ep:download" class="mr-5px" /> 导出</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="客户名称" align="center" prop="name" />
<el-table-column label="联系人" align="center" prop="contact" />
<el-table-column label="手机号码" align="center" prop="mobile" />
<el-table-column label="联系电话" align="center" prop="telephone" />
<el-table-column label="状态" align="center" prop="status" width="80"><template #default="scope"><dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" /></template></el-table-column>
<el-table-column label="备注" align="center" prop="remark" min-width="150" />
<el-table-column label="操作" align="center" fixed="right" width="150">
<template #default="scope">
<el-button link type="primary" @click="openForm('update', scope.row.id)" v-hasPermi="['erp:customer:update']">编辑</el-button>
<el-button link type="danger" @click="handleDelete(scope.row.id)" v-hasPermi="['erp:customer:delete']">删除</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CustomerForm ref="formRef" @success="getList" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { DICT_TYPE } from '@/utils/dict'
import download from '@/utils/download'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import CustomerForm from './CustomerForm.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 客户 列表 */
defineOptions({ name: 'ErpCustomer' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -188,6 +235,13 @@ const handleExport = async () => {
onMounted(() => {
getList()
})
/** 行点击操作 */
const handleRowClick = (row: CustomerVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.closest('button') || target.closest('a') || target.closest('.el-button')) return
openForm('update', row.id)
}
</script>
<style lang="scss" scoped>

View File

@@ -1,111 +1,71 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="订单单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="订单时间" prop="orderTime">
<el-date-picker
v-model="formData.orderTime"
type="date"
value-format="x"
placeholder="选择订单时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" style="width: 100%">
<el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="销售人员" prop="saleUserId">
<el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" style="width: 100%">
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="订单单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="formData.orderTime" type="date" value-format="x" placeholder="选择订单时间" style="width:100%" /></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" style="width:100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 订单产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">订单产品清单</div>
<SaleOrderItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 价格信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">价格信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number
v-model="formData.discountPercent"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入优惠率"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="收款优惠" prop="discountPrice">
<el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠后金额">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width: 100%">
<el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="收取订金" prop="depositPrice">
<el-input-number
v-model="formData.depositPrice"
controls-position="right"
:min="0"
:precision="4"
placeholder="请输入收取订金"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="收款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="收取订金" prop="depositPrice"><el-input-number v-model="formData.depositPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入收取订金" style="width:100%" /></el-form-item>
</div>
</el-form>
</div>
<!-- 底部按钮 -->
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2">
</el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="订单单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="formData.orderTime" type="date" value-format="x" placeholder="选择订单时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="订单产品清单" name="item"><SaleOrderItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="收款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="收取订金" prop="depositPrice"><el-input-number v-model="formData.depositPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入收取订金" class="!w-1/1" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SaleOrderApi, SaleOrderVO } from '@/api/erp/sale/order'
import SaleOrderItemForm from './components/SaleOrderItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
@@ -113,10 +73,14 @@ import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { erpPriceInputFormatter, erpPriceMultiply } from '@/utils'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售订单表单 */
defineOptions({ name: 'SaleOrderForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -134,22 +127,41 @@
</div>
</div>
<!-- 添加按钮 -->
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加销售产品</el-button>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input-number v-model="row.totalPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" @change="onChangeTotalPrice(row)" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加销售产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -194,7 +206,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
count: getSumValue(formData.value.map((item) => Number(item.count))),
@@ -204,6 +216,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,6 +1,8 @@
<!-- 可出库的订单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择销售订单(仅展示可出库)"
direction="rtl"
@@ -113,17 +115,52 @@
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择销售订单(仅展示可出库)" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1080">
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="订单单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入订单单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="queryParams.orderTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" width="65"><template #default="{ row }"><el-radio :value="row.id" v-model="currentRowValue" @change="handleCurrentChange(row)">&nbsp;</el-radio></template></el-table-column>
<el-table-column label="订单单号" align="center" prop="no" min-width="180" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="订单时间" align="center" prop="orderTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="出库数量" align="center" prop="outCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="金额合计" align="center" prop="totalProductPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="含税金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!currentRow" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { SaleOrderApi, SaleOrderVO } from '@/api/erp/sale/order'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { formatDate } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'ErpSaleOrderOutEnableList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const list = ref<SaleOrderVO[]>([])
const total = ref(0)
const loading = ref(false)

View File

@@ -1,6 +1,8 @@
<!-- 可退货的订单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择销售订单(仅展示可退货)"
direction="rtl"
@@ -117,17 +119,53 @@
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else title="选择销售订单(仅展示可退货)" v-model="dialogVisible" :appendToBody="true" :scroll="true" width="1100">
<ContentWrap>
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="订单单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入订单单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId"><el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="订单时间" prop="orderTime"><el-date-picker v-model="queryParams.orderTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange" start-placeholder="开始日期" end-placeholder="结束日期" :default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-160px" /></el-form-item>
<el-form-item><el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button><el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button></el-form-item>
</el-form>
</ContentWrap>
<ContentWrap>
<el-table v-loading="loading" :data="list" :show-overflow-tooltip="true" :stripe="true">
<el-table-column align="center" width="65"><template #default="{ row }"><el-radio :value="row.id" v-model="currentRowValue" @change="handleCurrentChange(row)">&nbsp;</el-radio></template></el-table-column>
<el-table-column label="订单单号" align="center" prop="no" min-width="180" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="订单时间" align="center" prop="orderTime" :formatter="dateFormatter2" width="120px" />
<el-table-column label="总数量" align="center" prop="totalCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="出库数量" align="center" prop="outCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="退货数量" align="center" prop="returnCount" :formatter="erpCountTableColumnFormatter" />
<el-table-column label="金额合计" align="center" prop="totalProductPrice" :formatter="erpPriceTableColumnFormatter" />
<el-table-column label="含税金额" align="center" prop="totalPrice" :formatter="erpPriceTableColumnFormatter" />
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
</ContentWrap>
<template #footer>
<el-button :disabled="!currentRow" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { SaleOrderApi, SaleOrderVO } from '@/api/erp/sale/order'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { formatDate } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'SaleOrderReturnEnableList' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const list = ref<SaleOrderVO[]>([])
const total = ref(0)
const loading = ref(false)

View File

@@ -1,28 +1,13 @@
<template>
<div class="mobile-sale-order">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-sale-order">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索订单单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索订单单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:sale-order:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:sale-order:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -191,26 +176,342 @@
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="订单单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入订单单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="订单时间" prop="orderTime">
<el-date-picker
v-model="queryParams.orderTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择供客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="出库数量" prop="outStatus">
<el-select
v-model="queryParams.outStatus"
placeholder="请选择出库数量"
clearable
class="!w-240px"
>
<el-option label="未出库" value="0" />
<el-option label="部分出库" value="1" />
<el-option label="全部出库" value="2" />
</el-select>
</el-form-item>
<el-form-item label="退货数量" prop="returnStatus">
<el-select
v-model="queryParams.returnStatus"
placeholder="请选择退货数量"
clearable
class="!w-240px"
>
<el-option label="未退货" value="0" />
<el-option label="部分退货" value="1" />
<el-option label="全部退货" value="2" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-order:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-order:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:sale-order:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="订单单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column
label="订单时间"
align="center"
prop="orderTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="总数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="出库数量"
align="center"
prop="outCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="退货数量"
align="center"
prop="returnCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额合计"
align="center"
prop="totalProductPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="含税金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="收取订金"
align="center"
prop="depositPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="380">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:sale-order:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-order:update']"
:disabled="scope.row.status === 20 || scope.row.hasApprovalRecords"
>
编辑
</el-button>
<el-button
link
type="success"
@click="handleSubmitApproval(scope.row.id)"
v-hasPermi="['erp:sale-order:submit-approval']"
v-if="scope.row.status === 10 && !scope.row.hasApprovalRecords"
>
提交审批
</el-button>
<el-button
link
type="info"
@click="handleViewApproval(scope.row.id)"
v-hasPermi="['erp:sale-order:query-approval']"
v-if="scope.row.hasApprovalRecords"
>
审批记录
</el-button>
<el-button
link
type="primary"
@click="handleProcessApproval(scope.row.id)"
v-hasPermi="['erp:approval-record:process']"
v-if="scope.row.hasApprovalRecords && scope.row.status !== 20"
>
处理审批
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:sale-order:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:sale-order:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:sale-order:delete']"
:disabled="scope.row.hasApprovalRecords"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<SaleOrderForm ref="formRef" @success="getList" />
<SubmitApprovalDialog ref="submitApprovalDialogRef" @success="getList" />
<ApprovalRecordsDialog ref="approvalDialogRef" />
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { SaleOrderApi, SaleOrderVO } from '@/api/erp/sale/order'
import SaleOrderForm from './SaleOrderForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { erpCountInputFormatter, erpPriceInputFormatter } from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { SubmitApprovalDialog, ApprovalRecordsDialog, ProcessApprovalDialog } from '@/components/Approval'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval/index'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售订单列表 */
defineOptions({ name: 'ErpSaleOrder' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -328,16 +629,31 @@ const handleProcessApproval = (id: number) => {
/** 删除按钮操作 */
const handleDelete = async (ids: number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await SaleOrderApi.deleteSaleOrder(ids)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<SaleOrderVO[]>([])
const handleSelectionChange = (rows: SaleOrderVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: SaleOrderVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
/** 审批/反审批操作 */
const handleUpdateStatus = async (id: number, status: number) => {
try {

View File

@@ -1,114 +1,80 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="出库单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="出库时间" prop="outTime">
<el-date-picker v-model="formData.outTime" type="date" value-format="x" placeholder="选择出库时间" style="width: 100%" />
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input readonly>
<template #prefix>
<el-link v-if="formData.orderNo && formData.orderId" type="primary" :underline="false" @click.stop="openSaleOrderDetail">
{{ formData.orderNo }}
</el-link>
</template>
<template #append>
<el-button @click="openSaleOrderOutEnableList">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" style="width: 100%">
<el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="销售人员" prop="saleUserId">
<el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" style="width: 100%">
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="出库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="出库时间" prop="outTime"><el-date-picker v-model="formData.outTime" type="date" value-format="x" placeholder="选择出库时间" style="width:100%" /></el-form-item>
<el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderNo && formData.orderId" type="primary" :underline="false" @click.stop="openSaleOrderDetail">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openSaleOrderOutEnableList"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" style="width:100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="选择销售人员" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 出库产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">出库产品清单</div>
<SaleOutItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 价格信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">价格信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width: 100%" />
</el-form-item>
<el-form-item label="收款优惠" prop="discountPrice">
<el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠后金额">
<el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="其它费用" prop="otherPrice">
<el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width: 100%" />
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width: 100%">
<el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="应收金额">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="收款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width:100%" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="应收金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
</div>
</el-form>
</div>
<!-- 底部按钮 -->
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2">
</el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="出库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="出库时间" prop="outTime"><el-date-picker v-model="formData.outTime" type="date" value-format="x" placeholder="选择出库时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderNo && formData.orderId" type="primary" :underline="false" @click.stop="openSaleOrderDetail" class="order-link">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openSaleOrderOutEnableList"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="出库产品清单" name="item"><SaleOutItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="收款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="应收金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 可出库的订单列表 -->
<SaleOrderOutEnableList ref="saleOrderOutEnableListRef" @success="handleSaleOrderChange" />
<!-- 销售订单详情弹窗 -->
<SaleOrderForm ref="saleOrderFormRef" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SaleOutApi, SaleOutVO } from '@/api/erp/sale/out'
import SaleOutItemForm from './components/SaleOutItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
@@ -118,10 +84,14 @@ import SaleOrderOutEnableList from '@/views/erp/sale/order/components/SaleOrderO
import SaleOrderForm from '@/views/erp/sale/order/SaleOrderForm.vue'
import { SaleOrderVO } from '@/api/erp/sale/order'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售出库表单 */
defineOptions({ name: 'SaleOutForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -149,16 +142,41 @@
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productName" /></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="原数量" fixed="right" min-width="80" v-if="formData[0]?.totalCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.totalCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="已出库" fixed="right" min-width="80" v-if="formData[0]?.outCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.outCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="库存单价" min-width="110" fixed="right"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockUnitPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="货值" min-width="110" fixed="right"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockValue" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="毛利润" prop="grossProfit" fixed="right" min-width="110"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.grossProfit" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button :disabled="formData.length === 1" @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -225,7 +243,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
count: getSumValue(formData.value.map((item) => Number(item.count))),
@@ -236,6 +254,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice', 'grossProfit'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,6 +1,8 @@
<!-- 可收款的销售出库单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择销售出库(仅展示可收款)"
direction="rtl"
@@ -116,21 +118,55 @@
</el-drawer>
<template #footer>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm">
</el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" title="选择销售出库(仅展示可收款)" width="950px" :close-on-press-escape="true" :destroy-on-close="true">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="出库单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入出库单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId">
<el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px">
<el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="list" :stripe="true" @selection-change="handleSelectionChange" style="margin-top:16px">
<el-table-column type="selection" width="50" />
<el-table-column label="出库单号" align="center" prop="no" min-width="160" />
<el-table-column label="客户" align="center" prop="customerName" width="120" />
<el-table-column label="产品" align="center" prop="productNames" min-width="150" show-overflow-tooltip />
<el-table-column label="出库时间" align="center" prop="outTime" width="110" :formatter="(row) => formatDate2(row.outTime)" />
<el-table-column label="应收金额" align="center" prop="totalPrice" width="100"><template #default="scope"><span style="color:#e6a23c">¥{{ erpPriceInputFormatter(scope.row.totalPrice) }}</span></template></el-table-column>
<el-table-column label="已收金额" align="center" prop="receiptPrice" width="100"><template #default="scope">¥{{ erpPriceInputFormatter(scope.row.receiptPrice || 0) }}</template></el-table-column>
<el-table-column label="未收金额" align="center" width="100"><template #default="scope"><el-tag v-if="(scope.row.receiptPrice || 0) < scope.row.totalPrice" type="danger">¥{{ erpPriceInputFormatter(scope.row.totalPrice - (scope.row.receiptPrice || 0)) }}</el-tag><span v-else>0</span></template></el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { SaleOutApi, SaleOutVO } from '@/api/erp/sale/out'
import { SaleOutwarehouseApi, SaleOutwarehouseVO } from '@/api/erp/sale/outwarehouse'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { formatDate } from '@/utils/formatTime'
import { erpPriceInputFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
type ReceiptOutRow = (SaleOutVO | SaleOutwarehouseVO) & {
customerName?: string
@@ -230,6 +266,11 @@ const handleQuery = () => {
selectionList.value = []
getList()
}
/** PC端表格选中变化 */
const handleSelectionChange = (rows: ReceiptOutRow[]) => {
selectionList.value = rows
}
</script>
<style lang="scss" scoped>

View File

@@ -1,29 +1,13 @@
<template>
<div class="mobile-sale-out">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-sale-out">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索出库单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索出库单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:sale-out:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:sale-out:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -170,35 +154,342 @@
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<SaleOutForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="出库单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入出库单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="出库时间" prop="outTime">
<el-date-picker
v-model="queryParams.outTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择供客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入关联订单"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="queryParams.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-240px"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="收款状态" prop="receiptStatus">
<el-select
v-model="queryParams.receiptStatus"
placeholder="请选择有款状态"
clearable
class="!w-240px"
>
<el-option label="未收款" value="0" />
<el-option label="部分收款" value="1" />
<el-option label="全部收款" value="2" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-out:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-out:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:sale-out:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
<el-button
type="info"
plain
@click="handlePrint"
v-hasPermi="['erp:sale-out:query']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:printer" class="mr-5px" /> 打印
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="出库单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column
label="出库时间"
align="center"
prop="outTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="总数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="应收金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="已收金额"
align="center"
prop="receiptPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="未收金额" align="center">
<template #default="scope">
<span v-if="scope.row.receiptPrice === scope.row.totalPrice">0</span>
<el-tag type="danger" v-else>
{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.receiptPrice) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="审核状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:sale-out:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-out:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:sale-out:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:sale-out:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:sale-out:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<SaleOutForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { SaleOutApi, SaleOutVO } from '@/api/erp/sale/out'
import SaleOutForm from './SaleOutForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import {
erpCountInputFormatter,
erpPriceInputFormatter
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { ElMessageBox } from 'element-plus'
import { useCache, CACHE_KEY } from '@/hooks/web/useCache'
import { onActivated } from 'vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售出库列表 */
defineOptions({ name: 'ErpSaleOut' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -294,15 +585,30 @@ const handleCardClick = (row: SaleOutVO) => {
/** 删除按钮操作 */
const handleDelete = async (ids: number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await SaleOutApi.deleteSaleOut(ids)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<SaleOutVO[]>([])
const handleSelectionChange = (rows: SaleOutVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: SaleOutVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
/** 审批/反审批操作 */
const handleUpdateStatus = async (id: number, status: number) => {
try {

View File

@@ -1,22 +1,8 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<!-- 基本信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
@@ -105,10 +91,45 @@
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="出库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="出库时间" prop="outTime"><el-date-picker v-model="formData.outTime" type="datetime" value-format="YYYY-MM-DD HH:mm:ss" placeholder="选择出库时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联明细" prop="stockRecordIds"><el-input v-model="formData.stockRecordText" readonly><template #append><el-button @click="openStockRecordList"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="仓库" prop="warehouseId"><el-select v-model="formData.warehouseId" clearable filterable placeholder="请选择仓库" class="!w-1/1"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="出库产品清单" name="item"><SaleOutwarehouseItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="2" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="收款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="2" placeholder="请输入其它费用" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="应收金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="总金额"><el-input-number v-model="formData.reverseCalculationAmount" :min="0" :precision="4" class="!w-1/1" placeholder="输入总金额反算单价" @change="handleReverseCalculation" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 库存批次选择弹窗 -->
<StockBatchSelectionDialog ref="stockBatchSelectionRef" @success="handleBatchSelectionChange" />
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { SaleOutwarehouseApi, SaleOutwarehouseVO } from '@/api/erp/sale/outwarehouse'
import SaleOutwarehouseItemForm from './components/SaleOutwarehouseItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
@@ -120,10 +141,14 @@ import { StockApi } from '@/api/erp/stock/stock/index'
import { ProductApi } from '@/api/erp/product/product'
import StockBatchSelectionDialog from './components/StockBatchSelectionDialog.vue'
import dayjs from 'dayjs'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售出库表单 */
defineOptions({ name: 'SaleOutwarehouseForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -150,23 +143,43 @@
</div>
</div>
<!-- 添加按钮 -->
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加出库产品</el-button>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="批号" min-width="120"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.batchCode" placeholder="批次编号" /></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable placeholder="请选择产品" @change="onChangeProduct($event, row)"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0" :precision="4" class="!w-100%" :disabled="!!row.stockRecordId" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0" :precision="8" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="2" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="120"><template #header><el-button type="success" @click="handleAdd"><Icon icon="ep:plus" class="mr-5px" /> 新增</el-button></template><template #default="{ $index, row }"><el-button :disabled="formData.length === 1 || !!row.stockRecordId" @click="handleDelete($index)" link type="danger"><Icon icon="ep:delete" /> 删除</el-button></template></el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { StockApi } from '@/api/erp/stock/stock'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: any[]
@@ -223,7 +236,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
count: getSumValue(formData.value.map((item) => Number(item.count))),
@@ -233,6 +246,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param) => {
const { columns, data } = param
const sums = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-sale-outwarehouse">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-sale-outwarehouse">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -154,12 +155,7 @@
<SaleOutwarehouseForm ref="formRef" @success="getList" />
<!-- 收款表单弹窗 -->
<el-dialog
v-model="receiptDialogVisible"
title="收款"
width="90%"
@closed="receiptDialogVisible = false"
>
<el-dialog v-model="receiptDialogVisible" title="收款" width="90%" @closed="receiptDialogVisible = false">
<div v-if="currentOutwarehouse">
<div class="mobile-receipt-info">
<div class="mobile-receipt-info__row">
@@ -223,8 +219,337 @@
</template>
</el-dialog>
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="出库单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入出库单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="出库时间" prop="outTime">
<el-date-picker
v-model="queryParams.outTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
clearable
placeholder="请选择状态"
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_SALE_OUT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="收款状态" prop="receiptStatus">
<el-select
v-model="queryParams.receiptStatus"
clearable
placeholder="请选择收款状态"
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_RECEIPT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="账户" prop="accountId">
<el-select
v-model="queryParams.accountId"
clearable
filterable
placeholder="请选择账户"
class="!w-240px"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建者" prop="creator">
<el-input
v-model="queryParams.creator"
placeholder="请输入创建者"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-outwarehouse:create']"
>
<Icon icon="ep:plus" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-outwarehouse:export']"
>
<Icon icon="ep:download" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" @row-click="handleRowClick">
<el-table-column label="出库单号" align="center" prop="no" min-width="180">
<template #default="scope">
<span>{{ scope.row.no }}</span>
</template>
</el-table-column>
<el-table-column label="客户" align="center" prop="customerName" min-width="180">
<template #default="scope">
<span>{{ scope.row.customerName }}</span>
</template>
</el-table-column>
<el-table-column label="产品" align="center" min-width="120">
<template #default="scope">
<div v-if="scope.row.itemList && scope.row.itemList.length > 0">
<div v-for="(productName, index) in getUniqueProductNames(scope.row.itemList)" :key="index" class="mb-1">
{{ productName }}
</div>
</div>
<span v-else>-</span>
</template>
</el-table-column>
<el-table-column label="出库时间" align="center" prop="outTime" min-width="180" sortable>
<template #default="scope">
<span>{{ formatDate(scope.row.outTime, 'YYYY-MM-DD HH:mm:ss') }}</span>
</template>
</el-table-column>
<el-table-column label="仓库" align="center" prop="warehouseNames" min-width="180">
<template #default="scope">
<div v-if="scope.row.warehouseNames">
<div v-for="(warehouse, index) in scope.row.warehouseNames.split(',')" :key="index">
{{ warehouse }}
</div>
</div>
<span v-else>{{ scope.row.warehouseName || '' }}</span>
</template>
</el-table-column>
<el-table-column label="合计数量" align="center" prop="totalCount" min-width="100">
<template #default="scope">
<span>{{ erpCountTableColumnFormatter(null, null, scope.row.totalCount, null) }}</span>
</template>
</el-table-column>
<el-table-column label="合计金额" align="center" prop="totalPrice" min-width="120">
<template #default="scope">
<span>{{ erpPriceTableColumnFormatter(null, null, scope.row.totalPrice, null) }}</span>
</template>
</el-table-column>
<el-table-column label="收款状态" align="center" prop="receiptStatus" min-width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_RECEIPT_STATUS" :value="scope.row.receiptStatus" />
</template>
</el-table-column>
<el-table-column label="已收款金额" align="center" prop="receiptPrice" min-width="120">
<template #default="scope">
<span>{{ erpPriceTableColumnFormatter(null, null, scope.row.receiptPrice, null) }}</span>
</template>
</el-table-column>
<el-table-column label="出库状态" align="center" prop="status" min-width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
width="350"
fixed="right"
>
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-outwarehouse:update']"
:disabled="scope.row.status === 20"
>
<Icon icon="ep:edit" />修改
</el-button>
<el-button
link
type="primary"
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:sale-outwarehouse:query']"
>
<Icon icon="ep:view" />详情
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, scope.row.status === 10 ? 20 : 10)"
v-if="scope.row.status === 10 || scope.row.status === 20"
v-hasPermi="['erp:sale-outwarehouse:update-status']"
>
<Icon icon="ep:check" />{{ scope.row.status === 10 ? '审核' : '反审核' }}
</el-button>
<el-button
link
type="success"
@click="openReceiptForm(scope.row)"
v-if="scope.row.status === 20"
v-hasPermi="['erp:sale-outwarehouse:update']"
>
<Icon icon="ep:money" />收款
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:sale-outwarehouse:delete']"
>
<Icon icon="ep:delete" />删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<SaleOutwarehouseForm ref="formRef" @success="getList" />
<!-- 收款表单弹窗 -->
<el-dialog v-model="receiptDialogVisible" title="收款" width="500px" @closed="receiptDialogVisible = false">
<div v-if="currentOutwarehouse">
<div class="mobile-receipt-info">
<div class="mobile-receipt-info__row"><span class="mobile-receipt-info__label">单号</span><span>{{ currentOutwarehouse.no }}</span></div>
<div class="mobile-receipt-info__row"><span class="mobile-receipt-info__label">客户</span><span>{{ currentOutwarehouse.customerName }}</span></div>
<div class="mobile-receipt-info__row"><span class="mobile-receipt-info__label">合计金额</span><span>{{ erpPriceTableColumnFormatter(null, null, currentOutwarehouse.totalPrice, null) }}</span></div>
<div class="mobile-receipt-info__row"><span class="mobile-receipt-info__label">已收款</span><span>{{ erpPriceTableColumnFormatter(null, null, currentOutwarehouse.receiptPrice, null) }}</span></div>
<div class="mobile-receipt-info__row"><span class="mobile-receipt-info__label">未收款</span><span class="mobile-receipt-info__danger">{{ erpPriceTableColumnFormatter(null, null, (currentOutwarehouse.totalPrice || 0) - (currentOutwarehouse.receiptPrice || 0), null) }}</span></div>
</div>
<el-form :model="receiptForm" label-width="80px" style="margin-top: 12px">
<el-form-item label="收款金额" required><el-input-number v-model="receiptForm.amount" :min="0" :precision="2" :step="0.01" :max="(currentOutwarehouse.totalPrice || 0) - (currentOutwarehouse.receiptPrice || 0)" style="width: 100%" /></el-form-item>
<el-form-item label="收款日期" required><el-date-picker v-model="receiptForm.date" type="date" value-format="YYYY-MM-DD" style="width: 100%" /></el-form-item>
<el-form-item label="备注"><el-input v-model="receiptForm.remark" type="textarea" :rows="2" placeholder="请输入备注" /></el-form-item>
</el-form>
<div style="margin-top: 12px">
<div style="font-weight: 600; margin-bottom: 8px">收款记录</div>
<div v-if="receiptHistory.length > 0">
<div v-for="(record, idx) in receiptHistory" :key="idx" class="mobile-receipt-record">
<div class="mobile-receipt-record__row"><span>{{ record.date }}</span><span class="mobile-receipt-record__amount">¥{{ erpPriceTableColumnFormatter(null, null, record.amount, null) }}</span></div>
<div class="mobile-receipt-record__detail" v-if="record.remark">{{ record.remark }}</div>
</div>
</div>
<div v-else style="text-align: center; padding: 16px; color: #909399;">暂无收款记录</div>
</div>
</div>
<template #footer>
<el-button @click="receiptDialogVisible = false">取消</el-button>
<el-button type="primary" @click="submitReceipt">确定</el-button>
</template>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import { SaleOutwarehouseApi, SaleOutwarehouseVO, SaleOutwarehouseReceiptVO } from '@/api/erp/sale/outwarehouse'
@@ -243,10 +568,14 @@ import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { formatDate } from '@/utils/formatTime'
import { ElMessageBox, ElMessage } from 'element-plus'
import { onActivated } from 'vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售出库列表 */
defineOptions({ name: 'ErpSaleOutwarehouse' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -571,6 +900,14 @@ onActivated(() => {
getList()
}
})
/** 行点击操作 */
const handleRowClick = (row: SaleOutwarehouseVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.closest('button') || target.closest('a') || target.closest('.el-button')) return
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
</script>
<style lang="scss" scoped>

View File

@@ -1,22 +1,8 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<!-- 基本信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
@@ -76,17 +62,50 @@
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="计划编号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="计划名称" prop="name"><el-input v-model="formData.name" placeholder="请输入计划名称" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="目标金额" prop="targetAmount"><el-input-number v-model="formData.targetAmount" controls-position="right" :min="0" :precision="4" placeholder="请输入目标金额" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="开始时间" prop="startTime"><el-date-picker v-model="formData.startTime" type="date" value-format="x" placeholder="选择开始时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结束时间" prop="endTime"><el-date-picker v-model="formData.endTime" type="date" value-format="x" placeholder="选择结束时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="审批人" prop="approverId"><el-select v-model="formData.approverId" clearable filterable placeholder="请选择审批人" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="计划产品明细" name="item"><SalePlanItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="合计金额"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch } from 'vue'
import { SalePlanApi, SalePlanVO } from '@/api/erp/sale/plan'
import SalePlanItemForm from './components/SalePlanItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { erpPriceInputFormatter } from '@/utils'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售计划表单 */
defineOptions({ name: 'SalePlanForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -95,20 +88,35 @@
</div>
</div>
<!-- 添加按钮 -->
<div class="mobile-item-add" v-if="!disabled">
<el-button @click="handleAdd" round>+ 添加计划产品</el-button>
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="计划销量" prop="planCount" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.planCount`" :rules="formRules.planCount" class="mb-0px!"><el-input-number v-model="row.planCount" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" :rules="formRules.productPrice" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加计划产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import {
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -148,7 +156,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
planCount: getSumValue(formData.value.map((item) => Number(item.planCount))),
@@ -156,6 +164,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['planCount', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,5 +1,6 @@
<template>
<div class="mobile-sale-plan">
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-sale-plan">
<!-- 顶部操作栏 -->
<div class="mobile-header">
<div class="mobile-header__search">
@@ -152,9 +153,292 @@
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
<!-- PC端布局 -->
<div v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="计划编号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入计划编号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="计划名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入计划名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option label="草稿" :value="10" />
<el-option label="已审核" :value="20" />
<!-- <el-option label="已批准" :value="30" />-->
<el-option label="已驳回" :value="40" />
</el-select>
</el-form-item>
<el-form-item label="计划时间" prop="planTime">
<el-date-picker
v-model="queryParams.planTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-plan:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-plan:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:sale-plan:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="计划编号" align="center" prop="no" />
<el-table-column label="计划名称" align="center" prop="name" min-width="150" />
<el-table-column label="客户" align="center" prop="customerName" min-width="120" />
<el-table-column
label="目标金额"
align="center"
prop="targetAmount"
:formatter="erpPriceTableColumnFormatter"
min-width="120"
/>
<el-table-column
label="已完成总额"
align="center"
prop="completedAmount"
:formatter="erpPriceTableColumnFormatter"
min-width="120"
/>
<el-table-column label="进度" align="center" prop="progress" min-width="120">
<template #default="scope">
<el-progress
:percentage="scope.row.progress || 0"
:status="scope.row.progress >= 100 ? 'success' : ''"
/>
</template>
</el-table-column>
<el-table-column label="完成状态" align="center" prop="completionStatus" min-width="100">
<template #default="scope">
<el-tag v-if="scope.row.completionStatus === 0" type="info">未开始</el-tag>
<el-tag v-else-if="scope.row.completionStatus === 1" type="warning">进行中</el-tag>
<el-tag v-else-if="scope.row.completionStatus === 2" type="success">已完成</el-tag>
<el-tag v-else-if="scope.row.completionStatus === 3" type="danger">已超期</el-tag>
</template>
</el-table-column>
<el-table-column
label="开始时间"
align="center"
prop="startTime"
:formatter="dateFormatter2"
width="120px"
/>
<el-table-column
label="结束时间"
align="center"
prop="endTime"
:formatter="dateFormatter2"
width="120px"
/>
<el-table-column label="审批人" align="center" prop="approverName" min-width="100" />
<el-table-column label="创建人" align="center" prop="creatorName" min-width="100" />
<el-table-column label="状态" align="center" width="90" prop="status">
<template #default="scope">
<el-tag v-if="scope.row.status === 10" type="info">草稿</el-tag>
<el-tag v-else-if="scope.row.status === 20" type="warning">已审核</el-tag>
<!-- <el-tag v-else-if="scope.row.status === 30" type="success">已批准</el-tag>-->
<el-tag v-else-if="scope.row.status === 40" type="danger">已驳回</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="380">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:sale-plan:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-plan:update']"
:disabled="scope.row.status === 30"
>
编辑
</el-button>
<!-- <el-button-->
<!-- link-->
<!-- type="warning"-->
<!-- @click="handleSubmit(scope.row.id)"-->
<!-- v-hasPermi="['erp:sale-plan:update-status']"-->
<!-- v-if="scope.row.status === 10"-->
<!-- >-->
<!-- 提交-->
<!-- </el-button>-->
<el-button
link
type="success"
@click="handleApprove(scope.row.id)"
v-hasPermi="['erp:sale-plan:update-status']"
v-if="scope.row.status === 10"
>
审核
</el-button>
<el-button
link
type="success"
@click="handleSubmitApproval(scope.row.id)"
v-hasPermi="['erp:sale-plan:submit-approval']"
v-if="scope.row.status === 10 && !scope.row.hasApprovalRecords"
>
提交审批
</el-button>
<el-button
link
type="info"
@click="handleViewApproval(scope.row.id)"
v-hasPermi="['erp:sale-plan:query-approval']"
v-if="scope.row.hasApprovalRecords"
>
审批记录
</el-button>
<el-button
link
type="primary"
@click="handleProcessApproval(scope.row.id)"
v-hasPermi="['erp:approval-record:process']"
v-if="scope.row.hasApprovalRecords && scope.row.status !== 20"
>
处理审批
</el-button>
<!-- <el-button-->
<!-- link-->
<!-- type="danger"-->
<!-- @click="handleReject(scope.row.id)"-->
<!-- v-hasPermi="['erp:sale-plan:update-status']"-->
<!-- v-if="scope.row.status === 20"-->
<!-- >-->
<!-- 驳回-->
<!-- </el-button>-->
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:sale-plan:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<SalePlanForm ref="formRef" @success="getList" />
<!-- 提交审批对话框 -->
<SubmitApprovalDialog ref="submitApprovalDialogRef" @success="getList" />
<!-- 审批记录对话框 -->
<ApprovalRecordsDialog ref="approvalDialogRef" />
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { formatDate } from '@/utils/formatTime'
import download from '@/utils/download'
@@ -166,10 +450,14 @@ import { erpPriceInputFormatter } from '@/utils'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { SubmitApprovalDialog, ApprovalRecordsDialog, ProcessApprovalDialog } from '@/components/Approval'
import { ApprovalRecordApi, ApprovalRecordVO } from '@/api/erp/approval/index'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售计划列表 */
defineOptions({ name: 'ErpSalePlan' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -253,6 +541,12 @@ const openForm = (type: string, id?: number) => {
formRef.value.open(type, id)
}
/** 选中操作 */
const selectionList = ref<SalePlanVO[]>([])
const handleSelectionChange = (rows: SalePlanVO[]) => {
selectionList.value = rows
}
/** 删除按钮操作 */
const handleDelete = async (ids: number[]) => {
try {
@@ -263,6 +557,7 @@ const handleDelete = async (ids: number[]) => {
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
@@ -335,6 +630,13 @@ onMounted(async () => {
customerList.value = await CustomerApi.getCustomerSimpleList()
userList.value = await UserApi.getSimpleUserList()
})
/** 行点击操作 */
const handleRowClick = (row: SalePlanVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.closest('button') || target.closest('a') || target.closest('.el-button')) return
openForm('detail', row.id)
}
</script>
<style lang="scss" scoped>

View File

@@ -1,114 +1,80 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="退货单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="退货时间" prop="returnTime">
<el-date-picker v-model="formData.returnTime" type="date" value-format="x" placeholder="选择退货时间" style="width: 100%" />
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input readonly>
<template #prefix>
<el-link v-if="formData.orderId" type="primary" @click.stop="openSaleOrderDetail" :underline="false">
{{ formData.orderNo }}
</el-link>
</template>
<template #append>
<el-button @click="openSaleOrderReturnEnableList">
<Icon icon="ep:search" /> 选择
</el-button>
</template>
</el-input>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" style="width: 100%">
<el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="销售人员" prop="saleUserId">
<el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" style="width: 100%">
<el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" />
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="退货单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="退货时间" prop="returnTime"><el-date-picker v-model="formData.returnTime" type="date" value-format="x" placeholder="选择退货时间" style="width:100%" /></el-form-item>
<el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderId" type="primary" @click.stop="openSaleOrderDetail" :underline="false">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openSaleOrderReturnEnableList"><Icon icon="ep:search" /></el-button></template></el-input></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" style="width:100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="选择销售人员" style="width:100%"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 退货产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">退货产品清单</div>
<SaleReturnItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
<!-- 价格信息 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">价格信息</div>
<el-form-item label="优惠率(%" prop="discountPercent">
<el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width: 100%" />
</el-form-item>
<el-form-item label="退款优惠" prop="discountPrice">
<el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠后金额">
<el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="其它费用" prop="otherPrice">
<el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width: 100%" />
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width: 100%">
<el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item label="应退金额" prop="totalPrice">
<el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" />
</el-form-item>
<el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" style="width:100%" /></el-form-item>
<el-form-item label="退款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
<el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" style="width:100%" /></el-form-item>
<el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" style="width:100%"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="应退金额" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item>
</div>
</el-form>
</div>
<!-- 底部按钮 -->
<template #footer>
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false" style="flex:1"> </el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2">
</el-button>
<el-button type="primary" @click="submitForm" :disabled="formLoading" v-if="!disabled" style="flex:2"> </el-button>
</div>
</template>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1440">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="退货单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="退货时间" prop="returnTime"><el-date-picker v-model="formData.returnTime" type="date" value-format="x" placeholder="选择退货时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="关联订单" prop="orderNo"><el-input readonly><template #prefix><el-link v-if="formData.orderId" type="primary" @click.stop="openSaleOrderDetail" :underline="false">{{ formData.orderNo }}</el-link></template><template #append><el-button @click="openSaleOrderReturnEnableList"><Icon icon="ep:search" /> 选择</el-button></template></el-input></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable disabled placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="销售人员" prop="saleUserId"><el-select v-model="formData.saleUserId" clearable filterable placeholder="请选择销售人员" class="!w-1/1"><el-option v-for="item in userList" :key="item.id" :label="item.nickname" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="退货产品清单" name="item"><SaleReturnItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="优惠率(%" prop="discountPercent"><el-input-number v-model="formData.discountPercent" controls-position="right" :min="0" :precision="4" placeholder="请输入优惠率" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="退款优惠" prop="discountPrice"><el-input disabled v-model="formData.discountPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="优惠后金额"><el-input disabled :model-value="formData.totalPrice - formData.otherPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="其它费用" prop="otherPrice"><el-input-number v-model="formData.otherPrice" controls-position="right" :min="0" :precision="4" placeholder="请输入其它费用" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="结算账户" prop="accountId"><el-select v-model="formData.accountId" clearable filterable placeholder="请选择结算账户" class="!w-1/1"><el-option v-for="item in accountList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item label="应退金额" prop="totalPrice"><el-input disabled v-model="formData.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></el-col>
</el-row>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
<!-- 可退货的订单列表 -->
<SaleOrderReturnEnableList ref="saleOrderReturnEnableListRef" @success="handleSaleOrderChange" />
<!-- 销售订单详情弹窗 -->
<SaleOrderForm ref="saleOrderFormRef" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { SaleReturnApi, SaleReturnVO } from '@/api/erp/sale/return'
import SaleReturnItemForm from './components/SaleReturnItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
@@ -118,10 +84,14 @@ import SaleOrderReturnEnableList from '@/views/erp/sale/order/components/SaleOrd
import SaleOrderForm from '@/views/erp/sale/order/SaleOrderForm.vue'
import { SaleOrderVO } from '@/api/erp/sale/order'
import * as UserApi from '@/api/system/user'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售退货表单 */
defineOptions({ name: 'SaleReturnForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -133,16 +126,38 @@
</div>
</div>
</el-form>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productName" /></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="已出库" fixed="right" min-width="80" v-if="formData[0]?.outCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.outCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="已退货" fixed="right" min-width="80" v-if="formData[0]?.returnCount != null"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.returnCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="金额" prop="totalProductPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalProductPrice`" class="mb-0px!"><el-input disabled v-model="row.totalProductPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税率(%" fixed="right" min-width="115"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPercent`" class="mb-0px!"><el-input-number v-model="row.taxPercent" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="税额" prop="taxPrice" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.taxPrice`" class="mb-0px!"><el-input disabled v-model="row.taxPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="税额合计" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button :disabled="formData.length === 1" @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -197,7 +212,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
return {
count: getSumValue(formData.value.map((item) => Number(item.count))),
@@ -207,6 +222,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index: number) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalProductPrice', 'taxPrice', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,6 +1,8 @@
<!-- 可退款的销售退货单列表 -->
<template>
<!-- 移动端布局 -->
<el-drawer
v-if="isMobile"
v-model="dialogVisible"
title="选择销售退货(仅展示可退款)"
direction="rtl"
@@ -116,20 +118,54 @@
</el-drawer>
<template #footer>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm">
</el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</el-drawer>
<!-- PC端布局 -->
<el-dialog v-else v-model="dialogVisible" title="选择销售退货(仅展示可退款)" width="900px" :close-on-press-escape="true" :destroy-on-close="true">
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
<el-form-item label="退货单号" prop="no"><el-input v-model="queryParams.no" placeholder="请输入退货单号" clearable @keyup.enter="handleQuery" class="!w-160px" /></el-form-item>
<el-form-item label="产品" prop="productId">
<el-select v-model="queryParams.productId" clearable filterable placeholder="请选择产品" class="!w-160px">
<el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" />
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="list" :stripe="true" @selection-change="handleSelectionChange" style="margin-top:16px">
<el-table-column type="selection" width="50" />
<el-table-column label="退货单号" align="center" prop="no" min-width="160" />
<el-table-column label="客户" align="center" prop="customerName" width="120" />
<el-table-column label="产品" align="center" prop="productNames" min-width="150" show-overflow-tooltip />
<el-table-column label="退货时间" align="center" prop="returnTime" width="110" :formatter="(row) => formatDate2(row.returnTime)" />
<el-table-column label="应退金额" align="center" prop="totalPrice" width="100"><template #default="scope"><span style="color:#e6a23c">¥{{ erpPriceInputFormatter(scope.row.totalPrice) }}</span></template></el-table-column>
<el-table-column label="已退金额" align="center" prop="refundPrice" width="100"><template #default="scope">¥{{ erpPriceInputFormatter(scope.row.refundPrice || 0) }}</template></el-table-column>
<el-table-column label="未退金额" align="center" width="100"><template #default="scope"><el-tag v-if="(scope.row.refundPrice || 0) < scope.row.totalPrice" type="danger">¥{{ erpPriceInputFormatter(scope.row.totalPrice - (scope.row.refundPrice || 0)) }}</el-tag><span v-else>0</span></template></el-table-column>
</el-table>
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
<template #footer>
<el-button @click="dialogVisible = false"> </el-button>
<el-button :disabled="!selectionList.length" type="primary" @click="submitForm"> </el-button>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { computed } from 'vue'
import { Search, Filter } from '@element-plus/icons-vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { SaleReturnApi, SaleReturnVO } from '@/api/erp/sale/return'
import { formatDate } from '@/utils/formatTime'
import { erpPriceInputFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const list = ref<SaleReturnVO[]>([])
const total = ref(0)
@@ -207,6 +243,11 @@ const handleQuery = () => {
selectionList.value = []
getList()
}
/** PC端表格选中变化 */
const handleSelectionChange = (rows: SaleReturnVO[]) => {
selectionList.value = rows
}
</script>
<style lang="scss" scoped>

View File

@@ -1,28 +1,13 @@
<template>
<div class="mobile-sale-return">
<!-- 顶部操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-sale-return">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索退货单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索退货单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:sale-return:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:sale-return:create']" />
</div>
</div>
<div class="mobile-header__quick-filter">
<div
class="quick-filter-item"
@@ -163,32 +148,335 @@
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<SaleReturnForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="退货单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入退货单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="退货时间" prop="outTime">
<el-date-picker
v-model="queryParams.outTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择供客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="关联订单" prop="orderNo">
<el-input
v-model="queryParams.orderNo"
placeholder="请输入关联订单"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="结算账户" prop="accountId">
<el-select
v-model="queryParams.accountId"
clearable
filterable
placeholder="请选择结算账户"
class="!w-240px"
>
<el-option
v-for="item in accountList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="退款状态" prop="refundStatus">
<el-select
v-model="queryParams.refundStatus"
placeholder="请选择退款状态"
clearable
class="!w-240px"
>
<el-option label="未退款" value="0" />
<el-option label="部分退款" value="1" />
<el-option label="全部退款" value="2" />
</el-select>
</el-form-item>
<el-form-item label="审核状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择审核状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:sale-return:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:sale-return:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:sale-return:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="退货单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column
label="退货时间"
align="center"
prop="returnTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="总数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="应退金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="已退金额"
align="center"
prop="refundPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="未退金额" align="center">
<template #default="scope">
<span v-if="scope.row.refundPrice === scope.row.totalPrice">0</span>
<el-tag type="danger" v-else>
{{ erpPriceInputFormatter(scope.row.totalPrice - scope.row.refundPrice) }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="审核状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:sale-return:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:sale-return:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:sale-return:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:sale-return:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:sale-return:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<SaleReturnForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate } from '@/utils/formatTime'
import { formatDate, dateFormatter2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { SaleReturnApi, SaleReturnVO } from '@/api/erp/sale/return'
import SaleReturnForm from './SaleReturnForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import {
erpCountInputFormatter,
erpPriceInputFormatter
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { AccountApi, AccountVO } from '@/api/erp/finance/account'
import { useWindowSize } from '@vueuse/core'
/** ERP 销售退货列表 */
defineOptions({ name: 'ErpSaleReturn' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -273,16 +561,31 @@ const handleCardClick = (row: SaleReturnVO) => {
/** 删除按钮操作 */
const handleDelete = async (ids: number[]) => {
try {
// 删除的二次确认
await message.delConfirm()
// 发起删除
await SaleReturnApi.deleteSaleReturn(ids)
message.success(t('common.delSuccess'))
// 刷新列表
await getList()
selectionList.value = selectionList.value.filter((item) => !ids.includes(item.id))
} catch {}
}
/** 选中操作(PC端) */
const selectionList = ref<SaleReturnVO[]>([])
const handleSelectionChange = (rows: SaleReturnVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClick = (row: SaleReturnVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) {
openForm('detail', row.id)
} else if (row.status === 10) {
openForm('update', row.id)
}
}
/** 审批/反审批操作 */
const handleUpdateStatus = async (id: number, status: number) => {
try {

View File

@@ -1,111 +1,59 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="业务时间" prop="bizTime">
<el-date-picker
v-model="formData.bizTime"
type="date"
value-format="x"
placeholder="选择业务时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-tag :type="formData.type === 10 ? 'success' : 'warning'" size="large">
{{ formData.type === 10 ? '组装单' : '拆卸单' }}
</el-tag>
</el-form-item>
<el-form-item :label="formData.type === 10 ? '成品' : '待拆产品'" prop="mainProductId">
<el-select
v-model="formData.mainProductId"
clearable
filterable
placeholder="请选择主产品"
style="width: 100%"
@change="onMainProductChange"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="formData.type === 10 ? '成品仓库' : '待拆仓库'" prop="mainWarehouseId">
<el-select
v-model="formData.mainWarehouseId"
clearable
filterable
placeholder="请选择仓库"
style="width: 100%"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item :label="formData.type === 10 ? '成品数量' : '待拆数量'" prop="mainCount">
<el-input-number
v-model="formData.mainCount"
controls-position="right"
:min="0.0001"
:precision="4"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="业务时间" prop="bizTime"><el-date-picker v-model="formData.bizTime" type="date" value-format="x" placeholder="选择业务时间" style="width: 100%" /></el-form-item>
<el-form-item label="类型" prop="type"><el-tag :type="formData.type === 10 ? 'success' : 'warning'" size="large">{{ formData.type === 10 ? '组装单' : '拆卸单' }}</el-tag></el-form-item>
<el-form-item :label="formData.type === 10 ? '成品' : '待拆产品'" prop="mainProductId"><el-select v-model="formData.mainProductId" clearable filterable placeholder="请选择主产品" style="width: 100%" @change="onMainProductChange"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item :label="formData.type === 10 ? '成品仓库' : '待拆仓库'" prop="mainWarehouseId"><el-select v-model="formData.mainWarehouseId" clearable filterable placeholder="请选择仓库" style="width: 100%"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item :label="formData.type === 10 ? '成品数量' : '待拆数量'" prop="mainCount"><el-input-number v-model="formData.mainCount" controls-position="right" :min="0.0001" :precision="4" style="width: 100%" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">{{ formData.type === 10 ? '原料/零件清单' : '拆卸产物清单' }}</div>
<AssemblyDisassemblyItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" :type="formData.type" />
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1200">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="120px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="业务时间" prop="bizTime"><el-date-picker v-model="formData.bizTime" type="date" value-format="x" placeholder="选择业务时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="类型" prop="type"><el-tag :type="formData.type === 10 ? 'success' : 'warning'" size="large">{{ formData.type === 10 ? '组装单' : '拆卸单' }}</el-tag></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8"><el-form-item :label="formData.type === 10 ? '成品' : '待拆产品'" prop="mainProductId"><el-select v-model="formData.mainProductId" clearable filterable placeholder="请选择主产品" class="!w-1/1" @change="onMainProductChange"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item :label="formData.type === 10 ? '成品仓库' : '待拆仓库'" prop="mainWarehouseId"><el-select v-model="formData.mainWarehouseId" clearable filterable placeholder="请选择仓库" class="!w-1/1"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="8"><el-form-item :label="formData.type === 10 ? '成品数量' : '待拆数量'" prop="mainCount"><el-input-number v-model="formData.mainCount" controls-position="right" :min="0.0001" :precision="4" class="!w-1/1" /></el-form-item></el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
</el-form>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane :label="formData.type === 10 ? '原料/零件清单' : '拆卸产物清单'" name="item"><AssemblyDisassemblyItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" :type="formData.type" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
@@ -115,10 +63,14 @@ import { AssemblyDisassemblyApi, AssemblyDisassemblyVO } from '@/api/erp/stock/a
import AssemblyDisassemblyItemForm from './components/AssemblyDisassemblyItemForm.vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { useWindowSize } from '@vueuse/core'
/** ERP 组装拆卸单 表单 */
defineOptions({ name: 'AssemblyDisassemblyForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -149,6 +101,7 @@ const productList = ref<ProductVO[]>([]) // 产品列表
const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
/** 子表的表单 */
const subTabsName = ref('item')
const itemFormRef = ref()
/** 打开弹窗 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -124,21 +117,38 @@
</div>
</div>
</el-form>
<div class="mobile-item-add" v-if="!disabled">
<div class="mobile-item-add" v-if="isMobile && !disabled">
<el-button @click="handleAdd" round style="width: 100%">+ 添加{{ type === 10 ? '原料/零件' : '拆卸产物' }}</el-button>
</div>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column :label="type === 10 ? '原料/零件' : '拆卸产物'" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加{{ type === 10 ? '原料/零件' : '拆卸产物' }}</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -190,7 +200,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -199,6 +209,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,16 +1,8 @@
<template>
<div class="mobile-assembly-disassembly">
<!-- 顶部搜索和操作 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-assembly-disassembly">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-dropdown @command="handleCreateCommand">
@@ -24,8 +16,6 @@
</el-dropdown>
</div>
</div>
<!-- 快捷筛选 -->
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
@@ -137,15 +127,271 @@
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<AssemblyDisassemblyForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select v-model="queryParams.type" placeholder="请选择类型" clearable class="!w-240px">
<el-option label="组装单" :value="10" />
<el-option label="拆卸单" :value="20" />
</el-select>
</el-form-item>
<el-form-item label="主产品" prop="mainProductId">
<el-select
v-model="queryParams.mainProductId"
clearable
filterable
placeholder="请选择主产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="业务时间" prop="bizTime">
<el-date-picker
v-model="queryParams.bizTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create', 10)"
v-hasPermi="['erp:assembly-disassembly:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增组装单
</el-button>
<el-button
type="warning"
plain
@click="openForm('create', 20)"
v-hasPermi="['erp:assembly-disassembly:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增拆卸单
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:assembly-disassembly:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:assembly-disassembly:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="单号" align="center" prop="no" />
<el-table-column label="类型" align="center" prop="typeName" width="100">
<template #default="scope">
<el-tag :type="scope.row.type === 10 ? 'success' : 'warning'">
{{ scope.row.typeName }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="主产品" align="center" prop="mainProductName" min-width="150" />
<el-table-column label="子产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column
label="业务时间"
align="center"
prop="bizTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="主产品数量"
align="center"
prop="mainCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="子产品数量"
align="center"
prop="totalSubCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.type, scope.row.id)"
v-hasPermi="['erp:assembly-disassembly:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.type, scope.row.id)"
v-hasPermi="['erp:assembly-disassembly:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:assembly-disassembly:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:assembly-disassembly:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:assembly-disassembly:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<AssemblyDisassemblyForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter2,formatDate2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate2 } from '@/utils/formatTime'
import download from '@/utils/download'
import { AssemblyDisassemblyApi, AssemblyDisassemblyVO } from '@/api/erp/stock/assdis'
import AssemblyDisassemblyForm from './AssemblyDisassemblyForm.vue'
@@ -157,10 +403,14 @@ import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/ut
import { useMessage } from '@/hooks/web/useMessage'
import { useI18n } from '@/hooks/web/useI18n'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 组装拆卸单列表 */
defineOptions({ name: 'ErpAssemblyDisassembly' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化
@@ -186,6 +436,7 @@ const exportLoading = ref(false) // 导出的加载中
const productList = ref<ProductVO[]>([]) // 产品列表
const warehouseList = ref<WarehouseVO[]>([]) // 仓库列表
const userList = ref<UserVO[]>([]) // 用户列表
const selectionList = ref<AssemblyDisassemblyVO[]>([]) // 选中列表
/** 查询列表 */
const getList = async () => {
@@ -279,31 +530,27 @@ const handleExport = async () => {
}
}
/** 行点击操作 */
/** 行点击操作(移动端) */
const handleRowClick = (row: AssemblyDisassemblyVO, event?: MouseEvent) => {
if (event) {
// 检查是否点击了按钮、链接或其他交互元素
const target = event.target as HTMLElement
if (
target.tagName === 'BUTTON' ||
target.tagName === 'A' ||
target.tagName === 'I' ||
target.tagName === 'svg' ||
target.closest('button') ||
target.closest('a') ||
target.closest('.el-button') ||
target.closest('.el-checkbox')
) {
return
}
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
}
if (row.status === 20) openForm('detail', row.type, row.id)
else if (row.status === 10) openForm('update', row.type, row.id)
}
// 已审核打开详情页面,未审核打开编辑页面
if (row.status === 20) {
openForm('detail', row.type, row.id)
} else if (row.status === 10) {
openForm('update', row.type, row.id)
}
/** 选中操作(PC端) */
const handleSelectionChange = (rows: AssemblyDisassemblyVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: AssemblyDisassemblyVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) openForm('detail', row.type, row.id)
else if (row.status === 10) openForm('update', row.type, row.id)
}
/** 初始化 **/

View File

@@ -1,72 +1,60 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="盘点单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="盘点时间" prop="checkTime">
<el-date-picker
v-model="formData.checkTime"
type="date"
value-format="x"
placeholder="选择盘点时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="盘点单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="盘点时间" prop="checkTime"><el-date-picker v-model="formData.checkTime" type="date" value-format="x" placeholder="选择盘点时间" style="width: 100%" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 盘点产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">盘点产品清单</div>
<StockCheckItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="盘点单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="盘点时间" prop="checkTime"><el-date-picker v-model="formData.checkTime" type="date" value-format="x" placeholder="选择盘点时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
</el-form>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="盘点产品清单" name="item"><StockCheckItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { StockCheckApi, StockCheckVO } from '@/api/erp/stock/check'
import StockCheckItemForm from './components/StockCheckItemForm.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 其它盘点单表单 */
defineOptions({ name: 'StockCheckForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -89,6 +77,7 @@ const disabled = computed(() => formType.value === 'detail')
const formRef = ref() // 表单 Ref
/** 子表的表单 */
const subTabsName = ref('item')
const itemFormRef = ref()
/** 打开弹窗 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -134,20 +127,39 @@
</div>
</div>
</el-form>
<div style="text-align: center; margin-top: 12px;" v-if="!disabled">
<div style="text-align: center; margin-top: 12px;" v-if="isMobile && !disabled">
<el-button @click="handleAdd" round>+ 添加盘点产品</el-button>
</div>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名字" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库名字" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="账面库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="实际库存" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.actualCount`" :rules="formRules.actualCount" class="mb-0px!"><el-input-number v-model="row.actualCount" controls-position="right" :precision="3" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="盈亏数量" prop="count" fixed="right" min-width="110"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input disabled v-model="row.count" :formatter="erpCountInputFormatter" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加盘点产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -195,7 +207,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -204,6 +216,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,23 +1,13 @@
<template>
<div class="mobile-stock-check">
<!-- 顶部搜索和操作 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-stock-check">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索盘点单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索盘点单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock-check:create']" />
</div>
</div>
<!-- 快捷筛选 -->
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
@@ -124,12 +114,282 @@
<!-- 处理审批对话框 -->
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="盘点单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入盘点单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="盘点时间" prop="checkTime">
<el-date-picker
v-model="queryParams.checkTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-check:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-check:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="warning"
plain
@click="openReport"
v-hasPermi="['erp:stock-check:query']"
>
<Icon icon="ep:data-analysis" class="mr-5px" /> 库存报告
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:stock-check:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="盘点单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column
label="盘点时间"
align="center"
prop="checkTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="380">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:stock-check:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:stock-check:update']"
:disabled="scope.row.status === 20 || scope.row.hasApprovalRecords"
>
编辑
</el-button>
<el-button
link
type="success"
@click="handleSubmitApproval(scope.row.id)"
v-hasPermi="['erp:stock-check:submit-approval']"
v-if="scope.row.status === 10 && !scope.row.hasApprovalRecords"
>
提交审批
</el-button>
<el-button
link
type="info"
@click="handleViewApproval(scope.row.id)"
v-hasPermi="['erp:stock-check:query-approval']"
v-if="scope.row.hasApprovalRecords"
>
审批记录
</el-button>
<el-button
link
type="primary"
@click="handleProcessApproval(scope.row.id)"
v-hasPermi="['erp:approval-record:process']"
v-if="scope.row.hasApprovalRecords && scope.row.status !== 20"
>
处理审批
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:stock-check:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:stock-check:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:stock-check:delete']"
:disabled="scope.row.hasApprovalRecords"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗 -->
<StockCheckForm ref="formRef" @success="getList" />
<StockReportDialog ref="reportDialogRef" />
<SubmitApprovalDialog ref="submitApprovalDialogRef" @success="getList" />
<ApprovalRecordsDialog ref="approvalDialogRef" />
<ProcessApprovalDialog ref="processApprovalDialogRef" @success="getList" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate2 } from '@/utils/formatTime'
import { formatDate2, dateFormatter2 } from '@/utils/formatTime'
import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { StockCheckApi, StockCheckVO } from '@/api/erp/stock/check'
import StockCheckForm from './StockCheckForm.vue'
@@ -142,10 +402,15 @@ import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { useMessage } from '@/hooks/web/useMessage'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
import download from '@/utils/download'
/** ERP 其它盘点单列表 */
defineOptions({ name: 'ErpStockCheck' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const loading = ref(true)
const list = ref<StockCheckVO[]>([])
@@ -163,9 +428,11 @@ const queryParams = reactive({
creator: undefined
})
const queryFormRef = ref()
const exportLoading = ref(false)
const productList = ref<ProductVO[]>([])
const warehouseList = ref<WarehouseVO[]>([])
const userList = ref<UserVO[]>([])
const selectionList = ref<StockCheckVO[]>([])
const getList = async () => {
loading.value = true
@@ -277,6 +544,31 @@ const handleRowClick = (row: StockCheckVO, event?: MouseEvent) => {
else if (row.status === 10) openForm('update', row.id)
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await StockCheckApi.exportStockCheck(queryParams)
download.excel(data, '库存盘点单.xls')
} finally {
exportLoading.value = false
}
}
/** 选中操作(PC端) */
const handleSelectionChange = (rows: StockCheckVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: StockCheckVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
onMounted(async () => {
await getList()
productList.value = await ProductApi.getProductSimpleList()

View File

@@ -1,80 +1,49 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="入库单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="入库时间" prop="inTime">
<el-date-picker
v-model="formData.inTime"
type="date"
value-format="x"
placeholder="选择入库时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="formData.supplierId"
clearable
filterable
placeholder="请选择供应商"
style="width: 100%"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="入库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="入库时间" prop="inTime"><el-date-picker v-model="formData.inTime" type="date" value-format="x" placeholder="选择入库时间" style="width: 100%" /></el-form-item>
<el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" style="width: 100%"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 入库产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">入库产品清单</div>
<StockInItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="入库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="入库时间" prop="inTime"><el-date-picker v-model="formData.inTime" type="date" value-format="x" placeholder="选择入库时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="供应商" prop="supplierId"><el-select v-model="formData.supplierId" clearable filterable placeholder="请选择供应商" class="!w-1/1"><el-option v-for="item in supplierList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
</el-form>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="入库产品清单" name="item"><StockInItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
@@ -83,10 +52,14 @@ import { useMessage } from '@/hooks/web/useMessage'
import { StockInApi, StockInVO } from '@/api/erp/stock/in'
import StockInItemForm from './components/StockInItemForm.vue'
import { SupplierApi, SupplierVO } from '@/api/erp/purchase/supplier'
import { useWindowSize } from '@vueuse/core'
/** ERP 其它入库单 表单 */
defineOptions({ name: 'StockInForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -110,6 +83,7 @@ const formRef = ref() // 表单 Ref
const supplierList = ref<SupplierVO[]>([]) // 供应商列表
/** 子表的表单 */
const subTabsName = ref('item')
const itemFormRef = ref()
/** 打开弹窗 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -124,21 +117,38 @@
</div>
</div>
</el-form>
<div class="mobile-item-add" v-if="!disabled">
<div class="mobile-item-add" v-if="isMobile && !disabled">
<el-button @click="handleAdd" round style="width: 100%">+ 添加入库产品</el-button>
</div>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加入库产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -189,7 +199,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -198,6 +208,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,23 +1,13 @@
<template>
<div class="mobile-stock-in">
<!-- 顶部搜索和操作 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-stock-in">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索入库单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索入库单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock-in:create']" />
</div>
</div>
<!-- 快捷筛选 -->
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
@@ -110,15 +100,260 @@
</template>
</el-drawer>
<!-- 表单弹窗 -->
<StockInForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="入库单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入入库单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="入库时间" prop="inTime">
<el-date-picker
v-model="queryParams.inTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select
v-model="queryParams.supplierId"
clearable
filterable
placeholder="请选择供应商"
class="!w-240px"
>
<el-option
v-for="item in supplierList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-in:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-in:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:stock-in:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="入库单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="供应商" align="center" prop="supplierName" />
<el-table-column
label="入库时间"
align="center"
prop="inTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:stock-in:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:stock-in:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:stock-in:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:stock-in:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:stock-in:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗 -->
<StockInForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { formatDate2 } from '@/utils/formatTime'
import { formatDate2, dateFormatter2 } from '@/utils/formatTime'
import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { StockInApi, StockInVO } from '@/api/erp/stock/in'
import StockInForm from './StockInForm.vue'
@@ -129,6 +364,10 @@ import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { useMessage } from '@/hooks/web/useMessage'
import { Search, Plus, Download, Filter } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const loading = ref(true)
@@ -233,6 +472,19 @@ const handleRowClick = (row: StockInVO, event?: MouseEvent) => {
else if (row.status === 10) openForm('update', row.id)
}
/** 选中操作(PC端) */
const handleSelectionChange = (rows: StockInVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: StockInVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
onMounted(async () => {
await getList()
productList.value = await ProductApi.getProductSimpleList()

View File

@@ -1,64 +1,47 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="调度单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="调度时间" prop="moveTime">
<el-date-picker
v-model="formData.moveTime"
type="date"
value-format="x"
placeholder="选择调度时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="调度单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="调度时间" prop="moveTime"><el-date-picker v-model="formData.moveTime" type="date" value-format="x" placeholder="选择调度时间" style="width: 100%" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 调度产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">调度产品清单</div>
<StockMoveItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="调度单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="调度时间" prop="moveTime"><el-date-picker v-model="formData.moveTime" type="date" value-format="x" placeholder="选择调度时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
</el-form>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="调度产品清单" name="item"><StockMoveItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
@@ -66,10 +49,14 @@ import { useI18n } from '@/hooks/web/useI18n'
import { useMessage } from '@/hooks/web/useMessage'
import { StockMoveApi, StockMoveVO } from '@/api/erp/stock/move'
import StockMoveItemForm from './components/StockMoveItemForm.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 库存调度单表单 */
defineOptions({ name: 'StockMoveForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -92,6 +79,7 @@ const disabled = computed(() => formType.value === 'detail')
const formRef = ref() // 表单 Ref
/** 子表的表单 */
const subTabsName = ref('item')
const itemFormRef = ref()
/** 打开弹窗 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -144,21 +137,39 @@
</div>
</div>
</el-form>
<div class="mobile-item-add" v-if="!disabled">
<div class="mobile-item-add" v-if="isMobile && !disabled">
<el-button @click="handleAdd" round style="width: 100%">+ 添加调度产品</el-button>
</div>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="调出仓库" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.fromWarehouseId`" :rules="formRules.fromWarehouseId" class="mb-0px!"><el-select v-model="row.fromWarehouseId" clearable filterable placeholder="请选择调出仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="调入仓库" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.toWarehouseId`" :rules="formRules.toWarehouseId" class="mb-0px!"><el-select v-model="row.toWarehouseId" clearable filterable placeholder="请选择调入仓库"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加调度产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -210,7 +221,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -219,6 +230,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,23 +1,13 @@
<template>
<div class="mobile-stock-move">
<!-- 顶部搜索和操作 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-stock-move">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索调度单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索调度单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock-move:create']" />
</div>
</div>
<!-- 快捷筛选 -->
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
@@ -106,15 +96,243 @@
</template>
</el-drawer>
<!-- 表单弹窗 -->
<StockMoveForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="调度单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入调度单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="调度时间" prop="moveTime">
<el-date-picker
v-model="queryParams.moveTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库" prop="fromWarehouseId">
<el-select
v-model="queryParams.fromWarehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-move:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-move:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:stock-move:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="调度单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column
label="调度时间"
align="center"
prop="moveTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:stock-move:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:stock-move:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:stock-move:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:stock-move:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:stock-move:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗 -->
<StockMoveForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter2,formatDate2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate2 } from '@/utils/formatTime'
import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { StockMoveApi, StockMoveVO } from '@/api/erp/stock/move'
import StockMoveForm from './StockMoveForm.vue'
@@ -124,10 +342,15 @@ import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { useMessage } from '@/hooks/web/useMessage'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
import download from '@/utils/download'
/** ERP 库存调度单列表 */
defineOptions({ name: 'ErpStockMove' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const loading = ref(true)
const list = ref<StockMoveVO[]>([])
@@ -145,9 +368,11 @@ const queryParams = reactive({
creator: undefined
})
const queryFormRef = ref()
const exportLoading = ref(false)
const productList = ref<ProductVO[]>([])
const warehouseList = ref<WarehouseVO[]>([])
const userList = ref<UserVO[]>([])
const selectionList = ref<StockMoveVO[]>([])
const getList = async () => {
loading.value = true
@@ -216,6 +441,31 @@ const handleRowClick = (row: StockMoveVO, event?: MouseEvent) => {
else if (row.status === 10) openForm('update', row.id)
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await StockMoveApi.exportStockMove(queryParams)
download.excel(data, '库存调度单.xls')
} finally {
exportLoading.value = false
}
}
/** 选中操作(PC端) */
const handleSelectionChange = (rows: StockMoveVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: StockMoveVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
onMounted(async () => {
await getList()
productList.value = await ProductApi.getProductSimpleList()

View File

@@ -1,80 +1,49 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
:disabled="disabled"
>
<!-- 基本信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top" :disabled="disabled">
<div class="mobile-form__section">
<div class="mobile-form__section-title">基本信息</div>
<el-form-item label="出库单号" prop="no">
<el-input disabled v-model="formData.no" placeholder="保存时自动生成" />
</el-form-item>
<el-form-item label="出库时间" prop="outTime">
<el-date-picker
v-model="formData.outTime"
type="date"
value-format="x"
placeholder="选择出库时间"
style="width: 100%"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="formData.customerId"
clearable
filterable
placeholder="请选择客户"
style="width: 100%"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
type="textarea"
v-model="formData.remark"
:rows="2"
placeholder="请输入备注"
/>
</el-form-item>
<el-form-item label="附件" prop="fileUrl">
<UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" />
</el-form-item>
<el-form-item label="出库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item>
<el-form-item label="出库时间" prop="outTime"><el-date-picker v-model="formData.outTime" type="date" value-format="x" placeholder="选择出库时间" style="width: 100%" /></el-form-item>
<el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" style="width: 100%"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="2" placeholder="请输入备注" /></el-form-item>
<el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item>
</div>
<!-- 出库产品清单 -->
<div class="mobile-form__section">
<div class="mobile-form__section-title">出库产品清单</div>
<StockOutItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" />
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible" width="1080">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading" :disabled="disabled">
<el-row :gutter="20">
<el-col :span="8"><el-form-item label="出库单号" prop="no"><el-input disabled v-model="formData.no" placeholder="保存时自动生成" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="出库时间" prop="outTime"><el-date-picker v-model="formData.outTime" type="date" value-format="x" placeholder="选择出库时间" class="!w-1/1" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="客户" prop="customerId"><el-select v-model="formData.customerId" clearable filterable placeholder="请选择客户" class="!w-1/1"><el-option v-for="item in customerList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></el-col>
<el-col :span="16"><el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" :rows="1" placeholder="请输入备注" /></el-form-item></el-col>
<el-col :span="8"><el-form-item label="附件" prop="fileUrl"><UploadFile :is-show-tip="false" v-model="formData.fileUrl" :limit="1" /></el-form-item></el-col>
</el-row>
</el-form>
<ContentWrap>
<el-tabs v-model="subTabsName" class="-mt-15px -mb-10px">
<el-tab-pane label="出库产品清单" name="item"><StockOutItemForm ref="itemFormRef" :items="formData.items" :disabled="disabled" /></el-tab-pane>
</el-tabs>
</ContentWrap>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading" v-if="!disabled"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { ref, reactive, computed, nextTick } from 'vue'
@@ -83,10 +52,14 @@ import { useMessage } from '@/hooks/web/useMessage'
import { StockOutApi, StockOutVO } from '@/api/erp/stock/out'
import StockOutItemForm from './components/StockOutItemForm.vue'
import { CustomerApi, CustomerVO } from '@/api/erp/sale/customer'
import { useWindowSize } from '@vueuse/core'
/** ERP 其它出库单表单 */
defineOptions({ name: 'StockOutForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
@@ -110,6 +83,7 @@ const formRef = ref() // 表单 Ref
const customerList = ref<CustomerVO[]>([]) // 客户列表
/** 子表的表单 */
const subTabsName = ref('item')
const itemFormRef = ref()
/** 打开弹窗 */

View File

@@ -1,13 +1,6 @@
<template>
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
v-loading="formLoading"
label-position="top"
:inline-message="true"
:disabled="disabled"
>
<!-- 移动端布局 -->
<el-form v-if="isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-position="top" :inline-message="true" :disabled="disabled">
<div class="mobile-item-list">
<div
v-for="(row, $index) in formData"
@@ -124,21 +117,38 @@
</div>
</div>
</el-form>
<div class="mobile-item-add" v-if="!disabled">
<div class="mobile-item-add" v-if="isMobile && !disabled">
<el-button @click="handleAdd" round style="width: 100%">+ 添加出库产品</el-button>
</div>
<!-- PC端布局 -->
<el-form v-if="!isMobile" ref="formRef" :model="formData" :rules="formRules" v-loading="formLoading" label-width="0px" :inline-message="true" :disabled="disabled">
<el-table :data="formData" show-summary :summary-method="getSummaries" class="-mt-10px">
<el-table-column label="序号" type="index" align="center" width="60" />
<el-table-column label="仓库名称" min-width="125"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.warehouseId`" :rules="formRules.warehouseId" class="mb-0px!"><el-select v-model="row.warehouseId" clearable filterable placeholder="请选择仓库" @change="onChangeWarehouse($event, row)"><el-option v-for="item in warehouseList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="产品名称" min-width="180"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productId`" :rules="formRules.productId" class="mb-0px!"><el-select v-model="row.productId" clearable filterable @change="onChangeProduct($event, row)" placeholder="请选择产品"><el-option v-for="item in productList" :key="item.id" :label="item.name" :value="item.id" /></el-select></el-form-item></template></el-table-column>
<el-table-column label="库存" min-width="100"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.stockCount" :formatter="erpCountInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="条码" min-width="150"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productBarCode" /></el-form-item></template></el-table-column>
<el-table-column label="单位" min-width="80"><template #default="{ row }"><el-form-item class="mb-0px!"><el-input disabled v-model="row.productUnitName" /></el-form-item></template></el-table-column>
<el-table-column label="数量" prop="count" fixed="right" min-width="140"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.count`" :rules="formRules.count" class="mb-0px!"><el-input-number v-model="row.count" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="产品单价" fixed="right" min-width="120"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.productPrice`" class="mb-0px!"><el-input-number v-model="row.productPrice" controls-position="right" :min="0.0001" :precision="4" class="!w-100%" /></el-form-item></template></el-table-column>
<el-table-column label="合计金额" prop="totalPrice" fixed="right" min-width="100"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.totalPrice`" class="mb-0px!"><el-input disabled v-model="row.totalPrice" :formatter="erpPriceInputFormatter" /></el-form-item></template></el-table-column>
<el-table-column label="备注" min-width="150"><template #default="{ row, $index }"><el-form-item :prop="`${$index}.remark`" class="mb-0px!"><el-input v-model="row.remark" placeholder="请输入备注" /></el-form-item></template></el-table-column>
<el-table-column align="center" fixed="right" label="操作" width="60"><template #default="{ $index }"><el-button @click="handleDelete($index)" link></el-button></template></el-table-column>
</el-table>
</el-form>
<el-row v-if="!isMobile && !disabled" justify="center" class="mt-3"><el-button @click="handleAdd" round>+ 添加出库产品</el-button></el-row>
</template>
<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { StockApi } from '@/api/erp/stock/stock'
import {
erpCountInputFormatter,
erpPriceInputFormatter,
erpPriceMultiply,
getSumValue
} from '@/utils'
import { erpCountInputFormatter, erpPriceInputFormatter, erpPriceMultiply, getSumValue } from '@/utils'
import { useWindowSize } from '@vueuse/core'
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const props = defineProps<{
items: undefined
@@ -189,7 +199,7 @@ watch(
{ deep: true }
)
/** 合计 */
/** 合计 - 移动端 */
const summaryData = computed(() => {
const data = formData.value
return {
@@ -198,6 +208,20 @@ const summaryData = computed(() => {
}
})
/** 合计 - PC端 */
const getSummaries = (param: SummaryMethodProps) => {
const { columns, data } = param
const sums: string[] = []
columns.forEach((column, index) => {
if (index === 0) { sums[index] = '合计'; return }
if (['count', 'totalPrice'].includes(column.property)) {
const sum = getSumValue(data.map((item) => Number(item[column.property])))
sums[index] = column.property === 'count' ? erpCountInputFormatter(sum) : erpPriceInputFormatter(sum)
} else { sums[index] = '' }
})
return sums
}
/** 新增按钮操作 */
const handleAdd = () => {
const row = {

View File

@@ -1,23 +1,13 @@
<template>
<div class="mobile-stock-out">
<!-- 顶部搜索和操作 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-stock-out">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.no"
placeholder="搜索出库单号"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.no" placeholder="搜索出库单号" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock-out:create']" />
</div>
</div>
<!-- 快捷筛选 -->
<div class="mobile-header__quick-filter">
<div class="quick-filter-item" :class="{ active: queryParams.status === undefined }" @click="handleQuickFilter(undefined)">全部</div>
<div class="quick-filter-item" :class="{ active: queryParams.status === 10 }" @click="handleQuickFilter(10)">待审核</div>
@@ -115,15 +105,260 @@
</template>
</el-drawer>
<!-- 表单弹窗 -->
<StockOutForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="出库单号" prop="no">
<el-input
v-model="queryParams.no"
placeholder="请输入出库单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="出库时间" prop="outTime">
<el-date-picker
v-model="queryParams.outTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-select
v-model="queryParams.customerId"
clearable
filterable
placeholder="请选择供客户"
class="!w-240px"
>
<el-option
v-for="item in customerList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="创建人" prop="creator">
<el-select
v-model="queryParams.creator"
clearable
filterable
placeholder="请选择创建人"
class="!w-240px"
>
<el-option
v-for="item in userList"
:key="item.id"
:label="item.nickname"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="请选择状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_AUDIT_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input
v-model="queryParams.remark"
placeholder="请输入备注"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-out:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-out:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="danger"
plain
@click="handleDelete(selectionList.map((item) => item.id))"
v-hasPermi="['erp:stock-out:delete']"
:disabled="selectionList.length === 0"
>
<Icon icon="ep:delete" class="mr-5px" /> 删除
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading="loading"
:data="list"
:stripe="true"
:show-overflow-tooltip="true"
@selection-change="handleSelectionChange"
@row-click="handleRowClick"
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column min-width="180" label="出库单号" align="center" prop="no" />
<el-table-column label="产品信息" align="center" prop="productNames" min-width="200" />
<el-table-column label="客户" align="center" prop="customerName" />
<el-table-column
label="出库时间"
align="center"
prop="outTime"
:formatter="dateFormatter2"
width="120px"
sortable
/>
<el-table-column label="创建人" align="center" prop="creatorName" />
<el-table-column
label="数量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="金额"
align="center"
prop="totalPrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="状态" align="center" fixed="right" width="90" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_AUDIT_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="220">
<template #default="scope">
<el-button
link
@click="openForm('detail', scope.row.id)"
v-hasPermi="['erp:stock-out:query']"
>
详情
</el-button>
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:stock-out:update']"
:disabled="scope.row.status === 20"
>
编辑
</el-button>
<el-button
link
type="primary"
@click="handleUpdateStatus(scope.row.id, 20)"
v-hasPermi="['erp:stock-out:update-status']"
v-if="scope.row.status === 10"
>
审批
</el-button>
<el-button
link
type="danger"
@click="handleUpdateStatus(scope.row.id, 10)"
v-hasPermi="['erp:stock-out:update-status']"
v-else
>
反审批
</el-button>
<el-button
link
type="danger"
@click="handleDelete([scope.row.id])"
v-hasPermi="['erp:stock-out:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗 -->
<StockOutForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { ref, reactive, onMounted, computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter2,formatDate2 } from '@/utils/formatTime'
import { dateFormatter2, formatDate2 } from '@/utils/formatTime'
import { erpCountTableColumnFormatter, erpPriceTableColumnFormatter } from '@/utils'
import { StockOutApi, StockOutVO } from '@/api/erp/stock/out'
import StockOutForm from './StockOutForm.vue'
@@ -134,10 +369,15 @@ import { UserVO } from '@/api/system/user'
import * as UserApi from '@/api/system/user'
import { useMessage } from '@/hooks/web/useMessage'
import { Search, Plus, Filter } from '@element-plus/icons-vue'
import { useWindowSize } from '@vueuse/core'
import download from '@/utils/download'
/** ERP 其它出库单列表 */
defineOptions({ name: 'ErpStockOut' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage()
const loading = ref(true)
const list = ref<StockOutVO[]>([])
@@ -156,10 +396,12 @@ const queryParams = reactive({
creator: undefined
})
const queryFormRef = ref()
const exportLoading = ref(false)
const productList = ref<ProductVO[]>([])
const warehouseList = ref<WarehouseVO[]>([])
const customerList = ref<CustomerVO[]>([])
const userList = ref<UserVO[]>([])
const selectionList = ref<StockOutVO[]>([])
const getList = async () => {
loading.value = true
@@ -228,6 +470,31 @@ const handleRowClick = (row: StockOutVO, event?: MouseEvent) => {
else if (row.status === 10) openForm('update', row.id)
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
await message.exportConfirm()
exportLoading.value = true
const data = await StockOutApi.exportStockOut(queryParams)
download.excel(data, '其它出库单.xls')
} finally {
exportLoading.value = false
}
}
/** 选中操作(PC端) */
const handleSelectionChange = (rows: StockOutVO[]) => {
selectionList.value = rows
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: StockOutVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.status === 20) openForm('detail', row.id)
else if (row.status === 10) openForm('update', row.id)
}
onMounted(async () => {
await getList()
productList.value = await ProductApi.getProductSimpleList()

View File

@@ -1,30 +1,14 @@
<!-- ERP 产品库存明细列表 - 移动端适配 -->
<!-- ERP 产品库存明细列表 -->
<template>
<div class="mobile-record">
<!-- 搜索操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-record">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="searchKeyword"
placeholder="搜索产品名称"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="searchKeyword" placeholder="搜索产品名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="showSearch = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:stock-record:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock-record:create']" />
</div>
</div>
<!-- 快捷操作 -->
<div class="mobile-quick-actions">
<el-button
size="small"
@@ -239,9 +223,209 @@
<!-- 质检详情弹窗 -->
<QualityDetailDialog v-model:visible="dialogVisible" :quality-id="selectedQualityId" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="产品分类" prop="categoryId">
<el-select
v-model="queryParams.categoryId"
clearable
filterable
placeholder="请选择产品分类"
class="!w-240px"
>
<el-option
v-for="item in categoryList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="操作类型" prop="bizType">
<el-select
v-model="queryParams.bizType"
placeholder="请选择操作类型"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="业务单号" prop="bizNo">
<el-input
v-model="queryParams.bizNo"
placeholder="请输入业务单号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
v-model="queryParams.createTime"
value-format="YYYY-MM-DD HH:mm:ss"
type="daterange"
start-placeholder="开始日期"
end-placeholder="结束日期"
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class="!w-240px"
/>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock-record:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock-record:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
<el-button
type="success"
plain
@click="handleExportProduct"
:loading="exportBatchLoading"
v-hasPermi="['erp:stock-record:export-product']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出批次
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="产品分类" align="center" prop="categoryName" />
<el-table-column label="产品单位" align="center" prop="unitName" />
<el-table-column label="仓库编号" align="center" prop="warehouseName" />
<el-table-column label="操作类型" align="center" prop="bizType" min-width="100">
<template #default="scope">
<dict-tag :type="DICT_TYPE.ERP_STOCK_RECORD_BIZ_TYPE" :value="scope.row.bizType" />
</template>
</el-table-column>
<el-table-column label="出入库单号" align="center" prop="bizNo" width="200" />
<el-table-column
label="出入库日期"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column
label="出入库数量"
align="center"
prop="count"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column
label="库存量"
align="center"
prop="totalCount"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column label="单价" align="center" prop="unitPrice" v-hasPermi="['erp:stock:goods-value']">
<template #default="scope">
{{ scope.row.unitPrice != null ? scope.row.unitPrice.toFixed(4) : '-' }}
</template>
</el-table-column>
<el-table-column label="货值" align="center" prop="stockValue" v-hasPermi="['erp:stock:goods-value']">
<template #default="scope">
{{ scope.row.stockValue != null ? scope.row.stockValue.toFixed(4) : '-' }}
</template>
</el-table-column>
<el-table-column label="操作人" align="center" prop="creatorName" />
<el-table-column label="操作" align="center" width="150">
<template #default="scope">
<el-button
link
type="primary"
@click="handleDetail(scope.row.bizId, scope.row)"
v-hasPermi="['erp:stock-record:review']"
:disabled="scope.row.bizType !== 90"
>
<Icon icon="ep:view" /> 查询
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 质检详情弹窗 -->
<QualityDetailDialog v-model:visible="dialogVisible" :quality-id="selectedQualityId" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
@@ -252,10 +436,14 @@ import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { ProductCategoryApi } from '@/api/erp/product/category'
import { erpCountTableColumnFormatter } from '@/utils'
import QualityDetailDialog from './QualityDetailDialog.vue'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品库存明细列表 */
defineOptions({ name: 'ErpStockRecord' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化

View File

@@ -1,30 +1,14 @@
<!-- ERP 产品库存列表 - 移动端适配 -->
<!-- ERP 产品库存列表 -->
<template>
<div class="mobile-stock">
<!-- 搜索操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-stock">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="searchKeyword"
placeholder="搜索产品名称"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="searchKeyword" placeholder="搜索产品名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="showSearch = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:stock:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:stock:create']" />
</div>
</div>
<!-- 快捷操作 -->
<div class="mobile-quick-actions">
<el-button
size="small"
@@ -128,19 +112,125 @@
</template>
</el-drawer>
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="产品" prop="productId">
<el-select
v-model="queryParams.productId"
clearable
filterable
placeholder="请选择产品"
class="!w-240px"
>
<el-option
v-for="item in productList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item label="仓库" prop="warehouseId">
<el-select
v-model="queryParams.warehouseId"
clearable
filterable
placeholder="请选择仓库"
class="!w-240px"
>
<el-option
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:stock:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:stock:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="产品名称" align="center" prop="productName" />
<el-table-column label="产品单位" align="center" prop="unitName" />
<el-table-column label="产品分类" align="center" prop="categoryName" />
<el-table-column
label="库存量"
align="center"
prop="count"
:formatter="erpCountTableColumnFormatter"
/>
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="单价" align="center" prop="unitPrice" v-hasPermi="['erp:stock:goods-value']">
<template #default="scope">
{{ scope.row.unitPrice != null ? scope.row.unitPrice.toFixed(4) : '-' }}
</template>
</el-table-column>
<el-table-column label="货值" align="center" prop="stockValue" v-hasPermi="['erp:stock:goods-value']">
<template #default="scope">
{{ scope.row.stockValue != null ? scope.row.stockValue.toFixed(4) : '-' }}
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import download from '@/utils/download'
import { StockApi, StockVO } from '@/api/erp/stock/stock'
import { ProductApi, ProductVO } from '@/api/erp/product/product'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { erpCountTableColumnFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
/** ERP 产品库存列表 */
defineOptions({ name: 'ErpStock' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const message = useMessage() // 消息弹窗
const { t } = useI18n() // 国际化

View File

@@ -1,96 +1,60 @@
<template>
<el-drawer
v-model="dialogVisible"
:title="dialogTitle"
direction="rtl"
size="100%"
:close-on-press-escape="true"
:destroy-on-close="true"
:append-to-body="true"
class="mobile-form-drawer"
>
<!-- 移动端布局 -->
<el-drawer v-if="isMobile" v-model="dialogVisible" :title="dialogTitle" direction="rtl" size="100%" :close-on-press-escape="true" :destroy-on-close="true" :append-to-body="true" class="mobile-form-drawer">
<div class="mobile-form" v-loading="formLoading">
<el-form
ref="formRef"
:model="formData"
:rules="formRules"
label-position="top"
>
<!-- 基础信息 -->
<el-form ref="formRef" :model="formData" :rules="formRules" label-position="top">
<div class="mobile-form-section">
<div class="mobile-form-section__title">基础信息</div>
<el-form-item label="仓库名称" prop="name">
<el-input v-model="formData.name" placeholder="请输入仓库名称" clearable />
</el-form-item>
<el-form-item label="仓库地址" prop="address">
<el-input v-model="formData.address" placeholder="请输入仓库地址" clearable />
</el-form-item>
<el-form-item label="负责人" prop="principal">
<el-input v-model="formData.principal" placeholder="请输入负责人" clearable />
</el-form-item>
<el-form-item label="仓储费" prop="warehousePrice">
<el-input-number
v-model="formData.warehousePrice"
placeholder="请输入仓储费,单位:元/天/KG"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="搬运费" prop="truckagePrice">
<el-input-number
v-model="formData.truckagePrice"
placeholder="请输入搬运费,单位:元"
:min="0"
:precision="4"
controls-position="right"
/>
</el-form-item>
<el-form-item label="仓库名称" prop="name"><el-input v-model="formData.name" placeholder="请输入仓库名称" clearable /></el-form-item>
<el-form-item label="仓库地址" prop="address"><el-input v-model="formData.address" placeholder="请输入仓库地址" clearable /></el-form-item>
<el-form-item label="负责人" prop="principal"><el-input v-model="formData.principal" placeholder="请输入负责人" clearable /></el-form-item>
<el-form-item label="仓储费" prop="warehousePrice"><el-input-number v-model="formData.warehousePrice" placeholder="请输入仓储费" :min="0" :precision="4" controls-position="right" /></el-form-item>
<el-form-item label="搬运费" prop="truckagePrice"><el-input-number v-model="formData.truckagePrice" placeholder="请输入搬运费" :min="0" :precision="4" controls-position="right" /></el-form-item>
</div>
<!-- 状态信息 -->
<div class="mobile-form-section">
<div class="mobile-form-section__title">状态信息</div>
<el-form-item label="仓库状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:value="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input-number
v-model="formData.sort"
placeholder="请输入排序"
:precision="0"
controls-position="right"
/>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="3" />
</el-form-item>
<el-form-item label="仓库状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="排序" prop="sort"><el-input-number v-model="formData.sort" placeholder="请输入排序" :precision="0" controls-position="right" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" :rows="3" /></el-form-item>
</div>
</el-form>
<!-- 底部操作按钮 -->
<div class="mobile-form__footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
</div>
</div>
</el-drawer>
<!-- PC端布局 -->
<Dialog v-else :title="dialogTitle" v-model="dialogVisible">
<el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px" v-loading="formLoading">
<el-form-item label="仓库名称" prop="name"><el-input v-model="formData.name" placeholder="请输入仓库名称" /></el-form-item>
<el-form-item label="仓库地址" prop="address"><el-input v-model="formData.address" placeholder="请输入仓库地址" /></el-form-item>
<el-form-item label="仓库状态" prop="status"><el-radio-group v-model="formData.status"><el-radio v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)" :key="dict.value" :value="dict.value">{{ dict.label }}</el-radio></el-radio-group></el-form-item>
<el-form-item label="仓储费" prop="warehousePrice"><el-input-number v-model="formData.warehousePrice" placeholder="请输入仓储费" :min="0" :precision="4" class="!w-1/1" /></el-form-item>
<el-form-item label="搬运费" prop="truckagePrice"><el-input-number v-model="formData.truckagePrice" placeholder="请输入搬运费" :min="0" :precision="4" class="!w-1/1" /></el-form-item>
<el-form-item label="负责人" prop="principal"><el-input v-model="formData.principal" placeholder="请输入负责人" /></el-form-item>
<el-form-item label="排序" prop="sort"><el-input-number v-model="formData.sort" placeholder="请输入排序" :precision="0" class="!w-1/1" /></el-form-item>
<el-form-item label="备注" prop="remark"><el-input type="textarea" v-model="formData.remark" placeholder="请输入备注" /></el-form-item>
</el-form>
<template #footer>
<el-button @click="submitForm" type="primary" :disabled="formLoading"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import { CommonStatusEnum } from '@/utils/constants'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'WarehouseFormMobile' })
defineOptions({ name: 'WarehouseForm' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const { t } = useI18n()
const message = useMessage()

View File

@@ -1,29 +1,13 @@
<template>
<div class="mobile-warehouse">
<!-- 搜索操作栏 -->
<!-- 移动端布局 -->
<div v-if="isMobile" class="mobile-warehouse">
<div class="mobile-header">
<div class="mobile-header__search">
<el-input
v-model="queryParams.name"
placeholder="搜索仓库名称"
clearable
@keyup.enter="handleQuery"
:prefix-icon="Search"
/>
</div>
<div class="mobile-header__search"><el-input v-model="queryParams.name" placeholder="搜索仓库名称" clearable @keyup.enter="handleQuery" :prefix-icon="Search" /></div>
<div class="mobile-header__actions">
<el-button :icon="Filter" circle @click="filterVisible = true" />
<el-button
type="primary"
:icon="Plus"
circle
@click="openForm('create')"
v-hasPermi="['erp:warehouse:create']"
/>
<el-button type="primary" :icon="Plus" circle @click="openForm('create')" v-hasPermi="['erp:warehouse:create']" />
</div>
</div>
<!-- 快捷操作 -->
<div class="mobile-quick-actions">
<el-button
size="small"
@@ -150,12 +134,147 @@
</template>
</el-drawer>
<!-- 表单弹窗添加/修改 -->
<WarehouseForm ref="formRef" @success="getList" />
</div>
<!-- PC端布局 -->
<template v-else>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="仓库名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入仓库名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="仓库状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="请选择仓库状态"
clearable
class="!w-240px"
>
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['erp:warehouse:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['erp:warehouse:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true" @row-click="handleRowClick">
<el-table-column label="仓库名称" align="center" prop="name" />
<el-table-column label="仓库地址" align="center" prop="address" />
<el-table-column
label="仓储费"
align="center"
prop="warehousePrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column
label="搬运费"
align="center"
prop="truckagePrice"
:formatter="erpPriceTableColumnFormatter"
/>
<el-table-column label="负责人" align="center" prop="principal" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="是否默认" align="center" prop="defaultStatus">
<template #default="scope">
<el-switch
v-model="scope.row.defaultStatus"
:active-value="true"
:inactive-value="false"
@change="handleDefaultStatusChange(scope.row)"
/>
</template>
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="createTime"
:formatter="dateFormatter"
width="180px"
sortable
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['erp:warehouse:update']"
>
编辑
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['erp:warehouse:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
</template>
<!-- 表单弹窗添加/修改 -->
<WarehouseForm ref="formRef" @success="getList" />
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { Search, Filter, Plus } from '@element-plus/icons-vue'
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
@@ -163,8 +282,12 @@ import download from '@/utils/download'
import { WarehouseApi, WarehouseVO } from '@/api/erp/stock/warehouse'
import WarehouseForm from './WarehouseForm.vue'
import { erpPriceTableColumnFormatter } from '@/utils'
import { useWindowSize } from '@vueuse/core'
defineOptions({ name: 'ErpWarehouseMobile' })
defineOptions({ name: 'ErpWarehouse' })
const { width } = useWindowSize()
const isMobile = computed(() => width.value < 768)
const loading = ref(true)
const list = ref<WarehouseVO[]>([])
@@ -215,6 +338,14 @@ const handleCardClick = (row: WarehouseVO) => {
openForm('update', row.id)
}
/** 行点击操作(PC端) */
const handleRowClickPC = (row: WarehouseVO, column: any, event: MouseEvent) => {
const target = event.target as HTMLElement
if (target.tagName === 'BUTTON' || target.tagName === 'A' || target.tagName === 'I' || target.tagName === 'svg' || target.closest('button') || target.closest('a') || target.closest('.el-button') || target.closest('.el-checkbox')) return
if (row.name === '-') return
openForm('update', row.id)
}
const handleDelete = async (id: number) => {
try {
await message.delConfirm()