Explorar el Código

财务分析数据录入

wukai hace 1 mes
padre
commit
65da41dd9d
Se han modificado 2 ficheros con 574 adiciones y 0 borrados
  1. 53 0
      src/api/lean/cost.js
  2. 521 0
      src/views/lean/cost/index.vue

+ 53 - 0
src/api/lean/cost.js

@@ -0,0 +1,53 @@
+import request from '@/utils/request'
+
+// 查询财务分析列表
+export function listCost(query) {
+    return request({
+        url: '/lean/cost/list',
+        method: 'get',
+        params: query
+    })
+}
+
+// 查询财务分析详细
+export function getCost(costId) {
+    return request({
+        url: '/lean/cost/' + costId,
+        method: 'get'
+    })
+}
+
+// 新增财务分析
+export function addCost(data) {
+    return request({
+        url: '/lean/cost',
+        method: 'post',
+        data: data
+    })
+}
+
+// 修改财务分析
+export function updateCost(data) {
+    return request({
+        url: '/lean/cost',
+        method: 'put',
+        data: data
+    })
+}
+
+// 删除财务分析
+export function delCost(costId) {
+    return request({
+        url: '/lean/cost/' + costId,
+        method: 'delete'
+    })
+}
+
+// 批量保存财务分析
+export function batchSave(data) {
+    return request({
+        url: '/lean/cost/batchSave',
+        method: 'post',
+        data: data
+    })
+}

+ 521 - 0
src/views/lean/cost/index.vue

@@ -0,0 +1,521 @@
+<template>
+  <div class="app-container">
+    <!-- 查询条件区域 -->
+    <el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
+      <el-form-item label="车间" prop="wsName">
+        <el-select v-model="queryParams.wsName" placeholder="请选择车间" style="width: 150px;"
+                   @change="handleWsChange">
+          <el-option
+              v-for="dict in all_ws"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="年份" prop="year">
+        <el-date-picker
+            v-model="selectedQueryYear"
+            type="year"
+            value-format="YYYY"
+            placeholder="请选择年份"
+            style="width: 150px;"
+            @change="handleYearChange"
+        >
+        </el-date-picker>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+            type="primary"
+            plain
+            icon="Plus"
+            @click="handleAddYear"
+            :disabled="!queryParams.wsName || !selectedQueryYear"
+        >新增年份数据
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="warning"
+            plain
+            icon="CirclePlus"
+            @click="handleAddRow"
+            :disabled="!queryParams.wsName || !selectedQueryYear"
+        >新增单行
+        </el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+            type="success"
+            plain
+            icon="CircleCheck"
+            @click="saveAll"
+        >保存全部
+        </el-button>
+      </el-col>
+
+    </el-row>
+
+    <el-table v-loading="loading" :data="costList" ref="costTable" style="width: 100%;">
+      <el-table-column label="时间" align="center" prop="costTime">
+        <template #default="scope">
+          <el-date-picker
+              v-if="scope.row.isEditing"
+              v-model="scope.row.costTime"
+              type="month"
+              value-format="YYYY-MM"
+              placeholder="请选择月份"
+              style="width: 100%;"
+              :disabled="!scope.row.isNew">
+          </el-date-picker>
+          <span v-else>{{ parseTime(scope.row.costTime, '{y}-{m}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="产量" align="center" prop="length">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.length" placeholder="产量"/>
+          <span v-else>{{ scope.row.length }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="总成本" align="center" prop="totalCost">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.totalCost" placeholder="总成本"/>
+          <span v-else>{{ scope.row.totalCost }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="人工工资" align="center" prop="laborWage">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.laborWage" placeholder="人工工资"/>
+          <span v-else>{{ scope.row.laborWage }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="社会保险" align="center" prop="socialInsurance">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.socialInsurance" placeholder="社会保险"/>
+          <span v-else>{{ scope.row.socialInsurance }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="配件/修理费" align="center" prop="partsRepair">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.partsRepair" placeholder="配件/修理费"/>
+          <span v-else>{{ scope.row.partsRepair }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="染料" align="center" prop="dyeCost">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.dyeCost" placeholder="染料"/>
+          <span v-else>{{ scope.row.dyeCost }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="助剂/辅料" align="center" prop="auxiliaryMaterials">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.auxiliaryMaterials" placeholder="助剂/辅料"/>
+          <span v-else>{{ scope.row.auxiliaryMaterials }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="水电费" align="center" prop="waterElectricity">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.waterElectricity" placeholder="水电费"/>
+          <span v-else>{{ scope.row.waterElectricity }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="摊销及工程费" align="center" prop="amortizationEngineering">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.amortizationEngineering" placeholder="摊销及工程费"/>
+          <span v-else>{{ scope.row.amortizationEngineering }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="折旧" align="center" prop="depreciation">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.depreciation" placeholder="折旧"/>
+          <span v-else>{{ scope.row.depreciation }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="其他" align="center" prop="otherCost">
+        <template #default="scope">
+          <el-input v-if="scope.row.isEditing" v-model="scope.row.otherCost" placeholder="其他"/>
+          <span v-else>{{ scope.row.otherCost }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="120">
+        <template #default="scope">
+          <el-button
+              type="danger"
+              link
+              @click="handleDelete(scope.row)"
+              icon="Delete"
+          >删除
+          </el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+  </div>
+</template>
+
+<script setup name="Cost">
+import {addCost, batchSave, delCost, listCost, updateCost} from "@/api/lean/cost";
+
+const {proxy} = getCurrentInstance();
+const {all_ws} = proxy.useDict('all_ws');
+
+const costList = ref([]);
+const loading = ref(true);
+const ids = ref([]);
+const multiple = ref(true);
+const total = ref(0);
+const originalRows = ref({}); // 用于保存原始数据,便于取消编辑时恢复
+const selectedQueryYear = ref(new Date().getFullYear().toString()); // 查询条件中的年份,默认当年,转为字符串
+
+// 获取车间名称
+function getWsName(wsValue) {
+  if (!wsValue) return '';
+  const ws = all_ws.find(item => item.value === wsValue);
+  return ws ? ws.label : wsValue;
+}
+
+// 车间变化处理
+function handleWsChange(value) {
+  // 车间变化时,如果年份已选择,则自动查询
+  if (selectedQueryYear.value) {
+    handleQuery();
+  }
+}
+
+// 年份变化处理
+function handleYearChange(value) {
+  selectedQueryYear.value = value;
+  // 年份变化时,如果车间已选择,则自动查询
+  if (queryParams.value.wsName) {
+    handleQuery();
+  }
+}
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 30, // 增加页面大小以显示一年12个月的数据
+    wsName: null, // 不再在这里设置默认值,改在getList中处理
+    costTime: null, // 查询时会转换为年份范围
+    length: null,
+    totalCost: null,
+    laborWage: null,
+    socialInsurance: null,
+    partsRepair: null,
+    dyeCost: null,
+    auxiliaryMaterials: null,
+    waterElectricity: null,
+    amortizationEngineering: null,
+    depreciation: null,
+    otherCost: null,
+    createBy: null,
+    createTime: null,
+    updateBy: null,
+    updateTime: null,
+    remark: null
+  },
+  rules: {}
+});
+
+const {queryParams, form, rules} = toRefs(data);
+
+/** 查询财务分析列表 */
+function getList() {
+  loading.value = true;
+  // 设置默认车间 - 只有在没有选择车间且有车间数据时才设置
+  if (!queryParams.value.wsName && all_ws && all_ws.value && all_ws.value.length > 0) {
+    queryParams.value.wsName = all_ws.value[0].value;
+  }
+
+  // 设置默认年份 - 只有在没有选择年份时才设置
+  if (!selectedQueryYear.value) {
+    selectedQueryYear.value = new Date().getFullYear().toString();
+  }
+  queryParams.value.params = {};
+  // 如果选择了年份,则构造该年份的开始和结束时间
+  if (selectedQueryYear.value) {
+    queryParams.value.params["year"] = selectedQueryYear.value;
+  }
+
+  // 构造查询条件
+  const queryParam = {...queryParams.value};
+
+
+  listCost(queryParam).then(response => {
+    costList.value = response.rows.map(item => ({
+      ...item,
+      isEditing: true, // 查询出来的数据也默认处于编辑状态
+      isNew: false // 标识为已存在的数据,不是新增的
+    }));
+
+    // 按时间从早到晚排序
+    costList.value.sort((a, b) => {
+      // 将costTime转换为可比较的日期格式
+      const dateA = new Date(a.costTime);
+      const dateB = new Date(b.costTime);
+      return dateA - dateB;
+    });
+
+    total.value = response.total;
+    loading.value = false;
+  });
+}
+
+// 监听 all_ws 的变化,当它有值时设置默认车间并重新查询
+watch(() => all_ws.value, (newVal) => {
+  if (newVal && newVal.length > 0 && !queryParams.value.wsName) {
+    queryParams.value.wsName = newVal[0].value;
+    handleQuery();
+  }
+});
+
+/** 查询数据 */
+function handleQuery() {
+  // 验证查询条件
+  if (!queryParams.value.wsName) {
+    // proxy.$modal.msgWarning("请选择车间");
+    return;
+  }
+  if (!selectedQueryYear.value) {
+    // proxy.$modal.msgWarning("请选择年份");
+    return;
+  }
+
+  queryParams.value.pageNum = 1;
+  getList();
+}
+
+/** 新增年份数据 */
+function handleAddYear() {
+  // 验证是否选择了车间和年份
+  if (!queryParams.value.wsName || !selectedQueryYear.value) {
+    proxy.$modal.msgWarning("请先选择车间和年份");
+    return;
+  }
+
+  // 检查是否已存在该年份的数据
+  const hasDataForYear = costList.value.some(item =>
+      item.costTime && item.costTime.startsWith(selectedQueryYear.value)
+  );
+
+  if (hasDataForYear) {
+    proxy.$modal.msgWarning(`已存在${selectedQueryYear.value}年的数据,无法新增`);
+    return;
+  }
+
+  // 直接使用查询条件中的年份生成数据
+  const year = selectedQueryYear.value;
+  // 生成该年12个月的数据
+  const newRows = [];
+  for (let month = 1; month <= 12; month++) {
+    const monthStr = month < 10 ? `0${month}` : `${month}`;
+    const costTime = `${year}-${monthStr}`;
+
+    const newRow = {
+      costId: null,
+      wsName: queryParams.value.wsName, // 使用当前选择的车间
+      costTime: costTime,
+      length: null,
+      totalCost: null,
+      laborWage: null,
+      socialInsurance: null,
+      partsRepair: null,
+      dyeCost: null,
+      auxiliaryMaterials: null,
+      waterElectricity: null,
+      amortizationEngineering: null,
+      depreciation: null,
+      otherCost: null,
+      isEditing: true, // 默认进入编辑状态
+      isNew: true // 标识为新增行
+    };
+    newRows.push(newRow);
+  }
+
+  // 将新行添加到列表开头
+  costList.value.unshift(...newRows);
+}
+
+/** 新增单行数据 */
+function handleAddRow() {
+  // 验证是否选择了车间和年份
+  if (!queryParams.value.wsName || !selectedQueryYear.value) {
+    proxy.$modal.msgWarning("请先选择车间和年份");
+    return;
+  }
+
+  // 创建一个新的空行数据
+  const newRow = {
+    costId: null,
+    wsName: queryParams.value.wsName, // 使用当前选择的车间
+    costTime: null, // 空的时间字段,让用户自己填写
+    length: null,
+    totalCost: null,
+    laborWage: null,
+    socialInsurance: null,
+    partsRepair: null,
+    dyeCost: null,
+    auxiliaryMaterials: null,
+    waterElectricity: null,
+    amortizationEngineering: null,
+    depreciation: null,
+    otherCost: null,
+    isEditing: true, // 默认进入编辑状态
+    isNew: true // 标识为新增行
+  };
+
+  // 将新行添加到列表开头
+  costList.value.unshift(newRow);
+}
+
+// 使用 nextTick 确保 DOM 更新后执行查询
+nextTick(() => {
+  console.log('nextTick executed, selectedQueryYear:', selectedQueryYear.value);
+  // 确保年份有默认值
+  if (!selectedQueryYear.value) {
+    selectedQueryYear.value = new Date().getFullYear();
+  }
+  handleQuery();
+});
+
+/** 编辑行 */
+function handleEdit(row) {
+  // 保存原始数据
+  originalRows.value[row.costId || 'new_' + costList.value.indexOf(row)] = {...row};
+  row.isEditing = true;
+}
+
+/** 取消编辑 */
+function cancelEdit(row) {
+  const rowId = row.costId || 'new_' + costList.value.indexOf(row);
+  if (row.isNew) {
+    // 如果是新增行,直接删除
+    const index = costList.value.indexOf(row);
+    if (index > -1) {
+      costList.value.splice(index, 1);
+    }
+  } else {
+    // 如果是编辑已存在的行,恢复原始数据
+    const originalRow = originalRows.value[rowId];
+    if (originalRow) {
+      Object.assign(row, originalRow);
+    }
+    row.isEditing = false;
+    delete originalRows.value[rowId];
+  }
+}
+
+/** 保存单行 */
+function saveRow(row) {
+  // 创建一个副本用于提交,将costTime转换为完整日期时间格式
+  const submitRow = {
+    ...row,
+    costTime: row.costTime ? `${row.costTime}-01 00:00:00` : null // 将年月转换为完整日期时间格式
+  };
+
+  if (row.isNew) {
+    // 新增
+    addCost(submitRow).then(response => {
+      proxy.$modal.msgSuccess("新增成功");
+      row.isNew = false;
+      row.costId = response.data.costId; // 更新ID
+      row.isEditing = false;
+      getList(); // 重新加载数据以确保数据一致性
+    }).catch(error => {
+      proxy.$modal.msgError("新增失败: " + error.message);
+    });
+  } else {
+    // 更新
+    updateCost(submitRow).then(response => {
+      proxy.$modal.msgSuccess("修改成功");
+      row.isEditing = false;
+      const rowId = row.costId || 'new_' + costList.value.indexOf(row);
+      delete originalRows.value[rowId];
+    }).catch(error => {
+      proxy.$modal.msgError("修改失败: " + error.message);
+    });
+  }
+}
+
+/** 保存全部 */
+function saveAll() {
+  const editingRows = costList.value.filter(row => row.isEditing);
+  if (editingRows.length === 0) {
+    proxy.$modal.msgInfo("没有需要保存的数据");
+    return;
+  }
+
+  // 转换所有正在编辑的行的costTime格式
+  const submitRows = editingRows.map(row => ({
+    ...row,
+    costTime: row.costTime ? `${row.costTime}-01 00:00:00` : null // 将年月转换为完整日期时间格式
+  }));
+
+  // 使用batchSave接口一次性保存所有数据
+  batchSave(submitRows).then(response => {
+    proxy.$modal.msgSuccess("全部保存成功");
+    getList(); // 重新加载数据
+  }).catch(error => {
+    proxy.$modal.msgError("保存失败: " + error.message);
+  });
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef");
+  handleQuery();
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.costId);
+  multiple.value = !selection.length;
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  // 如果是新增行且还没有保存到后台(costId为空)
+  if (row.isNew && !row.costId) {
+    // 直接在界面上删除
+    const index = costList.value.indexOf(row);
+    if (index > -1) {
+      costList.value.splice(index, 1);
+      proxy.$modal.msgSuccess("删除成功");
+    }
+  } else if (row.costId) {
+    // 如果是已存在的数据(costId不为空),调用后台接口删除
+    const costId = row.costId;
+    proxy.$modal.confirm('是否确认删除财务分析编号为"' + costId + '"的数据项?').then(function () {
+      return delCost(costId);
+    }).then(() => {
+      // 从列表中移除该行
+      const index = costList.value.indexOf(row);
+      if (index > -1) {
+        costList.value.splice(index, 1);
+      }
+      proxy.$modal.msgSuccess("删除成功");
+    }).catch(() => {
+      proxy.$modal.msgError("删除失败");
+    });
+  } else {
+    // 其他情况直接在界面上删除
+    const index = costList.value.indexOf(row);
+    if (index > -1) {
+      costList.value.splice(index, 1);
+      proxy.$modal.msgSuccess("删除成功");
+    }
+  }
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('lean/cost/export', {
+    ...queryParams.value
+  }, `cost_${new Date().getTime()}.xlsx`)
+}
+
+getList();
+</script>