feat: 更新采购计划和出入库管理功能
添加清除所有草稿功能 扩展采购计划和出入库接口类型定义 新增出入库统计和产品列表接口 重写计划详情页面数据展示逻辑 改进数据分析组件支持动态数据 优化库存管理页面查询和展示逻辑 完善详情信息组件展示和文件预览功能
This commit is contained in:
@ -5,7 +5,7 @@ VITE_APP_TITLE = 新能源场站智慧运维平台
|
||||
VITE_APP_ENV = 'development'
|
||||
|
||||
# 开发环境
|
||||
VITE_APP_BASE_API = 'http://192.168.110.210:18899'
|
||||
VITE_APP_BASE_API = 'http://192.168.110.149:18899'
|
||||
|
||||
# 应用访问路径 例如使用前缀 /admin/
|
||||
VITE_APP_CONTEXT_PATH = '/'
|
||||
|
||||
@ -54,3 +54,45 @@ export const caigouPlanDetail = (id: string | number): AxiosPromise<CaigouPlanVO
|
||||
method: 'get'
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* 更新运维-物资-采购计划单
|
||||
* @param data
|
||||
* @returns {*}
|
||||
*/
|
||||
export const updateCaigouPlan = (data: CaigouPlanForm): AxiosPromise<CaigouPlanVO> => {
|
||||
return request({
|
||||
url: '/ops/caigouPlan',
|
||||
method: 'put',
|
||||
data: data
|
||||
});
|
||||
};
|
||||
|
||||
// /**
|
||||
// * 查询运维-物资-采购计划单年度金额
|
||||
// * @param query
|
||||
// * @returns {*}
|
||||
// */
|
||||
// export const getJinE = (query?: CaigouPlanQuery): AxiosPromise<any> => {
|
||||
// return request({
|
||||
// url: '/ops/caigouPlan/getJinE',
|
||||
// method: 'get',
|
||||
// params: query
|
||||
// });
|
||||
// };
|
||||
|
||||
/**
|
||||
* 查询运维-物资-采购计划单年度金额
|
||||
* @param id
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getCount = (id: string | number): AxiosPromise<CaigouPlanVO> => {
|
||||
return request({
|
||||
url: '/ops/caigouPlan/getJinE',
|
||||
method: 'get',
|
||||
params: {
|
||||
projectId: id
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@ -178,6 +178,10 @@ export interface CaigouPlanVO {
|
||||
* 采购申请计划文件 查询
|
||||
*/
|
||||
opsCaigouPlanFilesVos?: Array<any>;
|
||||
/**
|
||||
* 申请原因
|
||||
*/
|
||||
reason?: string;
|
||||
|
||||
}
|
||||
|
||||
@ -360,7 +364,10 @@ export interface CaigouPlanForm extends BaseEntity {
|
||||
* 出货时间
|
||||
*/
|
||||
chouhuoTime?: string;
|
||||
|
||||
/**
|
||||
* 申请原因
|
||||
*/
|
||||
reason?: string;
|
||||
|
||||
}
|
||||
|
||||
@ -545,6 +552,10 @@ export interface CaigouPlanQuery extends PageQuery {
|
||||
* 出货时间
|
||||
*/
|
||||
chouhuoTime?: string;
|
||||
/**
|
||||
* 申请原因
|
||||
*/
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -62,15 +62,41 @@ export const delChurukudan = (id: string | number | Array<string | number>) => {
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维-物资-出入库单折现图
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getChuRuKuCountLine = (data:any): AxiosPromise<any> => {
|
||||
return request({
|
||||
url: '/ops/churukudan/getChuRuKuDayCount',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维-物资-出入库单柱状图
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getChuRuKuCountBar = (data:any): AxiosPromise<any> => {
|
||||
export const getChuRuKuDayCountBar = (data:any): AxiosPromise<any> => {
|
||||
return request({
|
||||
url: '/ops/churukudan/getChuRuKuCount',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* 运维-物资-出入库单-查询产品名称列表
|
||||
* @param query
|
||||
* @returns {*}
|
||||
*/
|
||||
export const getChanpinLists = (data:any): AxiosPromise<any> => {
|
||||
return request({
|
||||
url: '/ops/caigouPlan/getChanpinList',
|
||||
method: 'get',
|
||||
params: data
|
||||
});
|
||||
};
|
||||
|
||||
@ -47,6 +47,14 @@ export interface ChurukudanVO {
|
||||
*/
|
||||
danjvType: string;
|
||||
|
||||
/**
|
||||
* 审核状态
|
||||
*/
|
||||
auditStatus?: string;
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
chanpinName?: string;
|
||||
}
|
||||
|
||||
export interface ChurukudanForm extends BaseEntity {
|
||||
@ -102,7 +110,10 @@ export interface ChurukudanForm extends BaseEntity {
|
||||
* 审核状态
|
||||
*/
|
||||
auditStatus?: string;
|
||||
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
chanpinName?: string;
|
||||
}
|
||||
|
||||
export interface ChurukudanQuery extends PageQuery {
|
||||
@ -139,7 +150,10 @@ export interface ChurukudanQuery extends PageQuery {
|
||||
* 开始日期
|
||||
*/
|
||||
startDate?: string;
|
||||
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
chanpinName?: string;
|
||||
/**
|
||||
* 结束日期
|
||||
*/
|
||||
|
||||
@ -70,11 +70,18 @@ export const useProcurementDraftStore = defineStore('procurementDraft', () => {
|
||||
return false;
|
||||
};
|
||||
|
||||
// 清除所有草稿
|
||||
const clearAllDrafts = (): void => {
|
||||
draftList.value = [];
|
||||
saveDraftsToStorage(draftList.value);
|
||||
};
|
||||
|
||||
return {
|
||||
draftList,
|
||||
saveDraft,
|
||||
getDraftList,
|
||||
getDraft,
|
||||
deleteDraft
|
||||
deleteDraft,
|
||||
clearAllDrafts
|
||||
};
|
||||
});
|
||||
@ -19,9 +19,31 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onUnmounted } from 'vue';
|
||||
import { ref, onMounted, onUnmounted, watch } from 'vue';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
// 定义props
|
||||
const props = defineProps({
|
||||
lineData: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
// 默认值,防止传入数据为空时图表显示异常
|
||||
days: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
|
||||
rukuCounnts: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
|
||||
chukuCounnts: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90]
|
||||
})
|
||||
},
|
||||
barData: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
// 默认值,防止传入数据为空时图表显示异常
|
||||
shebeiTypes: ['设备1', '设备2', '设备3', '设备4', '设备5'],
|
||||
rukuCount: [5, 40, 20, 75, 60],
|
||||
chukuCount: [30, 40, 30, 30, 30]
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
// 图表容器引用
|
||||
const lineChartRef = ref(null);
|
||||
const barChartRef = ref(null);
|
||||
@ -77,7 +99,7 @@ const initLineChart = () => {
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12']
|
||||
data: props.lineData.days
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value'
|
||||
@ -86,7 +108,7 @@ const initLineChart = () => {
|
||||
{
|
||||
name: '入库数量',
|
||||
type: 'line',
|
||||
data: [5, 40, 20, 75, 60, 80, 40, 55, 30, 65, 5, 80],
|
||||
data: props.lineData.rukuCounnts,
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
@ -105,7 +127,7 @@ const initLineChart = () => {
|
||||
{
|
||||
name: '出库数量',
|
||||
type: 'line',
|
||||
data: [30, 40, 30, 30, 30, 15, 55, 50, 40, 60, 25, 90],
|
||||
data: props.lineData.chukuCounnts,
|
||||
symbol: 'none',
|
||||
smooth: true,
|
||||
lineStyle: {
|
||||
@ -155,7 +177,7 @@ const initBarChart = () => {
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: ['电器部件', '机械部件', '电子元件', '控制模块', '结构部件', '其他'],
|
||||
data: props.barData.shebeiTypes,
|
||||
axisLabel: {
|
||||
interval: 0, // 强制显示所有标签
|
||||
rotate: 30, // 标签旋转30度
|
||||
@ -171,7 +193,7 @@ const initBarChart = () => {
|
||||
{
|
||||
name: '入库数量',
|
||||
type: 'bar',
|
||||
data: [650, 480, 510, 280, 650, 220],
|
||||
data: props.barData.rukuCount,
|
||||
itemStyle: {
|
||||
color: 'rgba(22, 93, 255, 1)' // 入库数量颜色
|
||||
},
|
||||
@ -182,7 +204,7 @@ const initBarChart = () => {
|
||||
{
|
||||
name: '出库数量',
|
||||
type: 'bar',
|
||||
data: [850, 400, 770, 590, 540, 310],
|
||||
data: props.barData.chukuCount,
|
||||
itemStyle: {
|
||||
color: 'rgba(15, 198, 194, 1)' // 出库数量颜色
|
||||
},
|
||||
@ -205,6 +227,12 @@ const handleResize = () => {
|
||||
barChart.resize();
|
||||
}
|
||||
};
|
||||
|
||||
// 监听lineData变化,更新折线图
|
||||
watch(() => props.lineData, () => {
|
||||
initLineChart();
|
||||
initBarChart();
|
||||
}, { deep: true });
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@ -1,84 +1,32 @@
|
||||
<template>
|
||||
<div class="approval-form">
|
||||
<!-- 基础信息 -->
|
||||
<el-card class="card" shadow="hover">
|
||||
<template #header>
|
||||
<h3>基础信息</h3>
|
||||
</template>
|
||||
<el-form :model="detailInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="采购单号">
|
||||
<el-input v-model="detailInfo.id" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="创建时间">
|
||||
<el-input v-model="detailInfo.createTime" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人">
|
||||
<el-input v-model="detailInfo.jingbanrenName" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属部门">
|
||||
<el-select v-model="detailInfo.caigouDanweiName" placeholder="请选择">
|
||||
<el-option label="运维部" value="运维部" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="采购类型">
|
||||
<el-select v-model="detailInfo.caigouType" placeholder="请选择">
|
||||
<el-option label="项目业务" value="项目业务" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="申请原因">
|
||||
<el-input v-model="basicInfo.applyReason" type="textarea" :rows="2" placeholder="请输入申请原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<el-descriptions title="基础信息" direction="vertical" :column="3" border size="large" class="infoClass">
|
||||
<el-descriptions-item label="采购单编号">{{ props.detailInfo.id }}</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">{{ props.detailInfo.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="经办人">{{ props.detailInfo.jingbanrenName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="所属部门">{{ props.detailInfo.caigouDanweiName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="采购类型">{{ getTagLabel(wz_purchase_type, props.detailInfo.caigouType)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="申请原因">{{ props.detailInfo.reason }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>供应商信息</h3>
|
||||
</template>
|
||||
<el-form :model="detailInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供应商单位">
|
||||
<el-select v-model="detailInfo.gonyingshangId" placeholder="请选择">
|
||||
<el-option label="AAAA精密仪器制造有限公司" value="AAAA精密仪器制造有限公司" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="出货时间">
|
||||
<el-select v-model="detailInfo.chouhuoTime" placeholder="请选择">
|
||||
<el-option label="2年零4个月" value="2年零4个月" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-descriptions title="供应商信息" direction="vertical" :column="2" border size="large">
|
||||
<el-descriptions-item label="供应商单位">{{ props.detailInfo.gonyingshangId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="出货时间">{{ props.detailInfo.chuhuoTime }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 产品信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>产品信息</h3>
|
||||
</template>
|
||||
<el-table :data="detailInfo.opsCaigouPlanChanpinVos" border style="width: 100%">
|
||||
<div slot="header" class="infoTitle">产品信息</div>
|
||||
<el-table :data="props.detailInfo.opsCaigouPlanChanpinVos || []" border style="width: 100%">
|
||||
<el-table-column prop="chanpinName" label="产品名称" />
|
||||
<el-table-column prop="chanpinType" label="产品型号" />
|
||||
<el-table-column prop="chanpinMonovalent" label="产品单价" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="chanpinMonovalent" label="产品单价" align="center"
|
||||
:cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="goumaiNumber" label="购买数量" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="yontu" label="用途" />
|
||||
<el-table-column prop="totalPrice" label="合计" />
|
||||
@ -87,163 +35,89 @@
|
||||
|
||||
<!-- 合同条款 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>合同条款</h3>
|
||||
</template>
|
||||
<el-form :model="contractInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款条件">
|
||||
<el-select v-model="detailInfo.fukuantiaojian" placeholder="请选择">
|
||||
<el-option label="银行卡" value="银行卡" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发票开具方式">
|
||||
<el-select v-model="detailInfo.fapiaoKjfs" placeholder="请选择">
|
||||
<el-option label="请选择" value="请选择" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
<el-descriptions title="合同条款" direction="vertical" :column="3" border size="large">
|
||||
<el-descriptions-item label="付款条件">{{ getTagLabel(wz_payment_terms, props.detailInfo.fukuantiaojian)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="发票开具方式">{{ getTagLabel(wz_invoicing_way, props.detailInfo.fapiaoKjfs)
|
||||
}}</el-descriptions-item>
|
||||
<el-descriptions-item label="合同类型">{{
|
||||
getTagLabel(wz_contract_type, props.detailInfo.hetonType) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- 附件 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>附件</h3>
|
||||
</template>
|
||||
<el-upload class="upload-demo" action="#" :file-list="fileList" :auto-upload="false"
|
||||
:on-preview="handlePreview">
|
||||
<el-table :data="fileList" border style="width: 100%">
|
||||
<el-table-column prop="name" label="文件名" width="300" />
|
||||
<el-table-column prop="size" label="大小" width="100" />
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<!-- <el-link type="primary" @click="handlePreview(scope.row)"> -->
|
||||
<el-link type="primary">
|
||||
预览
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-upload>
|
||||
<div slot="header" class="infoTitle">附件</div>
|
||||
|
||||
<el-table :data="props.detailInfo.opsCaigouPlanFilesVos || []" border>
|
||||
<el-table-column prop="fileName" label="文件名" width="300" />
|
||||
<el-table-column label="文件类型" width="200">
|
||||
<template #default="scope">
|
||||
{{ getFileType(scope.row.fileName) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-link type="primary" @click="handlePreview(scope.row)">
|
||||
预览
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, getCurrentInstance, toRefs } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { ref, computed, onMounted, getCurrentInstance, toRefs } from 'vue';
|
||||
import { defineProps } from 'vue';
|
||||
import type { ComponentInternalInstance } from 'vue';
|
||||
const route = useRoute();
|
||||
import type { CaigouPlanVO } from '@/api/wuziguanli/caigouPlan/types';
|
||||
|
||||
// 定义props
|
||||
const props = defineProps<{
|
||||
detailInfo: CaigouPlanVO
|
||||
}>();
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type, wz_caigou_examine } = toRefs<any>(proxy?.useDict('wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
|
||||
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type } = toRefs<any>(proxy?.useDict('wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
|
||||
|
||||
import { caigouPlanDetail } from '@/api/wuziguanli/caigouPlan';
|
||||
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
|
||||
|
||||
// 存储计划详情数据
|
||||
const detailInfo = ref<CaigouPlanVO>({} as CaigouPlanVO);
|
||||
|
||||
// 存储计划编号
|
||||
const id = ref('');
|
||||
|
||||
const getDetailInfo = async () => {
|
||||
const res = await caigouPlanDetail(id.value);
|
||||
if (res.code === 200) {
|
||||
detailInfo.value = res.data;
|
||||
console.log(detailInfo.value);
|
||||
|
||||
}
|
||||
// 根据字典数组和值获取标签文本
|
||||
const getTagLabel = (dictArray: any[], value: any): string => {
|
||||
if (!dictArray || !value) return '';
|
||||
const item = dictArray.find(item => item.value === value);
|
||||
return item?.label || value;
|
||||
}
|
||||
onMounted(() => {
|
||||
// 接收路由参数
|
||||
id.value = route.query.id as string;
|
||||
getDetailInfo();
|
||||
|
||||
|
||||
|
||||
});
|
||||
// 基础信息数据
|
||||
const basicInfo = ref({
|
||||
orderNo: '0035455',
|
||||
createTime: '2023-11-02 16:32',
|
||||
handler: '李四',
|
||||
dept: '运维部',
|
||||
purchaseType: '项目业务',
|
||||
applyReason:
|
||||
'随着业务拓展,光伏电站业务负责增加,现有设备已运行5年,部分出现效率下降情况。为保证电站正常运行,计划采购一批新的逆变器替换老旧设备,并补充备件库存。',
|
||||
});
|
||||
|
||||
// 供应商信息数据
|
||||
const supplierInfo = ref({
|
||||
supplierName: 'AAAA精密仪器制造有限公司',
|
||||
deliveryTime: '2年零4个月',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 产品信息数据
|
||||
const productInfo = ref({
|
||||
tableData: [
|
||||
{
|
||||
productName: 'AAABBBCCC',
|
||||
productModel: '15-42',
|
||||
productPrice: 500,
|
||||
buyQuantity: 10,
|
||||
usage: '组件',
|
||||
total: 5000,
|
||||
},
|
||||
],
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 合同条款数据
|
||||
const contractInfo = ref({
|
||||
paymentCondition: '银行卡',
|
||||
invoiceWay: '请选择',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 附件数据
|
||||
const fileList = ref([
|
||||
{
|
||||
name: 'MWwwwww.jpg',
|
||||
size: '30kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '231234124w.zip',
|
||||
size: '50kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12451asdas.doc',
|
||||
size: '80kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '21seasda.xls',
|
||||
size: '29kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12kjaklskw.png',
|
||||
size: '16kb',
|
||||
url: '',
|
||||
},
|
||||
]);
|
||||
// 获取文件类型(后缀名)
|
||||
const getFileType = (fileName: string): string => {
|
||||
if (!fileName) return '';
|
||||
const lastDotIndex = fileName.lastIndexOf('.');
|
||||
if (lastDotIndex === -1) return '';
|
||||
return fileName.substring(lastDotIndex + 1).toLowerCase();
|
||||
};
|
||||
|
||||
// 预览文件
|
||||
const handlePreview = (file) => {
|
||||
console.log('预览文件:', file);
|
||||
// 实际场景可在这里处理文件预览逻辑,如打开新窗口等
|
||||
window.open(file.fileUrl, '_blank');
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.infoTitle {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.approval-form {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
@ -1,261 +0,0 @@
|
||||
<template>
|
||||
<div class="approval-form">
|
||||
<!-- 基础信息 -->
|
||||
<el-card class="card" shadow="hover">
|
||||
<template #header>
|
||||
<h3>基础信息</h3>
|
||||
</template>
|
||||
<el-form :model="basicInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="订单编号">
|
||||
<el-input v-model="basicInfo.orderNo" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="创建时间">
|
||||
<el-input v-model="basicInfo.createTime" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="经办人">
|
||||
<el-input v-model="basicInfo.handler" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="所属部门">
|
||||
<el-select v-model="basicInfo.dept" placeholder="请选择">
|
||||
<el-option label="运维部" value="运维部" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="采购类型">
|
||||
<el-select v-model="basicInfo.purchaseType" placeholder="请选择">
|
||||
<el-option label="项目业务" value="项目业务" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="申请原因">
|
||||
<el-input v-model="basicInfo.applyReason" type="textarea" :rows="2" placeholder="请输入申请原因" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>供应商信息</h3>
|
||||
</template>
|
||||
<el-form :model="supplierInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="供应商单位">
|
||||
<el-select v-model="supplierInfo.supplierName" placeholder="请选择">
|
||||
<el-option label="AAAA精密仪器制造有限公司" value="AAAA精密仪器制造有限公司" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="出货时间">
|
||||
<el-select v-model="supplierInfo.deliveryTime" placeholder="请选择">
|
||||
<el-option label="2年零4个月" value="2年零4个月" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 产品信息 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>产品信息</h3>
|
||||
</template>
|
||||
<el-table :data="productInfo.tableData" border style="width: 100%">
|
||||
<el-table-column prop="productName" label="产品名称" />
|
||||
<el-table-column prop="productModel" label="产品型号" />
|
||||
<el-table-column prop="productPrice" label="产品单价" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="buyQuantity" label="购买数量" align="center" :cell-style="{ background: 'pink' }" />
|
||||
<el-table-column prop="usage" label="用途" />
|
||||
<el-table-column prop="total" label="合计" />
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<!-- 合同条款 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>合同条款</h3>
|
||||
</template>
|
||||
<el-form :model="contractInfo" label-width="120px">
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="付款条件">
|
||||
<el-select v-model="contractInfo.paymentCondition" placeholder="请选择">
|
||||
<el-option label="银行卡" value="银行卡" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="发票开具方式">
|
||||
<el-select v-model="contractInfo.invoiceWay" placeholder="请选择">
|
||||
<el-option label="请选择" value="请选择" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-card>
|
||||
|
||||
<!-- 附件 -->
|
||||
<el-card class="card" shadow="hover" style="margin-top: 20px">
|
||||
<template #header>
|
||||
<h3>附件</h3>
|
||||
</template>
|
||||
<el-upload class="upload-demo" action="#" :file-list="fileList" :auto-upload="false"
|
||||
:on-preview="handlePreview">
|
||||
<el-table :data="fileList" border style="width: 100%">
|
||||
<el-table-column prop="name" label="文件名" width="300" />
|
||||
<el-table-column prop="size" label="大小" width="100" />
|
||||
<el-table-column label="操作" width="100">
|
||||
<template #default="scope">
|
||||
<!-- <el-link type="primary" @click="handlePreview(scope.row)"> -->
|
||||
<el-link type="primary">
|
||||
预览
|
||||
</el-link>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-upload>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, getCurrentInstance, toRefs } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import type { ComponentInternalInstance } from 'vue';
|
||||
const route = useRoute();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type, wz_caigou_examine } = toRefs<any>(proxy?.useDict('wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
|
||||
|
||||
import { caigouPlanDetail } from '@/api/wuziguanli/caigouPlan';
|
||||
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
|
||||
|
||||
|
||||
// 存储计划编号
|
||||
const id = ref('');
|
||||
|
||||
const getDetailInfo = async () => {
|
||||
const res = await caigouPlanDetail(id.value);
|
||||
if (res.code === 200) {
|
||||
console.log(res);
|
||||
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 接收路由参数
|
||||
id.value = route.query.id as string;
|
||||
getDetailInfo();
|
||||
|
||||
|
||||
|
||||
});
|
||||
// 基础信息数据
|
||||
const basicInfo = ref({
|
||||
orderNo: '0035455',
|
||||
createTime: '2023-11-02 16:32',
|
||||
handler: '李四',
|
||||
dept: '运维部',
|
||||
purchaseType: '项目业务',
|
||||
applyReason:
|
||||
'随着业务拓展,光伏电站业务负责增加,现有设备已运行5年,部分出现效率下降情况。为保证电站正常运行,计划采购一批新的逆变器替换老旧设备,并补充备件库存。',
|
||||
});
|
||||
|
||||
// 供应商信息数据
|
||||
const supplierInfo = ref({
|
||||
supplierName: 'AAAA精密仪器制造有限公司',
|
||||
deliveryTime: '2年零4个月',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 产品信息数据
|
||||
const productInfo = ref({
|
||||
tableData: [
|
||||
{
|
||||
productName: 'AAABBBCCC',
|
||||
productModel: '15-42',
|
||||
productPrice: 500,
|
||||
buyQuantity: 10,
|
||||
usage: '组件',
|
||||
total: 5000,
|
||||
},
|
||||
],
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 合同条款数据
|
||||
const contractInfo = ref({
|
||||
paymentCondition: '银行卡',
|
||||
invoiceWay: '请选择',
|
||||
remark: '',
|
||||
});
|
||||
|
||||
// 附件数据
|
||||
const fileList = ref([
|
||||
{
|
||||
name: 'MWwwwww.jpg',
|
||||
size: '30kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '231234124w.zip',
|
||||
size: '50kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12451asdas.doc',
|
||||
size: '80kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '21seasda.xls',
|
||||
size: '29kb',
|
||||
url: '',
|
||||
},
|
||||
{
|
||||
name: '12kjaklskw.png',
|
||||
size: '16kb',
|
||||
url: '',
|
||||
},
|
||||
]);
|
||||
|
||||
// 预览文件
|
||||
const handlePreview = (file) => {
|
||||
console.log('预览文件:', file);
|
||||
// 实际场景可在这里处理文件预览逻辑,如打开新窗口等
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.approval-form {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.card {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.error-tip {
|
||||
color: red;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
::v-deep(.el-input__inner) {
|
||||
color: red;
|
||||
}
|
||||
</style>
|
||||
@ -23,20 +23,20 @@
|
||||
<el-input v-model="queryParams.danjvNumber" placeholder="请输入单据编号"
|
||||
clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型" prop="shebeiType">
|
||||
<!-- <el-form-item label="设备类型" prop="shebeiType">
|
||||
<el-select v-model="queryParams.shebeiType" placeholder="请选择设备类型"
|
||||
clearable>
|
||||
<el-option v-for="dict in wz_device_type" :key="dict.value"
|
||||
:label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="审核状态" prop="auditStatus">
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="审核状态" prop="auditStatus">
|
||||
<el-select v-model="queryParams.auditStatus" placeholder="请选择审核状态"
|
||||
clearable>
|
||||
<el-option v-for="dict in shenheStatus" :key="dict.value"
|
||||
:label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="开始日期" prop="startDate">
|
||||
<el-date-picker v-model="queryParams.startDate" type="date"
|
||||
placeholder="请选择开始日期" format="YYYY-MM-DD" value-format="YYYY-MM-DD"
|
||||
@ -63,21 +63,17 @@
|
||||
<el-table v-loading="loading" border :data="churukudanList"
|
||||
style="width: 100%;margin-top: 15px;">
|
||||
<el-table-column label="单据编号" align="center" prop="danjvNumber" />
|
||||
<el-table-column label="设备类型" align="center" prop="shebeiType">
|
||||
<template #default="scope">
|
||||
<span>{{ getTagLabel(wz_device_type, scope.row.shebeiType) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="经手人" align="center" prop="jingshourenName" />
|
||||
<el-table-column label="产品名称" align="center" prop="chanpinName"></el-table-column>
|
||||
<el-table-column label="经手人" align="center" prop="jingshourenName" width="80px" />
|
||||
<el-table-column label="操作时间" align="center" prop="updateTime" />
|
||||
<el-table-column label="总数量" align="center" prop="zonNumber" width="80px" />
|
||||
<el-table-column label="审核状态" align="center" prop="shenheStatus">
|
||||
<!-- <el-table-column label="审核状态" align="center" prop="shenheStatus">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getTagType(shenheStatus, scope.row.shenheStatus)" as="span">
|
||||
{{ getTagLabel(shenheStatus, scope.row.shenheStatus) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="单据类型" align="center" prop="danjvType">
|
||||
<template #default="scope">
|
||||
<el-tag :type="getTagType(danjvType, scope.row.danjvType)">
|
||||
@ -87,8 +83,8 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
||||
<template #default="scope">
|
||||
<el-button link type="primary" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['personnel:churukudan:edit']">修改</el-button>
|
||||
<!-- <el-button link type="primary" @click="handleUpdate(scope.row)"
|
||||
v-hasPermi="['personnel:churukudan:edit']">修改</el-button> -->
|
||||
<el-button link type="primary" @click="handleDetail(scope.row)"
|
||||
v-hasPermi="['personnel:churukudan:query']">详情</el-button>
|
||||
<el-button link type="primary" @click="handleDelete(scope.row)"
|
||||
@ -118,7 +114,7 @@
|
||||
<div class="item-box">
|
||||
<div class="title">数据分析</div>
|
||||
<div class="content">
|
||||
<DataAnalysis />
|
||||
<DataAnalysis :lineData="lineData" :barData="barData" />
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
@ -136,11 +132,17 @@
|
||||
<el-form-item label="单据编号" prop="danjvNumber">
|
||||
<el-input v-model="form.danjvNumber" placeholder="请输入单据编号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="设备类型" prop="shebeiType">
|
||||
<!-- <el-form-item label="设备类型" prop="shebeiType">
|
||||
<el-select v-model="form.shebeiType" placeholder="请选择设备类型">
|
||||
<el-option v-for="dict in wz_device_type" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="产品名称" prop="chanpinName">
|
||||
<el-select v-model="form.chanpinName" placeholder="请选择产品名称">
|
||||
<el-option v-for="dict in chanpinName" :key="dict.value" :label="dict.label"
|
||||
:value="dict.value"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="经手人id" prop="jingshourenId">
|
||||
<el-input v-model="form.jingshourenId" placeholder="请输入经手人id" />
|
||||
@ -325,7 +327,7 @@ import SystemInfo from './components/SystemInfo.vue';
|
||||
import DataAnalysis from './components/DataAnalysis.vue';
|
||||
import { ref, computed } from 'vue';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { listChurukudan, getChurukudan, delChurukudan, addChurukudan, updateChurukudan, getChuRuKuCountBar } from '@/api/wuziguanli/churuku/index';
|
||||
import { listChurukudan, getChurukudan, delChurukudan, addChurukudan, updateChurukudan, getChuRuKuCountLine, getChuRuKuDayCountBar, getChanpinLists } from '@/api/wuziguanli/churuku/index';
|
||||
import { ChurukudanVO, ChurukudanQuery, ChurukudanForm } from '@/api/wuziguanli/churuku/types';
|
||||
const { wz_device_type } = toRefs<any>(proxy?.useDict('wz_device_type'));
|
||||
|
||||
@ -427,6 +429,7 @@ const initFormData: ChurukudanForm = {
|
||||
danjvType: undefined,
|
||||
updateTime: undefined,
|
||||
auditStatus: undefined,
|
||||
chanpinName: undefined,
|
||||
}
|
||||
const data = reactive<PageData<ChurukudanForm, ChurukudanQuery>>({
|
||||
form: { ...initFormData },
|
||||
@ -440,6 +443,7 @@ const data = reactive<PageData<ChurukudanForm, ChurukudanQuery>>({
|
||||
startDate: undefined,
|
||||
endDate: undefined,
|
||||
auditStatus: undefined,
|
||||
chanpinName: undefined,
|
||||
danjvType: '1', // 默认显示出库单
|
||||
params: {
|
||||
}
|
||||
@ -464,6 +468,20 @@ const data = reactive<PageData<ChurukudanForm, ChurukudanQuery>>({
|
||||
});
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
// 查询产品名称列表
|
||||
const chanpinList = ref<any[]>([]);
|
||||
// 查询产品名称列表
|
||||
const getChanpinList = async () => {
|
||||
try {
|
||||
const res = await getChanpinLists({ projectId: userStore.selectedProject.id });
|
||||
chanpinList.value = res.rows || [];
|
||||
console.log('chanpinList.value', chanpinList.value);
|
||||
} catch (error) {
|
||||
console.error('获取产品名称列表失败:', error);
|
||||
proxy?.$modal.msgError("获取产品名称列表失败,请稍后重试");
|
||||
chanpinList.value = [];
|
||||
}
|
||||
}
|
||||
|
||||
/** 查询运维-物资-出入库单管理列表 */
|
||||
const getList = async () => {
|
||||
@ -526,23 +544,23 @@ const handleAdd = () => {
|
||||
}
|
||||
|
||||
/** 修改按钮操作 */
|
||||
const handleUpdate = async (row?: ChurukudanVO) => {
|
||||
reset();
|
||||
const _id = row?.id || ids.value[0];
|
||||
if (!_id) {
|
||||
proxy?.$modal.msgWarning("请选择要修改的数据");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await getChurukudan(_id);
|
||||
Object.assign(form.value, res.data);
|
||||
dialog.visible = true;
|
||||
dialog.title = "修改运维-物资-出入库单管理";
|
||||
} catch (error) {
|
||||
console.error('获取出入库单详情失败:', error);
|
||||
proxy?.$modal.msgError("获取数据失败,请稍后重试");
|
||||
}
|
||||
}
|
||||
// const handleUpdate = async (row?: ChurukudanVO) => {
|
||||
// reset();
|
||||
// const _id = row?.id || ids.value[0];
|
||||
// if (!_id) {
|
||||
// proxy?.$modal.msgWarning("请选择要修改的数据");
|
||||
// return;
|
||||
// }
|
||||
// try {
|
||||
// const res = await getChurukudan(_id);
|
||||
// Object.assign(form.value, res.data);
|
||||
// dialog.visible = true;
|
||||
// dialog.title = "修改运维-物资-出入库单管理";
|
||||
// } catch (error) {
|
||||
// console.error('获取出入库单详情失败:', error);
|
||||
// proxy?.$modal.msgError("获取数据失败,请稍后重试");
|
||||
// }
|
||||
// }
|
||||
|
||||
/** 提交按钮 */
|
||||
const submitForm = () => {
|
||||
@ -607,7 +625,29 @@ const handleDelete = async (row?: ChurukudanVO) => {
|
||||
}
|
||||
}
|
||||
|
||||
// 折线图数据获取
|
||||
const lineData = ref<any>();
|
||||
const fetchChuRuKuCountLineData = async () => {
|
||||
if (!queryParams.value.projectId) {
|
||||
return;
|
||||
}
|
||||
let data = {
|
||||
projectId: queryParams.value.projectId,
|
||||
startDate: currentMonthDates[0].fullDate,
|
||||
endDate: currentMonthDates[currentMonthDates.length - 1].fullDate,
|
||||
}
|
||||
try {
|
||||
const res = await getChuRuKuCountLine(data);
|
||||
if (res.code === 200) {
|
||||
lineData.value = res.data;
|
||||
}
|
||||
// 这里可以添加数据处理和图表更新的逻辑
|
||||
} catch (error) {
|
||||
proxy?.$modal.msgError("获取统计数据失败");
|
||||
}
|
||||
}
|
||||
// 柱状图数据获取
|
||||
const barData = ref<any>();
|
||||
const fetchChuRuKuCountBarData = async () => {
|
||||
if (!queryParams.value.projectId) {
|
||||
return;
|
||||
@ -618,16 +658,15 @@ const fetchChuRuKuCountBarData = async () => {
|
||||
endDate: currentMonthDates[currentMonthDates.length - 1].fullDate,
|
||||
}
|
||||
try {
|
||||
const res = await getChuRuKuCountBar(data);
|
||||
console.log(res);
|
||||
const res = await getChuRuKuDayCountBar(data);
|
||||
if (res.code === 200) {
|
||||
barData.value = res.data;
|
||||
}
|
||||
// 这里可以添加数据处理和图表更新的逻辑
|
||||
} catch (error) {
|
||||
console.error('获取柱状图数据失败:', error);
|
||||
// 可以选择是否显示错误提示,根据UI需求决定
|
||||
// proxy?.$modal.msgError("获取统计数据失败");
|
||||
proxy?.$modal.msgError("获取统计数据失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 监听用户选择的项目变化
|
||||
watch(() => userStore.selectedProject, (newProject) => {
|
||||
if (newProject && newProject.id) {
|
||||
@ -638,12 +677,15 @@ watch(() => userStore.selectedProject, (newProject) => {
|
||||
}
|
||||
// 调用getList刷新数据
|
||||
getList();
|
||||
fetchChuRuKuCountBarData();
|
||||
fetchChuRuKuCountLineData();
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
onMounted(() => {
|
||||
getList();
|
||||
fetchChuRuKuCountLineData();
|
||||
fetchChuRuKuCountBarData();
|
||||
// 查询产品名称列表
|
||||
getChanpinList();
|
||||
});
|
||||
|
||||
// 组件卸载时清空projectId
|
||||
|
||||
@ -9,15 +9,15 @@
|
||||
<ArrowLeft />
|
||||
</el-icon>
|
||||
</span>
|
||||
<h2>Q2风电轴承采购计划</h2>
|
||||
<h2>{{ Info.jihuaName }}</h2>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row gutter="10">
|
||||
<el-row :gutter="10">
|
||||
<el-col :span="18">
|
||||
<el-card>
|
||||
<detailInfo />
|
||||
<detailInfo :detail-info="Info" />
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :span="6" style="flex-grow: 1;">
|
||||
@ -46,12 +46,66 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
<script setup>
|
||||
<script setup lang="ts">
|
||||
|
||||
import detailInfo from './components/detailInfo.vue';
|
||||
import DetailsProcess from './components/DetailsProcess.vue';
|
||||
import { ref, onMounted, getCurrentInstance, toRefs, watch } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import type { ComponentInternalInstance } from 'vue';
|
||||
const route = useRoute();
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
import { caigouPlanDetail } from '@/api/wuziguanli/caigouPlan';
|
||||
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
|
||||
|
||||
|
||||
// 存储计划详情数据
|
||||
const Info = ref<CaigouPlanVO>({} as CaigouPlanVO);
|
||||
|
||||
// 存储计划编号
|
||||
const id = ref('');
|
||||
|
||||
// 获取详细信息
|
||||
const getDetailInfo = async () => {
|
||||
const res = await caigouPlanDetail(id.value);
|
||||
if (res.code === 200) {
|
||||
Info.value = res.data;
|
||||
console.log(Info.value);
|
||||
|
||||
}
|
||||
}
|
||||
onMounted(() => {
|
||||
// 接收路由参数
|
||||
id.value = route.query.id as string || '';
|
||||
console.log('组件挂载时路由参数id:', id.value);
|
||||
// 确保id不为空时才调用接口
|
||||
if (id.value) {
|
||||
getDetailInfo();
|
||||
} else {
|
||||
proxy.$modal.msgError('未获取到详细信息')
|
||||
setTimeout(() => {
|
||||
router.back();
|
||||
}, 800);
|
||||
}
|
||||
});
|
||||
|
||||
// 监听路由参数变化
|
||||
watch(
|
||||
() => route.query.id,
|
||||
(newId) => {
|
||||
id.value = newId as string || '';
|
||||
if (id.value) {
|
||||
getDetailInfo();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
const router = useRouter();
|
||||
const handleBack = () => {
|
||||
router.back();
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
@ -12,7 +12,7 @@
|
||||
待审批计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(255, 178, 30, 1);">
|
||||
12
|
||||
{{ pendingCount }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
@ -20,7 +20,7 @@
|
||||
已批准计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
||||
28
|
||||
{{ approvedCount }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
@ -28,7 +28,7 @@
|
||||
采购中计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(113, 214, 213, 1);">
|
||||
15
|
||||
{{ purchasingCount }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
@ -36,7 +36,7 @@
|
||||
已完成计划
|
||||
</div>
|
||||
<div class="count" style="color: rgba(0, 184, 122, 1);">
|
||||
86
|
||||
{{ completedCount }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -53,7 +53,7 @@
|
||||
本年度已采购金额
|
||||
</div>
|
||||
<div class="count" style="color: rgba(255, 153, 0, 1);">
|
||||
520,000.00
|
||||
{{ yearlyAmount.shijiJine }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
@ -61,7 +61,7 @@
|
||||
本年度采购预算金额
|
||||
</div>
|
||||
<div class="count" style="color: rgba(67, 101, 220, 1);">
|
||||
3,000,000.00
|
||||
{{ yearlyAmount.yujiJine }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -73,34 +73,38 @@
|
||||
<el-card style="border-radius: 10px;">
|
||||
<div class="content">
|
||||
<div class="tabs">
|
||||
<el-button type="success">导出</el-button>
|
||||
<el-button type="primary" @click="isNewProcurementDialogVisible = true">新建采购申请单</el-button>
|
||||
<!-- <el-button type="success">导出</el-button> -->
|
||||
<el-button type="primary" @click="handleAdd">新建采购申请单</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 标签页导航 -->
|
||||
<div class="tabs">
|
||||
<!-- <el-badge :value="pendingCount" type="warning">
|
||||
<el-button :type="activeTab === 'pending' ? 'primary' : ''"
|
||||
@click="changeTab('pending')">待审批</el-button>
|
||||
<el-badge :value="total" type="success">
|
||||
<el-button :type="activeTab === 'all' ? 'primary' : ''"
|
||||
@click="changeTab('all')">全部</el-button>
|
||||
</el-badge>
|
||||
<el-badge :value="purchasingCount" type="info">
|
||||
<el-button :type="activeTab === 'purchasing' ? 'primary' : ''"
|
||||
@click="changeTab('purchasing')">采购中</el-button>
|
||||
<el-badge :value="pendingCount" type="warning">
|
||||
<el-button :type="activeTab === '3' ? 'primary' : ''"
|
||||
@click="changeTab('3')">待审批</el-button>
|
||||
</el-badge>
|
||||
<el-badge :value="purchasingCount" type="primary">
|
||||
<el-button :type="activeTab === '5' ? 'primary' : ''"
|
||||
@click="changeTab('5')">采购中</el-button>
|
||||
</el-badge>
|
||||
<el-badge :value="rejectedCount" type="danger">
|
||||
<el-button :type="activeTab === 'rejected' ? 'primary' : ''"
|
||||
@click="changeTab('rejected')">
|
||||
<el-button :type="activeTab === '7' ? 'primary' : ''"
|
||||
@click="changeTab('7')">
|
||||
未通过
|
||||
</el-button>
|
||||
</el-badge>
|
||||
<el-badge :value="approvedCount" type="primary">
|
||||
<el-button :type="activeTab === 'approved' ? 'primary' : ''"
|
||||
@click="changeTab('approved')">已通过</el-button>
|
||||
<el-badge :value="approvedCount" type="success">
|
||||
<el-button :type="activeTab === '9' ? 'primary' : ''"
|
||||
@click="changeTab('9')">已通过</el-button>
|
||||
</el-badge>
|
||||
<el-badge :value="completedCount" type="success">
|
||||
<el-button :type="activeTab === 'completed' ? 'primary' : ''"
|
||||
@click="changeTab('completed')">已完成</el-button>
|
||||
</el-badge> -->
|
||||
<el-button :type="activeTab === '11' ? 'primary' : ''"
|
||||
@click="changeTab('11')">已完成</el-button>
|
||||
</el-badge>
|
||||
</div>
|
||||
<!-- 表格 -->
|
||||
<el-table :data="caigouPlanList" border style="width: 100%;margin-top: 15px;">
|
||||
@ -115,9 +119,10 @@
|
||||
<dict-tag :options="wz_caigou_examine" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" fixed="right" width="80" align="center">
|
||||
<el-table-column label="操作" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handleView(scope.row)">查看</el-button>
|
||||
<el-button type="text" @click="handleUpdate(scope.row)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -131,26 +136,23 @@
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-dialog v-model="isNewProcurementDialogVisible" title="新建采购申请单" width="60%" :close-on-click-modal="false">
|
||||
<el-dialog v-model="isDialogVisible" :title="dialogTitle" width="60%" :close-on-click-modal="false">
|
||||
<div class="new-procurement-form">
|
||||
<!-- 基础信息 -->
|
||||
<div class="form-section">
|
||||
<h3>基础信息</h3>
|
||||
<!-- 输入框行 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="12">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="计划名称">
|
||||
<el-input v-model="form.jihuaName" placeholder="请填写计划名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="合同名称">
|
||||
<el-input v-model="form.hetonName" placeholder="请填写合同名称" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 下拉框行 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="合同类型">
|
||||
<el-select v-model="form.hetonType" placeholder="请选择">
|
||||
@ -159,6 +161,9 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- 下拉框行 -->
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="采购类型">
|
||||
<el-select v-model="form.caigouType" placeholder="请选择">
|
||||
@ -173,6 +178,13 @@
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="24">
|
||||
<el-form-item label="申请原因">
|
||||
<el-input v-model="form.reason" placeholder="请输入申请原因" type="textarea" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
<!-- 供应商信息 -->
|
||||
@ -184,9 +196,9 @@
|
||||
<el-select v-model="form.danwei" placeholder="请选择">
|
||||
<!-- <el-option v-for="option in supplierList" :key="option.value" :label="option.label"
|
||||
:value="option.value" /> -->
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
<el-option label="供应商1" value="供应商1" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@ -216,13 +228,13 @@
|
||||
<el-table-column prop="chanpinMonovalent" label="产品单价">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.chanpinMonovalent" placeholder="请填写" type="number"
|
||||
@change="calculateTotalPrice(scope.row)" />
|
||||
@change="calculateTotalPrice(scope.row)" min="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="goumaiNumber" label="购买数量">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.goumaiNumber" placeholder="请填写" type="number"
|
||||
@change="calculateTotalPrice(scope.row)" />
|
||||
@change="calculateTotalPrice(scope.row)" min="0" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="danwei" label="单位">
|
||||
@ -230,6 +242,11 @@
|
||||
<el-input v-model="scope.row.danwei" placeholder="请填写" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="yontu" label="用途(简要描述)">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.yontu" placeholder="请填写" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="totalPrice" label="合计" :formatter="calculateTotalPrice">
|
||||
<template #default="scope">
|
||||
<span>{{ calculateTotalPrice(scope.row) }}</span>
|
||||
@ -271,17 +288,38 @@
|
||||
<!-- 附件上传 -->
|
||||
<div class="form-section">
|
||||
<h3>附件上传</h3>
|
||||
<!-- 附件 -->
|
||||
<el-table :data="form.opsCaigouPlanFilesBos || []" border v-if="currentOperation === 'update'">
|
||||
<el-table-column prop="fileName" label="文件名" align="center" />
|
||||
<el-table-column label="文件类型" align="center">
|
||||
<template #default="scope">
|
||||
{{ getFileType(scope.row.fileName) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="text" @click="handlePreview(scope.row)">
|
||||
预览
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<file-upload ref="fileUploadRef" :isDrag="true" :file-list="form.opsCaigouPlanFilesBos"
|
||||
:is-show-tip="false"
|
||||
@update:file-list="handleUpdateFileList"
|
||||
:is-show-tip="false" @update:file-list="handleUpdateFileList"
|
||||
:file-type="['doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'pdf', 'png', 'jpg', 'jpeg']" />
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button @click="cancelNewProcurement">取消</el-button>
|
||||
<el-button @click="saveDraft" :loading="buttonLoading">保存草稿</el-button>
|
||||
<el-button type="primary" @click="submitProcurement" :loading="buttonLoading">提交申请</el-button>
|
||||
<el-button @click="cancelOperation">取消</el-button>
|
||||
<el-button v-if="currentOperation !== 'update'" @click="saveDraft" :loading="buttonLoading">保存草稿</el-button>
|
||||
<el-button type="primary" @click="getSubmitFunction()" :loading="buttonLoading">
|
||||
{{ currentOperation === 'add' ? '提交申请' : '更新' }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
@ -361,13 +399,13 @@
|
||||
}
|
||||
</style>
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue';
|
||||
import { ref, reactive, computed, getCurrentInstance, onUnmounted } from 'vue';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useProcurementDraftStore } from '@/store/modules/procurementDraft';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
const { wz_invoicing_way, wz_payment_terms, wz_purchase_type, wz_contract_type, wz_caigou_examine } = toRefs<any>(proxy?.useDict('wz_invoicing_way', 'wz_payment_terms', 'wz_purchase_type', 'wz_contract_type', 'wz_caigou_examine'));
|
||||
|
||||
import { listCaigouPlan, getSupplierList, addCaigouPlan } from '@/api/wuziguanli/caigouPlan';
|
||||
import { listCaigouPlan, getSupplierList, addCaigouPlan, caigouPlanDetail, updateCaigouPlan,getCount } from '@/api/wuziguanli/caigouPlan';
|
||||
import { CaigouPlanVO, CaigouPlanQuery, CaigouPlanForm } from '@/api/wuziguanli/caigouPlan/types';
|
||||
|
||||
import { useRouter } from 'vue-router';
|
||||
@ -384,6 +422,25 @@ const buttonLoading = ref(false);
|
||||
const loading = ref(true);
|
||||
const total = ref(0);
|
||||
|
||||
// 标签页状态变量
|
||||
const activeTab = ref('all');
|
||||
|
||||
// 各状态数量变量
|
||||
const pendingCount = ref(0);
|
||||
const purchasingCount = ref(0);
|
||||
const rejectedCount = ref(0);
|
||||
const approvedCount = ref(0);
|
||||
const completedCount = ref(0);
|
||||
|
||||
// 标签页切换函数
|
||||
const changeTab = (tab: string) => {
|
||||
activeTab.value = tab;
|
||||
// 重置页码
|
||||
queryParams.value.pageNum = 1;
|
||||
// 重新获取列表数据
|
||||
getList();
|
||||
};
|
||||
|
||||
const initFormData: CaigouPlanForm = {
|
||||
id: undefined,
|
||||
projectId: undefined,
|
||||
@ -405,7 +462,7 @@ const initFormData: CaigouPlanForm = {
|
||||
shenheStatus: undefined,
|
||||
yujiJine: undefined,
|
||||
shijiJine: undefined,
|
||||
opsCaigouPlanFilesBos: [],
|
||||
opsCaigouPlanFilesBos: undefined,
|
||||
opsCaigouPlanChanpinBos: [
|
||||
{
|
||||
chanpinName: '',
|
||||
@ -413,9 +470,11 @@ const initFormData: CaigouPlanForm = {
|
||||
chanpinMonovalent: 0,
|
||||
goumaiNumber: 0,
|
||||
danwei: '',
|
||||
yontu: '',
|
||||
totalPrice: 0
|
||||
}
|
||||
],
|
||||
reason: undefined,
|
||||
}
|
||||
const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
|
||||
form: { ...initFormData },
|
||||
@ -441,6 +500,7 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
|
||||
shenheStatus: undefined,
|
||||
yujiJine: undefined,
|
||||
shijiJine: undefined,
|
||||
reason: undefined,
|
||||
opsCaigouPlanChanpinBos: [
|
||||
{
|
||||
chanpinName: '',
|
||||
@ -448,6 +508,7 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
|
||||
chanpinMonovalent: 0,
|
||||
goumaiNumber: 0,
|
||||
danwei: '',
|
||||
yontu: '',
|
||||
totalPrice: 0
|
||||
}
|
||||
],
|
||||
@ -460,30 +521,90 @@ const data = reactive<PageData<CaigouPlanForm, CaigouPlanQuery>>({
|
||||
|
||||
const { queryParams, form, rules } = toRefs(data);
|
||||
|
||||
|
||||
// 查询运维-物资-采购计划单年度金额
|
||||
const yearlyAmount=ref({
|
||||
yujiJine: 0,
|
||||
shijiJine: 0,
|
||||
})
|
||||
const getYearlyAmount = async () => {
|
||||
try {
|
||||
const res = await getCount(queryParams.value.projectId);
|
||||
if (res.code === 200) {
|
||||
yearlyAmount.value.shijiJine = res.data.shijiJine;
|
||||
yearlyAmount.value.yujiJine = res.data.yujiJine;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取年度金额失败:', error);
|
||||
ElMessage({ message: '获取年度金额失败,请重试', type: 'error' });
|
||||
}
|
||||
}
|
||||
/** 查询运维-物资-采购计划单列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res = await listCaigouPlan(queryParams.value);
|
||||
caigouPlanList.value = res.rows;
|
||||
total.value = res.total;
|
||||
loading.value = false;
|
||||
|
||||
// 创建查询参数的副本,避免直接修改原参数
|
||||
const queryParamsCopy = { ...queryParams.value };
|
||||
|
||||
// 根据当前选中的标签页设置状态过滤条件
|
||||
if (activeTab.value !== 'all') {
|
||||
queryParamsCopy.status = activeTab.value;
|
||||
} else {
|
||||
// 如果是'全部'标签页,不设置状态过滤条件
|
||||
queryParamsCopy.status = undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
// 先查询所有数据来统计各状态数量
|
||||
const allDataRes = await listCaigouPlan({ ...queryParamsCopy, status: undefined });
|
||||
|
||||
// 统计各状态数量
|
||||
pendingCount.value = allDataRes.rows.filter(item => item.status === '3').length;
|
||||
purchasingCount.value = allDataRes.rows.filter(item => item.status === '5').length;
|
||||
rejectedCount.value = allDataRes.rows.filter(item => item.status === '7').length;
|
||||
approvedCount.value = allDataRes.rows.filter(item => item.status === '9').length;
|
||||
completedCount.value = allDataRes.rows.filter(item => item.status === '11').length;
|
||||
total.value = allDataRes.total;
|
||||
|
||||
// 然后查询当前标签页的数据
|
||||
const filteredRes = await listCaigouPlan(queryParamsCopy);
|
||||
caigouPlanList.value = filteredRes.rows;
|
||||
|
||||
} catch (error) {
|
||||
console.error('获取采购计划列表失败:', error);
|
||||
ElMessage({ message: '获取数据失败,请重试', type: 'error' });
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
// 新增采购计划单
|
||||
const addCaigouPlans = async () => {
|
||||
// 新增采购计划单提交函数
|
||||
const addCaigouPlanSubmit = async () => {
|
||||
buttonLoading.value = true; // 显示按钮加载状态
|
||||
try {
|
||||
// 提交表单数据到后端
|
||||
const res = await addCaigouPlan(form.value);
|
||||
|
||||
if (res.code === 200) {
|
||||
ElMessage({ message: '采购申请单已成功提交,等待审批!', type: 'success' });
|
||||
|
||||
// 提交成功后,删除相关的草稿
|
||||
const procurementDraftStore = useProcurementDraftStore();
|
||||
const draftList = procurementDraftStore.getDraftList();
|
||||
|
||||
// 查找并删除与当前计划名称匹配的草稿
|
||||
if (form.value.jihuaName && draftList && draftList.length > 0) {
|
||||
const matchingDraft = draftList.find(draft =>
|
||||
draft.name === form.value.jihuaName
|
||||
);
|
||||
|
||||
if (matchingDraft) {
|
||||
procurementDraftStore.deleteDraft(matchingDraft.id);
|
||||
}
|
||||
}
|
||||
// 刷新列表数据
|
||||
getList();
|
||||
|
||||
// 关闭对话框并重置表单
|
||||
resetNewProcurementForm();
|
||||
isNewProcurementDialogVisible.value = false;
|
||||
isDialogVisible.value = false;
|
||||
} else {
|
||||
// 显示详细的错误信息
|
||||
ElMessage({
|
||||
@ -492,7 +613,38 @@ const addCaigouPlans = async () => {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
ElMessage({ message: '失败', type: 'error' });
|
||||
console.error('新增采购计划单失败:', error);
|
||||
ElMessage({ message: '操作失败', type: 'error' });
|
||||
} finally {
|
||||
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
|
||||
}
|
||||
}
|
||||
|
||||
// 更新采购计划单提交函数
|
||||
const updateCaigouPlanSubmit = async () => {
|
||||
buttonLoading.value = true; // 显示按钮加载状态
|
||||
try {
|
||||
console.log(form.value);
|
||||
const res = await updateCaigouPlan(form.value);
|
||||
if (res.code === 200) {
|
||||
ElMessage({ message: '采购申请单已成功更新!', type: 'success' });
|
||||
|
||||
// 刷新列表数据
|
||||
getList();
|
||||
|
||||
// 关闭对话框并重置表单
|
||||
resetNewProcurementForm();
|
||||
isDialogVisible.value = false;
|
||||
} else {
|
||||
// 显示详细的错误信息
|
||||
ElMessage({
|
||||
message: res.msg || '更新采购计划单失败,请重试',
|
||||
type: 'error'
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('更新采购计划单失败:', error);
|
||||
ElMessage({ message: '操作失败', type: 'error' });
|
||||
} finally {
|
||||
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
|
||||
}
|
||||
@ -509,12 +661,29 @@ const getSupplierLists = async () => {
|
||||
supplierList.value = res.rows;
|
||||
|
||||
}
|
||||
// 获取文件类型(后缀名)
|
||||
const getFileType = (fileName: string): string => {
|
||||
if (!fileName) return '';
|
||||
const lastDotIndex = fileName.lastIndexOf('.');
|
||||
if (lastDotIndex === -1) return '';
|
||||
return fileName.substring(lastDotIndex + 1).toLowerCase();
|
||||
};
|
||||
|
||||
|
||||
// 预览文件
|
||||
const handlePreview = (file) => {
|
||||
// 实际场景可在这里处理文件预览逻辑,如打开新窗口等
|
||||
window.open(file.fileUrl, '_blank');
|
||||
};
|
||||
// 删除文件
|
||||
const handleDelete = (file) => {
|
||||
// 这里简单地从表格数据中移除该文件
|
||||
form.value.opsCaigouPlanFilesBos = form.value.opsCaigouPlanFilesBos.filter(f => f !== file);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
getList();
|
||||
getSupplierLists();
|
||||
getYearlyAmount();
|
||||
});
|
||||
// 监听用户选择的项目变化
|
||||
watch(() => userStore.selectedProject, (newProject) => {
|
||||
@ -528,10 +697,16 @@ watch(() => userStore.selectedProject, (newProject) => {
|
||||
getList();
|
||||
}
|
||||
}, { immediate: true, deep: true });
|
||||
// 新建采购申请单对话框是否可见
|
||||
const isNewProcurementDialogVisible = ref(false);
|
||||
// 对话框是否可见
|
||||
const isDialogVisible = ref(false);
|
||||
// 当前操作类型:'add' 或 'update'
|
||||
const currentOperation = ref('add');
|
||||
// 对话框标题
|
||||
const dialogTitle = computed(() => {
|
||||
return currentOperation.value === 'add' ? '新建采购申请单' : '编辑采购申请单';
|
||||
});
|
||||
|
||||
// 跳转查看详情
|
||||
// 跳转查看
|
||||
const handleView = (row) => {
|
||||
router.push({
|
||||
path: '/materialManagement/planDetails',
|
||||
@ -540,6 +715,106 @@ const handleView = (row) => {
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 处理新增
|
||||
const handleAdd = async () => {
|
||||
currentOperation.value = 'add';
|
||||
resetNewProcurementForm();
|
||||
|
||||
// 检查是否有保存的草稿
|
||||
const procurementDraftStore = useProcurementDraftStore();
|
||||
const draftList = procurementDraftStore.getDraftList();
|
||||
|
||||
if (draftList && draftList.length > 0) {
|
||||
try {
|
||||
// 提示用户是否恢复上次保存的草稿
|
||||
await ElMessageBox.confirm(
|
||||
'检测到您有未提交的草稿,是否恢复?',
|
||||
'恢复草稿',
|
||||
{
|
||||
confirmButtonText: '恢复',
|
||||
cancelButtonText: '不恢复',
|
||||
type: 'info'
|
||||
}
|
||||
);
|
||||
|
||||
// 获取最新的草稿并恢复
|
||||
const latestDraft = draftList[0]; // 假设列表是按创建时间降序排列的
|
||||
const draftData = procurementDraftStore.getDraft(latestDraft.id);
|
||||
|
||||
if (draftData) {
|
||||
form.value = JSON.parse(JSON.stringify(draftData.content));
|
||||
// 确保产品列表和附件列表有默认值
|
||||
if (!form.value.opsCaigouPlanChanpinBos || form.value.opsCaigouPlanChanpinBos.length === 0) {
|
||||
form.value.opsCaigouPlanChanpinBos = [{chanpinName: '',chanpinType: '',chanpinMonovalent: '',goumaiNumber: '',danwei: '',yontu: '',totalPrice: ''}];
|
||||
}
|
||||
if (!form.value.opsCaigouPlanFilesBos) {
|
||||
form.value.opsCaigouPlanFilesBos = [];
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
// 用户选择不恢复草稿,继续使用空表单
|
||||
if (error !== 'cancel') {
|
||||
console.error('恢复草稿时发生错误:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isDialogVisible.value = true;
|
||||
};
|
||||
|
||||
// 根据操作类型获取对应的提交函数
|
||||
const getSubmitFunction = computed(() => {
|
||||
return currentOperation.value === 'add' ? submitAddProcurement : submitUpdateProcurement;
|
||||
});
|
||||
|
||||
// 处理编辑
|
||||
const handleUpdate = async (row) => {
|
||||
currentOperation.value = 'update';
|
||||
buttonLoading.value = true;
|
||||
try {
|
||||
// 获取采购计划详情
|
||||
const res = await caigouPlanDetail(row.id);
|
||||
if (res.code === 200) {
|
||||
// 深拷贝数据,避免直接修改原始数据
|
||||
form.value = JSON.parse(JSON.stringify(res.data));
|
||||
// 将数据字段从Vos后缀改为Bos后缀
|
||||
if (form.value.opsCaigouPlanChanpinVos) {
|
||||
form.value.opsCaigouPlanChanpinBos = form.value.opsCaigouPlanChanpinVos;
|
||||
delete form.value.opsCaigouPlanChanpinVos;
|
||||
}
|
||||
if (form.value.opsCaigouPlanFilesVos) {
|
||||
form.value.opsCaigouPlanFilesBos = form.value.opsCaigouPlanFilesVos;
|
||||
delete form.value.opsCaigouPlanFilesVos;
|
||||
}
|
||||
console.log(form.value);
|
||||
// 确保产品列表和附件列表有默认值
|
||||
if (!form.value.opsCaigouPlanChanpinBos || form.value.opsCaigouPlanChanpinBos.length === 0) {
|
||||
form.value.opsCaigouPlanChanpinBos = [{
|
||||
chanpinName: '',
|
||||
chanpinType: '',
|
||||
chanpinMonovalent: 0,
|
||||
goumaiNumber: 0,
|
||||
danwei: '',
|
||||
yontu: '',
|
||||
totalPrice: 0
|
||||
}];
|
||||
}
|
||||
if (!form.value.opsCaigouPlanFilesBos || form.value.opsCaigouPlanFilesBos.length === 0) {
|
||||
form.value.opsCaigouPlanFilesBos = [];
|
||||
}
|
||||
// 显示对话框
|
||||
isDialogVisible.value = true;
|
||||
} else {
|
||||
ElMessage({ message: res.msg || '获取采购计划详情失败', type: 'error' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取采购计划详情失败:', error);
|
||||
ElMessage({ message: '获取采购计划详情失败', type: 'error' });
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
// 计算产品总价
|
||||
const calculateTotalPrice = (row) => {
|
||||
if (!row.chanpinMonovalent || !row.goumaiNumber) {
|
||||
@ -595,96 +870,12 @@ const resetNewProcurementForm = () => {
|
||||
chanpinMonovalent: '',
|
||||
goumaiNumber: '',
|
||||
danwei: '',
|
||||
yontu: '',
|
||||
totalPrice: ''
|
||||
}];
|
||||
form.value.opsCaigouPlanFilesBos = [];
|
||||
};
|
||||
|
||||
// 取消新建采购申请
|
||||
const cancelNewProcurement = () => {
|
||||
// 检查是否有未保存的内容
|
||||
const hasContent = Object.values(form.value).some(value => {
|
||||
if (Array.isArray(value)) {
|
||||
return value.length > 0 &&
|
||||
value.some(item =>
|
||||
typeof item === 'object' &&
|
||||
Object.values(item).some(v => v)
|
||||
);
|
||||
}
|
||||
return !!value;
|
||||
});
|
||||
|
||||
if (hasContent) {
|
||||
ElMessageBox.confirm('表单内容尚未保存,确定要关闭吗?', '提示', {
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
resetNewProcurementForm();
|
||||
isNewProcurementDialogVisible.value = false;
|
||||
});
|
||||
} else {
|
||||
resetNewProcurementForm();
|
||||
isNewProcurementDialogVisible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 草稿校验函数
|
||||
const validateDraft = () => {
|
||||
// 草稿只需要计划名称作为必填项
|
||||
if (!form.value.jihuaName.trim()) {
|
||||
ElMessage({ message: '请填写计划名称', type: 'error' });
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查已填写的产品信息的有效性
|
||||
for (let i = 0; i < form.value.opsCaigouPlanChanpinBos.length; i++) {
|
||||
const product = form.value.opsCaigouPlanChanpinBos[i];
|
||||
if (product.chanpinName && !product.chanpinType) {
|
||||
ElMessage({ message: `第${i + 1}行产品:填写了产品名称,请也填写产品型号`, type: 'warning' });
|
||||
}
|
||||
if (product.productPrice && parseFloat(product.productPrice) <= 0) {
|
||||
ElMessage({ message: `第${i + 1}行产品:产品单价应大于0`, type: 'warning' });
|
||||
}
|
||||
if (product.purchaseQuantity && parseInt(product.purchaseQuantity) <= 0) {
|
||||
ElMessage({ message: `第${i + 1}行产品:购买数量应大于0`, type: 'warning' });
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// 保存草稿
|
||||
const saveDraft = async () => {
|
||||
// 验证草稿
|
||||
if (!validateDraft()) {
|
||||
return;
|
||||
}
|
||||
|
||||
buttonLoading.value = true; // 显示按钮加载状态
|
||||
try {
|
||||
// 使用pinia store保存草稿
|
||||
const draftStore = useProcurementDraftStore();
|
||||
const savedDraft = draftStore.saveDraft(form.value.jihuaName, form.value);
|
||||
|
||||
console.log('保存草稿:', {
|
||||
draftNumber: savedDraft.draftNumber,
|
||||
saveTime: savedDraft.saveTime,
|
||||
content: savedDraft.content
|
||||
});
|
||||
|
||||
ElMessage({ message: `草稿已成功保存(编号:${savedDraft.draftNumber}),您可以在草稿箱中查看`, type: 'success' });
|
||||
} catch (error) {
|
||||
console.error('保存草稿失败:', error);
|
||||
ElMessage({
|
||||
message: '保存草稿失败,请重试',
|
||||
type: 'error'
|
||||
});
|
||||
} finally {
|
||||
buttonLoading.value = false; // 无论成功失败,都关闭加载状态
|
||||
}
|
||||
};
|
||||
|
||||
// 表单校验函数
|
||||
const validateForm = () => {
|
||||
// 基础信息校验
|
||||
@ -717,14 +908,18 @@ const validateForm = () => {
|
||||
ElMessage({ message: '请选择供应商单位', type: 'error' });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!form.value.reason) {
|
||||
ElMessage({ message: '请填写申请原因', type: 'error' });
|
||||
return false;
|
||||
}
|
||||
// 产品信息校验
|
||||
const hasValidProduct = form.value.opsCaigouPlanChanpinBos.some(product => {
|
||||
return product.chanpinName &&
|
||||
product.chanpinType &&
|
||||
product.chanpinMonovalent && parseFloat(product.chanpinMonovalent) > 0 &&
|
||||
product.goumaiNumber && parseInt(product.goumaiNumber) > 0 &&
|
||||
product.danwei;
|
||||
product.danwei &&
|
||||
product.yontu;
|
||||
});
|
||||
|
||||
if (!hasValidProduct) {
|
||||
@ -764,14 +959,51 @@ const validateForm = () => {
|
||||
ElMessage({ message: `第${i + 1}行产品:请填写单位`, type: 'error' });
|
||||
return false;
|
||||
}
|
||||
if (!product.yontu) {
|
||||
ElMessage({ message: `第${i + 1}行产品:请填写用途`, type: 'error' });
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
// 提交申请
|
||||
const submitProcurement = async () => {
|
||||
// 新增申请提交
|
||||
const submitAddProcurement = async () => {
|
||||
// 在提交前,为所有产品行重新计算并保存总价
|
||||
form.value.opsCaigouPlanChanpinBos.forEach(product => {
|
||||
calculateTotalPrice(product);
|
||||
});
|
||||
// 表单验证
|
||||
if (!validateForm()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// 确认提交
|
||||
await ElMessageBox.confirm(
|
||||
'确定要提交采购申请单吗?提交后将进入审批流程,不可撤销。',
|
||||
'确认操作',
|
||||
{
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
);
|
||||
// 调用新增提交函数
|
||||
await addCaigouPlanSubmit();
|
||||
} catch (error) {
|
||||
// 处理用户取消或其他错误
|
||||
if (error !== 'cancel') {
|
||||
console.error('提交采购申请单时发生错误:', error);
|
||||
ElMessage({ message: '提交过程中发生错误,请重试', type: 'error' });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 更新申请提交
|
||||
const submitUpdateProcurement = async () => {
|
||||
// 在提交前,为所有产品行重新计算并保存总价
|
||||
form.value.opsCaigouPlanChanpinBos.forEach(product => {
|
||||
calculateTotalPrice(product);
|
||||
@ -785,27 +1017,26 @@ const submitProcurement = async () => {
|
||||
try {
|
||||
// 确认提交
|
||||
await ElMessageBox.confirm(
|
||||
'确定要提交采购申请单吗?提交后将进入审批流程,不可撤销。',
|
||||
'确认提交',
|
||||
'确定要更新采购申请单吗?',
|
||||
'确认操作',
|
||||
{
|
||||
confirmButtonText: '确认提交',
|
||||
confirmButtonText: '确认',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
);
|
||||
|
||||
// 调用提交函数
|
||||
await addCaigouPlans();
|
||||
// 调用更新提交函数
|
||||
await updateCaigouPlanSubmit();
|
||||
|
||||
} catch (error) {
|
||||
// 处理用户取消或其他错误
|
||||
if (error !== 'cancel') {
|
||||
console.error('提交采购申请单时发生错误:', error);
|
||||
ElMessage({ message: '提交过程中发生错误,请重试', type: 'error' });
|
||||
console.error('更新采购申请单时发生错误:', error);
|
||||
ElMessage({ message: '更新过程中发生错误,请重试', type: 'error' });
|
||||
}
|
||||
}
|
||||
}
|
||||
// });
|
||||
|
||||
// 处理文件上传完成后获取完整文件列表
|
||||
const handleUpdateFileList = (fileList) => {
|
||||
@ -815,4 +1046,118 @@ const handleUpdateFileList = (fileList) => {
|
||||
fileUrl: file.url,
|
||||
}));
|
||||
};
|
||||
|
||||
// 检查表单是否有内容
|
||||
const hasFormContent = () => {
|
||||
// 检查基础信息字段
|
||||
if (form.value.jihuaName ||
|
||||
form.value.hetonName ||
|
||||
form.value.hetonType ||
|
||||
form.value.caigouType ||
|
||||
form.value.cangkuUrl ||
|
||||
form.value.danwei ||
|
||||
form.value.chuhuoTime ||
|
||||
form.value.fukuantiaojian ||
|
||||
form.value.fapiaoKjfs ||
|
||||
form.value.reason) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 检查产品信息
|
||||
if (form.value.opsCaigouPlanChanpinBos) {
|
||||
for (const product of form.value.opsCaigouPlanChanpinBos) {
|
||||
if (product.chanpinName ||
|
||||
product.chanpinType ||
|
||||
product.chanpinMonovalent ||
|
||||
product.goumaiNumber ||
|
||||
product.danwei ||
|
||||
product.yontu) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 检查附件
|
||||
if (form.value.opsCaigouPlanFilesBos && form.value.opsCaigouPlanFilesBos.length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
// 取消操作
|
||||
const cancelOperation = async () => {
|
||||
// 检查是否有表单内容
|
||||
if (hasFormContent()) {
|
||||
try {
|
||||
// 提示用户确认是否放弃编辑
|
||||
await ElMessageBox.confirm(
|
||||
'您有未保存的内容,确定要取消吗?',
|
||||
'确认取消',
|
||||
{
|
||||
confirmButtonText: '确定',
|
||||
cancelButtonText: '取消',
|
||||
type: 'warning'
|
||||
}
|
||||
);
|
||||
// 重置表单
|
||||
resetNewProcurementForm();
|
||||
// 关闭对话框
|
||||
isDialogVisible.value = false;
|
||||
} catch (error) {
|
||||
// 用户取消了确认操作
|
||||
if (error !== 'cancel') {
|
||||
console.error('取消操作时发生错误:', error);
|
||||
}
|
||||
// 不执行任何操作,保持对话框打开
|
||||
}
|
||||
} else {
|
||||
// 没有表单内容,直接关闭对话框并重置
|
||||
resetNewProcurementForm();
|
||||
isDialogVisible.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 保存草稿
|
||||
const saveDraft = async () => {
|
||||
buttonLoading.value = true;
|
||||
try {
|
||||
// 检查是否有计划名称
|
||||
if (!form.value.jihuaName || !form.value.jihuaName.trim()) {
|
||||
ElMessage({ message: '请填写计划名称后再保存草稿', type: 'warning' });
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取草稿存储
|
||||
const procurementDraftStore = useProcurementDraftStore();
|
||||
|
||||
// 保存草稿到pinia存储
|
||||
const savedDraft = procurementDraftStore.saveDraft(form.value.jihuaName, form.value);
|
||||
|
||||
// 显示成功消息
|
||||
ElMessage({ message: '草稿保存成功', type: 'success' });
|
||||
|
||||
// 关闭对话框
|
||||
isDialogVisible.value = false;
|
||||
} catch (error) {
|
||||
console.error('保存草稿失败:', error);
|
||||
ElMessage({ message: '草稿保存失败,请重试', type: 'error' });
|
||||
} finally {
|
||||
buttonLoading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 组件卸载时清除草稿
|
||||
onUnmounted(() => {
|
||||
try {
|
||||
// 获取草稿存储
|
||||
const procurementDraftStore = useProcurementDraftStore();
|
||||
// 清除所有草稿
|
||||
procurementDraftStore.clearAllDrafts();
|
||||
} catch (error) {
|
||||
console.error('组件卸载时清除草稿失败:', error);
|
||||
// 这里不显示错误消息,因为组件已经卸载
|
||||
}
|
||||
});
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user