干燥机配套车间生产管理系统/云平台前端
feat(dry): 新增设备维护记录功能、新增维修记录功能、设备主数据增加履历相关字段
已修改1个文件
已添加19个文件
2277 ■■■■■ 文件已修改
src/views/dry/dataDefine/DryEquipment.data.ts 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/DryMaintenanceRecord.api.ts 76 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/DryMaintenanceRecord.data.ts 175 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/DryMaintenanceRecordList.vue 207 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/DryMaintenanceRecord_menu_insert.sql 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/components/DryMaintenanceRecordForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/maint/components/DryMaintenanceRecordModal.vue 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/repair/DrySpareStockLogListRepair.vue 192 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareParts.api.ts 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareParts.data.ts 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySparePartsList.vue 197 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareParts_menu_insert.sql 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareStockLog.api.ts 85 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareStockLog.data.ts 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareStockLogList.vue 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/DrySpareStockLog_menu_insert.sql 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/components/DrySparePartsForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/components/DrySparePartsModal.vue 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/components/DrySpareStockLogForm.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/spareParts/components/DrySpareStockLogModal.vue 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dry/dataDefine/DryEquipment.data.ts
@@ -21,6 +21,47 @@
        dataIndex: 'type_dictText',
    },
    {
        title: '制造商',
        align: 'center',
        dataIndex: 'manufacturer',
    },
    {
        title: '购入日期',
        align: 'center',
        dataIndex: 'purchaseDate',
    },
    {
        title: '启用日期',
        align: 'center',
        dataIndex: 'startDate',
    },
    {
        title: '安装位置',
        align: 'center',
        dataIndex: 'location',
    },
    {
        title: '设备状态',
        align: 'center',
        dataIndex: 'status',
        customRender: ({text}) => {
            // 0-'新增',1-'在用', 2-'停用', 3-'ç»´ä¿®', 4-'报废'
      const options = {
        '0': '新增',
        '1': '在用',
        '2': '停用',
        '3': 'ç»´ä¿®',
        '4': '报废'
      };
      return options[text] || text;
    }
    },
    {
        title: '报废日期',
        align: 'center',
        dataIndex: 'scrapDate',
    },
    {
        title: '设备描述',
        align: 'center',
        dataIndex: 'remark',
@@ -99,6 +140,57 @@
        },
    },
    {
        label: '制造商',
        field: 'manufacturer',
        component: 'Input',
    },
    {
        label: '购入日期',
        field: 'purchaseDate',
        component: 'DatePicker',
        componentProps: {
            valueFormat: 'YYYY-MM-DD',
            format: 'YYYY-MM-DD'
        },
    },
    {
        label: '启用日期',
        field: 'startDate',
        component: 'DatePicker',
        componentProps: {
            valueFormat: 'YYYY-MM-DD',
            format: 'YYYY-MM-DD'
        },
    },
    {
        label: '安装位置',
        field: 'location',
        component: 'Input',
    },
    {
        label: '设备状态',
        field: 'status',
        component: 'Select',
        componentProps: {
            options: [ // '周保','月保','季保','年保'
              { label: '新增', value: '0' },
              { label: '在用', value: '1' },
              { label: '停用', value: '2' },
              { label: 'ç»´ä¿®', value: '3' },
              { label: '报废', value: '4' }
            ]
        },
    },
    {
        label: '报废日期',
        field: 'scrapDate',
        component: 'DatePicker',
        componentProps: {
            valueFormat: 'YYYY-MM-DD',
            format: 'YYYY-MM-DD'
        },
    },
    {
        label: '设备IP',
        field: 'ip',
        component: 'Input',
@@ -113,7 +205,7 @@
        componentProps: {
            dictCode: 'dry_eqp_type,name,id,tenant_id=' + getTenantId(),
        },
        dynamicRules: ({ model, schema }) => {
        dynamicRules: ({  }) => {
            return [{ required: true, message: '请输入设备类型!' }]
        },
    },
@@ -129,7 +221,7 @@
        componentProps: {
            dictCode: 'dry_shop,name,id,tenant_id=' + getTenantId(),
        },
        dynamicRules: ({ model, schema }) => {
        dynamicRules: ({ }) => {
            return [{ required: true, message: '请输入车间id!' }]
        },
    },
@@ -138,7 +230,7 @@
        field: 'enable',
        component: 'JSwitch',
        componentProps: {},
        dynamicRules: ({ model, schema }) => {
        dynamicRules: ({  }) => {
            return [{ required: true, message: '请输入启用状态!' }]
        },
    },
src/views/dry/maint/DryMaintenanceRecord.api.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,76 @@
import {defHttp} from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
  list = '/dry/dryMaintenanceRecord/list',
  save='/dry/dryMaintenanceRecord/add',
  edit='/dry/dryMaintenanceRecord/edit',
  deleteOne = '/dry/dryMaintenanceRecord/delete',
  deleteBatch = '/dry/dryMaintenanceRecord/deleteBatch',
  importExcel = '/dry/dryMaintenanceRecord/importExcel',
  exportXls = '/dry/dryMaintenanceRecord/exportXls',
  generateMaintenanceNo = '/dry/dryMaintenanceRecord/generateMaintenanceNo'
}
/**
 * å¯¼å‡ºapi
 * @param params
 */
export const getExportUrl = Api.exportXls;
/**
 * å¯¼å…¥api
 */
export const getImportUrl = Api.importExcel;
/**
 * åˆ—表接口
 * @param params
 */
export const list = (params) => {
  if (params.planNumber) {
    params.relatedOrder = params.planNumber;
    delete params.planNumber;
  }
  return defHttp.get({url: Api.list, params});
};
/**
 * åˆ é™¤å•个
 */
export const deleteOne = (params,handleSuccess) => {
  return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
    handleSuccess();
  });
}
/**
 * æ‰¹é‡åˆ é™¤
 * @param params
 */
export const batchDelete = (params, handleSuccess) => {
  createConfirm({
    iconType: 'warning',
    title: '确认删除',
    content: '是否删除选中数据',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
        handleSuccess();
      });
    }
  });
}
/**
 * ä¿å­˜æˆ–者更新
 * @param params
 */
export const saveOrUpdate = (params, isUpdate) => {
  let url = isUpdate ? Api.edit : Api.save;
  return defHttp.post({url: url, params});
}
/**
 * ç”Ÿæˆä¿å…»å•编号
 */
export const generateMaintenanceNo = () => {
  return defHttp.get({url: Api.generateMaintenanceNo},{ successMessageMode: 'none' });
}
src/views/dry/maint/DryMaintenanceRecord.data.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,175 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
   {
    title: '保养编号',
    align:"center",
    dataIndex: 'planNumber'
   },
   {
    title: '设备编号',
    align:"center",
    dataIndex: 'equipmentId_dictText'
   },
   {
    title: '保养周期',
    align:"center",
    dataIndex: 'cycle',
   },
   {
    title: '保养时间',
    align:"center",
    dataIndex: 'maintDate',
    customRender:({text}) =>{
      return !text?"":(text.length>10?text.substr(0,10):text)
    },
   },
   {
    title: '保养人员',
    align:"center",
    dataIndex: 'technician'
   },
   {
    title: '保养内容',
    align:"center",
    dataIndex: 'content'
   },
   {
    title: '备件使用情况',
    align:"center",
    dataIndex: 'spareParts'
   },
   {
    title: '备注',
    align:"center",
    dataIndex: 'remark'
   },
];
//查询数据
export const searchFormSchema: FormSchema[] = [
    {
      label: "设备编号",
      field: 'equipmentId',
      component: 'JDictSelectTag',
      componentProps:{
          dictCode:"dry_equipment,name,id"
      },
      colProps: {span: 6},
     },
  {
    label: '保养周期',
    field: 'cycle',
    component: 'JDictSelectTag',
    componentProps:{
            options: [ // '周保','月保','季保','年保'
              { label: '周保', value: '周保' },
              { label: '月保', value: '月保' },
              { label: '季保', value: '季保' },
              { label: '年保', value: '年保' }
            ]
        },
    colProps: {span: 6},
  },
{
      label: "保养时间",
      field: 'maintDate',
      component: 'DatePicker',
      componentProps: {
         showTime:true,
         valueFormat: 'YYYY-MM-DD HH:mm:ss'
       },
      colProps: {span: 6},
     },
    {
      label: "保养人员",
      field: 'technician',
      component: 'Input',
      colProps: {span: 6},
     },
];
//表单数据
export const formSchema: FormSchema[] = [
  {
    label: '保养编号',
    field: 'planNumber',
    component: 'Input',
    dynamicDisabled:true
  },
  {
    label: '设备编号',
    field: 'equipmentId',
    component: 'JDictSelectTag',
    componentProps:{
        dictCode:"dry_equipment,name,id"
     },
    rules: [{ required: true, message: '请选择设备编号' }],
  },
  {
    label: '保养周期',
    field: 'cycle',
    component: 'JDictSelectTag',
    componentProps:{
            options: [ // '周保','月保','季保','年保'
              { label: '周保', value: '周保' },
              { label: '月保', value: '月保' },
              { label: '季保', value: '季保' },
              { label: '年保', value: '年保' }
            ]
        },
    rules: [{ required: true, message: '请选择保养周期' }],
  },
  {
    label: '保养时间',
    field: 'maintDate',
    component: 'DatePicker',
    componentProps: {
       showTime: true,
       valueFormat: 'YYYY-MM-DD HH:mm:ss'
     },
    rules: [{ required: true, message: '请选择保养时间' }],
  },
  {
    label: '保养人员',
    field: 'technician',
    component: 'Input',
    rules: [{ required: true, message: '请输入保养人员' }],
  },
  {
    label: '保养内容',
    field: 'content',
    component: 'InputTextArea',
    rules: [{ required: true, message: '请输入保养内容' }],
  },
  {
    label: '备件使用情况',
    field: 'spareParts',
    component: 'Input',
  },
  {
    label: '备注',
    field: 'remark',
    component: 'Input',
  },
    // TODO ä¸»é”®éšè—å­—段,目前写死为ID
    {
      label: '',
      field: 'id',
      component: 'Input',
      show: false
    },
];
/**
* æµç¨‹è¡¨å•调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
  // é»˜è®¤å’ŒåŽŸå§‹è¡¨å•ä¿æŒä¸€è‡´ å¦‚果流程中配置了权限数据,这里需要单独处理formSchema
  return formSchema;
}
src/views/dry/maint/DryMaintenanceRecordList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,207 @@
<template>
  <div>
    <!--引用表格-->
   <BasicTable @register="registerTable" :rowSelection="rowSelection">
     <!--插槽:table标题-->
      <template #tableTitle>
          <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> æ–°å¢ž</a-button>
          <a-button  type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> å¯¼å‡º</a-button>
          <j-upload-button  type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
          <a-dropdown v-if="selectedRowKeys.length > 0">
              <template #overlay>
                <a-menu>
                  <a-menu-item key="1" @click="batchHandleDelete">
                    <Icon icon="ant-design:delete-outlined"></Icon>
                    åˆ é™¤
                  </a-menu-item>
                </a-menu>
              </template>
              <a-button>批量操作
                <Icon icon="mdi:chevron-down"></Icon>
              </a-button>
        </a-dropdown>
      </template>
       <!--操作栏-->
      <template #action="{ record }">
        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
      </template>
      <!--字段回显插槽-->
      <template #htmlSlot="{text}">
         <div v-html="text"></div>
      </template>
      <!--省市区字段回显插槽-->
      <template #pcaSlot="{text}">
         {{ getAreaTextByCode(text) }}
      </template>
      <template #fileSlot="{text}">
         <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
         <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
      </template>
    </BasicTable>
    <!-- è¡¨å•区域 -->
    <DryMaintenanceRecordModal @register="registerModal" @success="handleSuccess"></DryMaintenanceRecordModal>
  </div>
  <!--子表表格tab-->
  <a-tabs defaultActiveKey="1" style="margin: 10px">
    <a-tab-pane tab="使用备件列表" key="1" forceRender>
      <DrySpareStockLogListRepair />
    </a-tab-pane>
  </a-tabs>
</template>
<script lang="ts" name="dry-dryMaintenanceRecord" setup>
  import {ref, computed, unref, provide} from 'vue';
  import {BasicTable, useTable, TableAction} from '/@/components/Table';
  import {useModal} from '/@/components/Modal';
  import { useListPage } from '/@/hooks/system/useListPage'
  import DryMaintenanceRecordModal from './components/DryMaintenanceRecordModal.vue'
  import DrySpareStockLogListRepair from '../repair/DrySpareStockLogListRepair.vue';
  import {columns, searchFormSchema} from './DryMaintenanceRecord.data';
  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './DryMaintenanceRecord.api';
  import { downloadFile } from '/@/utils/common/renderUtils';
  const checkedKeys = ref<Array<string | number>>([]);
  //注册model
  const [registerModal, {openModal}] = useModal();
  const selectedRows = ref<Array<any>>([]); // æ–°å¢žï¼šç”¨äºŽå­˜å‚¨é€‰ä¸­çš„行数据
  //注册table数据
  const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
      tableProps:{
           title: 'dry_maintenance_record',
           api: list,
           columns,
           canResize:false,
           formConfig: {
              //labelWidth: 120,
              schemas: searchFormSchema,
              autoSubmitOnEnter:true,
              showAdvancedButton:true,
              fieldMapToNumber: [
              ],
              fieldMapToTime: [
              ],
            },
           actionColumn: {
               width: 120,
               fixed:'right'
            },
           rowSelection: {
             type: 'radio',
             onChange: (selectedRowKeyList: (string | number)[], selectedRowList: any[]) => {
               selectedRowKeys.value = selectedRowKeyList;
               selectedRows.value = selectedRowList;
             },
           },
           customRow: (record) => {
             return {
               onClick: () => {
                 if (selectedRowKeys.value.includes(record.id)) {
                   selectedRowKeys.value = [];
                   selectedRows.value = [];
                 } else {
                   selectedRowKeys.value = [record.id];
                   selectedRows.value = [record];
                 }
               },
             };
           },
      },
       exportConfig: {
            name:"dry_maintenance_record",
            url: getExportUrl,
          },
          importConfig: {
            url: getImportUrl,
            success: handleSuccess
          },
  })
  const [registerTable, {reload, updateTableDataRecord},{ rowSelection, selectedRowKeys }] = tableContext
  const planNumber = computed(() => (
     unref(selectedRows).length > 0 ? unref(selectedRows)[0].planNumber : '1'))
  ;
  //下发 planNumber,子组件接收
  provide('orderNumber', planNumber);
   /**
    * æ–°å¢žäº‹ä»¶
    */
  function handleAdd() {
     openModal(true, {
       isUpdate: false,
       showFooter: true,
     });
  }
   /**
    * ç¼–辑事件
    */
  function handleEdit(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: true,
     });
   }
   /**
    * è¯¦æƒ…
   */
  function handleDetail(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: false,
     });
   }
   /**
    * åˆ é™¤äº‹ä»¶
    */
  async function handleDelete(record) {
     await deleteOne({id: record.id}, handleSuccess);
   }
   /**
    * æ‰¹é‡åˆ é™¤äº‹ä»¶
    */
  async function batchHandleDelete() {
     await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
   }
   /**
    * æˆåŠŸå›žè°ƒ
    */
  function handleSuccess() {
      (selectedRowKeys.value = []) && reload();
   }
   /**
      * æ“ä½œæ 
      */
  function getTableAction(record){
       return [
         {
           label: '编辑',
           onClick: handleEdit.bind(null, record),
         }
       ]
   }
     /**
        * ä¸‹æ‹‰æ“ä½œæ 
        */
  function getDropDownAction(record){
       return [
         {
           label: '详情',
           onClick: handleDetail.bind(null, record),
         }, {
           label: '删除',
           popConfirm: {
             title: '是否确认删除',
             confirm: handleDelete.bind(null, record),
           }
         }
       ]
   }
</script>
<style scoped>
</style>
src/views/dry/maint/DryMaintenanceRecord_menu_insert.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
-- æ³¨æ„ï¼šè¯¥é¡µé¢å¯¹åº”的前台目录为views/dry文件夹下
-- å¦‚果你想更改到其他目录,请修改sql中component字段对应的值
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('2025072104423690330', NULL, 'dry_maintenance_record', '/dry/dryMaintenanceRecordList', 'dry/maint/DryMaintenanceRecordList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0);
-- æƒé™æŽ§åˆ¶sql
-- æ–°å¢ž
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690331', '2025072104423690330', '添加dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
-- ç¼–辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690332', '2025072104423690330', '编辑dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
-- åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690333', '2025072104423690330', '删除dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
-- æ‰¹é‡åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690334', '2025072104423690330', '批量删除dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å‡ºexcel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690335', '2025072104423690330', '导出excel_dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å…¥excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072104423690336', '2025072104423690330', '导入excel_dry_maintenance_record', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_maintenance_record:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-21 16:42:33', NULL, NULL, 0, 0, '1', 0);
src/views/dry/maint/components/DryMaintenanceRecordForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
<template>
    <div style="min-height: 400px">
        <BasicForm @register="registerForm"></BasicForm>
        <div style="width: 100%;text-align: center" v-if="!formDisabled">
            <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 äº¤</a-button>
        </div>
    </div>
</template>
<script lang="ts">
    import {BasicForm, useForm} from '/@/components/Form/index';
    import {computed, defineComponent} from 'vue';
    import {defHttp} from '/@/utils/http/axios';
    import { propTypes } from '/@/utils/propTypes';
    import {getBpmFormSchema} from '../DryMaintenanceRecord.data';
    import {saveOrUpdate} from '../DryMaintenanceRecord.api';
    export default defineComponent({
        name: "DryMaintenanceRecordForm",
        components:{
            BasicForm
        },
        props:{
            formData: propTypes.object.def({}),
            formBpm: propTypes.bool.def(true),
        },
        setup(props){
            const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
                labelWidth: 150,
                schemas: getBpmFormSchema(props.formData),
                showActionButtonGroup: false,
                baseColProps: {span: 12}
            });
            const formDisabled = computed(()=>{
                if(props.formData.disabled === false){
                    return false;
                }
                return true;
            });
            let formData = {};
            const queryByIdUrl = '/dry/dryMaintenanceRecord/queryById';
            async function initFormData(){
                let params = {id: props.formData.dataId};
                const data = await defHttp.get({url: queryByIdUrl, params});
                formData = {...data}
                //设置表单的值
                await setFieldsValue(formData);
                //默认是禁用
                await setProps({disabled: formDisabled.value})
            }
            async function submitForm() {
                let data = getFieldsValue();
                let params = Object.assign({}, formData, data);
                console.log('表单数据', params)
                await saveOrUpdate(params, true)
            }
            initFormData();
            return {
                registerForm,
                formDisabled,
                submitForm,
            }
        }
    });
</script>
src/views/dry/maint/components/DryMaintenanceRecordModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,72 @@
<template>
  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="896" @ok="handleSubmit">
      <BasicForm @register="registerForm"/>
  </BasicModal>
</template>
<script lang="ts" setup>
    import {ref, computed, unref} from 'vue';
    import {BasicModal, useModalInner} from '/@/components/Modal';
    import {BasicForm, useForm} from '/@/components/Form/index';
    import {formSchema} from '../DryMaintenanceRecord.data';
    import {saveOrUpdate, generateMaintenanceNo} from '../DryMaintenanceRecord.api';
    // Emits声明
    const emit = defineEmits(['register','success']);
    const isUpdate = ref(true);
    //表单配置
    const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
        //labelWidth: 150,
        schemas: formSchema,
        showActionButtonGroup: false,
        baseColProps: {span: 24}
    });
    //表单赋值
    const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
        //重置表单
        await resetFields();
        setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
        isUpdate.value = !!data?.isUpdate;
        if (unref(isUpdate)) {
            //表单赋值
            await setFieldsValue({
                ...data.record,
            });
        } else {
            // æ–°å¢žæ¨¡å¼ä¸‹ç”Ÿæˆä¿å…»å•编号
            const result = await generateMaintenanceNo();
            await setFieldsValue({
                planNumber: result,
            });
        }
        // éšè—åº•部时禁用整个表单
       setProps({ disabled: !data?.showFooter })
    });
    //设置标题
    const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
    //表单提交事件
    async function handleSubmit(v) {
        try {
            let values = await validate();
            setModalProps({confirmLoading: true});
            //提交表单
            await saveOrUpdate(values, isUpdate.value);
            //关闭弹窗
            closeModal();
            //刷新列表
            emit('success');
        } finally {
            setModalProps({confirmLoading: false});
        }
    }
</script>
<style lang="less" scoped>
    /** æ—¶é—´å’Œæ•°å­—输入框样式 */
  :deep(.ant-input-number){
        width: 100%
    }
    :deep(.ant-calendar-picker){
        width: 100%
    }
</style>
src/views/dry/repair/DrySpareStockLogListRepair.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,192 @@
<template>
  <div>
    <!--引用表格-->
   <BasicTable @register="registerTable" :rowSelection="rowSelection" :search-info="searchInfo">
     <!--插槽:table标题-->
      <template #tableTitle>
          <a-button type="primary" @click="handleCreate" preIcon="ant-design:plus-outlined"> æ–°å¢ž</a-button>
          <a-dropdown v-if="selectedRowKeys.length > 0">
              <template #overlay>
                <a-menu>
                  <a-menu-item key="1" @click="batchHandleDelete">
                    <Icon icon="ant-design:delete-outlined"></Icon>
                    åˆ é™¤
                  </a-menu-item>
                </a-menu>
              </template>
              <a-button>批量操作
                <Icon icon="mdi:chevron-down"></Icon>
              </a-button>
        </a-dropdown>
      </template>
      <!--操作栏-->
      <!-- <template #action="{ record }">
        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
      </template> -->
   </BasicTable>
    <!-- è¡¨å•区域 -->
    <DrySpareStockLogModal @register="registerModal" @success="handleSuccess"></DrySpareStockLogModal>
  </div>
</template>
<script lang="ts" name="dry-drySpareStockLogRepair" setup>
  import {ref, computed, unref, inject, watch, nextTick} from 'vue';
  import {BasicTable, useTable, TableAction} from '/@/components/Table';
  import {useModal} from '/@/components/Modal';
  import {useMessage} from '/@/hooks/web/useMessage';
  import { useListPage } from '/@/hooks/system/useListPage'
  import DrySpareStockLogModal from '../spareParts/components/DrySpareStockLogModal.vue'
  import {columns, searchFormSchema} from '../spareParts/DrySpareStockLog.data';
  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from '../spareParts/DrySpareStockLog.api';
  import { downloadFile } from '/src/utils/common/renderUtils';
  import {isEmpty} from "/src/utils/is";
  const checkedKeys = ref<Array<string | number>>([]);
  //注册model
  const [registerModal, {openModal}] = useModal();
  const searchInfo = {};
  // ä»Žçˆ¶ç»„件注入 orderNumber
  const orderNumber = inject('orderNumber', ''); // ä¿æŒåç§°ä¸ºrepairRecordId,但实际传递的是orderNumber
  //注册table数据
  const { prefixCls,tableContext } = useListPage({
      tableProps:{
           title: '出入库记录表',
           api: list,
           columns,
           canResize:false,
        useSearchForm:false,
           formConfig: {
              //labelWidth: 120,
              schemas: searchFormSchema,
              autoSubmitOnEnter:true,
              showAdvancedButton:true,
              fieldMapToNumber: [
              ],
              fieldMapToTime: [
              ],
            },
           // actionColumn: {
           //     width: 120,
           //     fixed:'right'
           //  },
           showActionColumn: false,
           // æ ¹æ® orderNumber è¿‡æ»¤æ•°æ®
           beforeFetch: (params) => {
              console.log('beforeFetch', params, orderNumber.value)
             return Object.assign(params, { orderNumber: unref(orderNumber) });
           },
      },
       exportConfig: {
            name:"出入库记录表",
            url: getExportUrl,
          },
          importConfig: {
            url: getImportUrl,
            success: handleSuccess
          },
  })
  const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
  // ç›‘听 orderNumber å˜åŒ–,重新加载表格数据
  watch(orderNumber, () => {
    reload();
  });
   /**
    * æ–°å¢žäº‹ä»¶
    */
  function handleCreate() {
    console.log('handleCreate', unref(orderNumber));
     const {createMessage} = useMessage();
     if (isEmpty(unref(orderNumber)) || orderNumber.value === '1') { // æ£€æŸ¥orderNumber是否为空
       createMessage.warning('请选择一个维修单');
       return;
     }
     nextTick(() => {
       console.log('handleCreate', unref(orderNumber));
       openModal(true, {
       isUpdate: false,
       showFooter: true,
        stockType: 'out',
         relatedOrder: unref(orderNumber), // ä¼ é€’ orderNumber
       });
     });
  }
   /**
    * ç¼–辑事件
    */
  function handleEdit(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: true,
     });
   }
   /**
    * è¯¦æƒ…
   */
  function handleDetail(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: false,
     });
   }
   /**
    * åˆ é™¤äº‹ä»¶
    */
  async function handleDelete(record) {
     await deleteOne({id: record.id}, handleSuccess);
   }
   /**
    * æ‰¹é‡åˆ é™¤äº‹ä»¶
    */
  async function batchHandleDelete() {
     await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
   }
   /**
    * æˆåŠŸå›žè°ƒ
    */
  function handleSuccess() {
      (selectedRowKeys.value = []) && reload();
   }
   /**
      * æ“ä½œæ 
      */
  // function getTableAction(record){
  //      return [
  //        {
  //          label: '编辑',
  //          onClick: handleEdit.bind(null, record),
  //        }
  //      ]
  //  }
  //    /**
  //       * ä¸‹æ‹‰æ“ä½œæ 
  //       */
  // function getDropDownAction(record){
  //      return [
  //        {
  //          label: '详情',
  //          onClick: handleDetail.bind(null, record),
  //        }, {
  //          label: '删除',
  //          popConfirm: {
  //            title: '是否确认删除',
  //            confirm: handleDelete.bind(null, record),
  //          }
  //        }
  //      ]
  //  }
</script>
<style scoped>
</style>
src/views/dry/spareParts/DrySpareParts.api.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,82 @@
import {defHttp} from '/@/utils/http/axios';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
  list = '/dry/drySpareParts/list',
  save='/dry/drySpareParts/add',
  edit='/dry/drySpareParts/edit',
  deleteOne = '/dry/drySpareParts/delete',
  deleteBatch = '/dry/drySpareParts/deleteBatch',
  importExcel = '/dry/drySpareParts/importExcel',
  exportXls = '/dry/drySpareParts/exportXls',
  addStock = '/dry/drySpareParts/addStock',
  reduceStock = '/dry/drySpareParts/reduceStock',
}
/**
 * å¯¼å‡ºapi
 * @param params
 */
export const getExportUrl = Api.exportXls;
/**
 * å¯¼å…¥api
 */
export const getImportUrl = Api.importExcel;
/**
 * åˆ—表接口
 * @param params
 */
export const list = (params) =>
  defHttp.get({url: Api.list, params});
/**
 * åˆ é™¤å•个
 */
export const deleteOne = (params,handleSuccess) => {
  return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
    handleSuccess();
  });
}
/**
 * æ‰¹é‡åˆ é™¤
 * @param params
 */
export const batchDelete = (params, handleSuccess) => {
  createConfirm({
    iconType: 'warning',
    title: '确认删除',
    content: '是否删除选中数据',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
        handleSuccess();
      });
    }
  });
}
/**
 * ä¿å­˜æˆ–者更新
 * @param params
 */
export const saveOrUpdate = (params, isUpdate) => {
  let url = isUpdate ? Api.edit : Api.save;
  return defHttp.post({url: url, params});
}
/**
 * å¢žåŠ åº“å­˜
 * @param params
 */
export const addStock = (params) => {
  return defHttp.post({url: Api.addStock, params});
}
/**
 * å‡å°‘库存
 * @param params
 */
export const reduceStock = (params) => {
  return defHttp.post({url: Api.reduceStock, params});
}
src/views/dry/spareParts/DrySpareParts.data.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
import {BasicColumn} from '/@/components/Table';
import {FormSchema} from '/@/components/Table';
import { rules} from '/@/utils/helper/validator';
import { render } from '/@/utils/common/renderUtils';
//列表数据
export const columns: BasicColumn[] = [
   {
    title: '零件编号',
    align:"center",
    dataIndex: 'partNumber'
   },
   {
    title: '零件名称',
    align:"center",
    dataIndex: 'partName'
   },
   {
    title: '分类',
    align:"center",
    dataIndex: 'category',
    customRender: ({ text }) => {
      // æœºæ¢°ç±»ï¼šå¦‚轴承、齿轮、链条等。
// ç”µæ°”类:如继电器、接触器、电缆等。
// æ¶²åŽ‹ç±»ï¼šå¦‚æ³µã€é˜€ã€æ²¹ç®¡ç­‰ã€‚
// æ°”动类:如气缸、电磁阀、空气过滤器等。
// ç”µå­ç±»ï¼šå¦‚电路板、传感器、显示器等。
            return render.renderSwitch(text, [
                { text: '机械类', value: '0' },
                { text: '电气类', value: '1' },
                { text: '液压类', value: '2' },
                { text: '气动类', value: '3' },
                { text: '电子类', value: '4' },
            ])
        },
   },
   {
    title: '规格型号',
    align:"center",
    dataIndex: 'specModel'
   },
   {
    title: '单位',
    align:"center",
    dataIndex: 'unit',
    customRender: ({ text }) => {
//       ä¸ª/件:适用于大多数独立的零部件,如螺丝、螺帽、继电器等。
// ç±³ï¼ˆm):适合线材类产品,如电线、电缆、管道等。
// å…¬æ–¤ï¼ˆkg):用于衡量重量较大的材料或产品,例如润滑油、金属块等。
// å‡ï¼ˆL):液体类物资,如机油、冷却液等。
// å¥—:包含多个相关小部件组成的集合体,如工具套装、维修包等。
// å·ï¼šæŸäº›é•¿æ¡å½¢ä¸”难以精确计数的物品,如胶带、绝缘带等。
// ç»„:由若干个相同或不同类型的元件组成的功能单元,如一组电池、一套阀门组等。
            return render.renderSwitch(text, [
                { text: '个/ä»¶', value: '0' },
                { text: '米(m)', value: '1' },
                { text: '公斤(kg)', value: '2' },
                { text: '升(L)', value: '3' },
                { text: '套', value: '4' },
                { text: '卷', value: '5' },
                { text: '组', value: '6' },
            ])
        },
   },
   {
    title: '供应商',
    align:"center",
    dataIndex: 'supplier'
   },
   {
    title: '最低库存',
    align:"center",
    dataIndex: 'minStock'
   },
   {
    title: '安全库存',
    align:"center",
    dataIndex: 'safeStock'
   },
   {
    title: '库位',
    align:"center",
    dataIndex: 'location'
   },
   {
    title: '当前库存',
    align:"center",
    dataIndex: 'currentStock'
   },
   {
    title: '冻结库存',
    align:"center",
    dataIndex: 'frozenStock'
   },
   {
    title: '备注',
    align:"center",
    dataIndex: 'remark'
   },
   {
    title: '状态',
    align:"center",
    dataIndex: 'status',
    customRender: ({ text }) => {
      // '可用', '冻结', '报废'
            return render.renderSwitch(text, [
                { text: '可用', value: '0' },
                { text: '冻结', value: '1' },
                { text: '报废', value: '2' },
            ])
        },
   },
];
//查询数据
export const searchFormSchema: FormSchema[] = [
    {
      label: "零件编号",
      field: 'partNumber',
      component: 'Input',
      colProps: {span: 6},
     },
    {
      label: "零件名称",
      field: 'partName',
      component: 'Input',
      colProps: {span: 6},
     },
];
//表单数据
export const formSchema: FormSchema[] = [
  {
    label: '零件编号',
    field: 'partNumber',
    component: 'Input',
    dynamicRules: ({model,schema}) => {
          return [
                 { required: true, message: '请输入零件编号!'},
                 {...rules.duplicateCheckRule('dry_spare_parts', 'part_number',model,schema)[0]},
          ];
     },
  },
  {
    label: '零件名称',
    field: 'partName',
    component: 'Input',
    dynamicRules: ({}) => {
          return [
                 { required: true, message: '请输入零件名称!'},
          ];
     },
  },
  {
    label: '分类',
    field: 'category',
    component: 'Select',
    componentProps:{
      options: [
        { label: '机械类', value: '0' },
        { label: '电气类', value: '1' },
        { label: '液压类', value: '2' },
        { label: '气动类', value: '3' },
        { label: '电子类', value: '4' },
      ]
     },
    dynamicRules: ({}) => {
          return [
            { required: true, message: '请输入分类!'},
          ];
     },
  },
  {
    label: '规格型号',
    field: 'specModel',
    component: 'Input',
  },
  {
    label: '单位',
    field: 'unit',
    component: 'Select',
    componentProps:{
        options: [
          { label: '个/ä»¶', value: '0' },
          { label: '米(m)', value: '1' },
          { label: '公斤(kg)', value: '2' },
          { label: '升(L)', value: '3' },
          { label: '套', value: '4' },
          { label: '卷', value: '5' },
          { label: '组', value: '6' },
        ]
     },
    dynamicRules: ({}) => {
          return [
                 { required: true, message: '请输入单位!'},
          ];
     },
  },
  {
    label: '供应商',
    field: 'supplier',
    component: 'Input',
  },
  {
    label: '最低库存',
    field: 'minStock',
    component: 'InputNumber',
  },
  {
    label: '安全库存',
    field: 'safeStock',
    component: 'InputNumber',
  },
  {
    label: '库位',
    field: 'location',
    component: 'Input',
  },
  {
    label: '当前库存',
    field: 'currentStock',
    component: 'InputNumber',
    dynamicRules: ({}) => {
          return [
                 { required: true, message: '请输入当前库存!'},
          ];
     },
  },
  {
    label: '冻结库存',
    field: 'frozenStock',
    component: 'InputNumber',
  },
  {
    label: '备注',
    field: 'remark',
    component: 'InputTextArea',
  },
  {
    label: '状态',
    field: 'status',
    component: 'Select',
    defaultValue: '0',
    componentProps:{
        options: [
          { label: '可用', value: '0' },
          { label: '冻结', value: '1' },
          { label: '报废', value: '2' },
        ]
     },
    dynamicRules: ({}) => {
          return [
                 { required: true, message: '请输入状态!'},
          ];
     },
  },
    // TODO ä¸»é”®éšè—å­—段,目前写死为ID
    {
      label: '',
      field: 'id',
      component: 'Input',
      show: false
    },
];
/**
* æµç¨‹è¡¨å•调用这个方法获取formSchema
* @param param
*/
export function getBpmFormSchema(_formData): FormSchema[]{
  // é»˜è®¤å’ŒåŽŸå§‹è¡¨å•ä¿æŒä¸€è‡´ å¦‚果流程中配置了权限数据,这里需要单独处理formSchema
  return formSchema;
}
src/views/dry/spareParts/DrySparePartsList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,197 @@
<template>
  <div>
    <!--引用表格-->
   <BasicTable @register="registerTable" :rowSelection="rowSelection">
     <!--插槽:table标题-->
      <template #tableTitle>
          <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> æ–°å¢ž</a-button>
          <a-button type="primary" @click="handleStockIn" preIcon="ant-design:download-outlined"> å…¥åº“</a-button>
          <a-button type="primary" @click="handleStockOut" preIcon="ant-design:upload-outlined"> å‡ºåº“</a-button>
          <a-button  type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> å¯¼å‡º</a-button>
          <j-upload-button  type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
          <a-dropdown v-if="selectedRowKeys.length > 0">
              <template #overlay>
                <a-menu>
                  <a-menu-item key="1" @click="batchHandleDelete">
                    <Icon icon="ant-design:delete-outlined"></Icon>
                    åˆ é™¤
                  </a-menu-item>
                </a-menu>
              </template>
              <a-button>批量操作
                <Icon icon="mdi:chevron-down"></Icon>
              </a-button>
        </a-dropdown>
      </template>
       <!--操作栏-->
      <template #action="{ record }">
        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
      </template>
      <!--字段回显插槽-->
      <template #htmlSlot="{text}">
         <div v-html="text"></div>
      </template>
      <template #fileSlot="{text}">
         <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
         <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
      </template>
    </BasicTable>
    <!-- è¡¨å•区域 -->
    <DrySparePartsModal @register="registerModal" @success="handleSuccess"></DrySparePartsModal>
    <DrySpareStockLogModal @register="registerStockLogModal" @success="handleSuccess"></DrySpareStockLogModal>
  </div>
</template>
<script lang="ts" name="dry-drySpareParts" setup>
  import {ref, computed, unref} from 'vue';
  import {BasicTable, useTable, TableAction} from '/@/components/Table';
  import {useModal} from '/@/components/Modal';
  import { useListPage } from '/@/hooks/system/useListPage'
  import DrySparePartsModal from './components/DrySparePartsModal.vue'
  import DrySpareStockLogModal from './components/DrySpareStockLogModal.vue'
  import {columns, searchFormSchema} from './DrySpareParts.data';
  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './DrySpareParts.api';
  import { downloadFile } from '/@/utils/common/renderUtils';
  const checkedKeys = ref<Array<string | number>>([]);
  //注册model
  const [registerModal, {openModal}] = useModal();
  const [registerStockLogModal, {openModal: openStockLogModal}] = useModal();
  //注册table数据
  const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
      tableProps:{
           title: '备品备件',
           api: list,
           columns,
           canResize:false,
           formConfig: {
              //labelWidth: 120,
              schemas: searchFormSchema,
              autoSubmitOnEnter:true,
              showAdvancedButton:true,
              fieldMapToNumber: [
              ],
              fieldMapToTime: [
              ],
            },
           actionColumn: {
               width: 120,
               fixed:'right'
            },
      },
       exportConfig: {
            name:"备品备件",
            url: getExportUrl,
          },
          importConfig: {
            url: getImportUrl,
            success: handleSuccess
          },
  })
  const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
   /**
    * æ–°å¢žäº‹ä»¶
    */
  function handleAdd() {
     openModal(true, {
       isUpdate: false,
       showFooter: true,
     });
  }
  /**
   * å…¥åº“事件
   */
  function handleStockIn() {
    openStockLogModal(true, {
      isUpdate: false,
      showFooter: true,
      stockType: 'in'
    });
  }
  /**
   * å‡ºåº“事件
   */
  function handleStockOut() {
    openStockLogModal(true, {
      isUpdate: false,
      showFooter: true,
      stockType: 'out'
    });
  }
   /**
    * ç¼–辑事件
    */
  function handleEdit(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: true,
     });
   }
   /**
    * è¯¦æƒ…
   */
  function handleDetail(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: false,
     });
   }
   /**
    * åˆ é™¤äº‹ä»¶
    */
  async function handleDelete(record) {
     await deleteOne({id: record.id}, handleSuccess);
   }
   /**
    * æ‰¹é‡åˆ é™¤äº‹ä»¶
    */
  async function batchHandleDelete() {
     await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
   }
   /**
    * æˆåŠŸå›žè°ƒ
    */
  function handleSuccess() {
      (selectedRowKeys.value = []) && reload();
   }
   /**
      * æ“ä½œæ 
      */
  function getTableAction(record){
       return [
         {
           label: '编辑',
           onClick: handleEdit.bind(null, record),
         }
       ]
   }
     /**
        * ä¸‹æ‹‰æ“ä½œæ 
        */
  function getDropDownAction(record){
       return [
         {
           label: '详情',
           onClick: handleDetail.bind(null, record),
         }, {
           label: '删除',
           popConfirm: {
             title: '是否确认删除',
             confirm: handleDelete.bind(null, record),
           }
         }
       ]
   }
</script>
<style scoped>
</style>
src/views/dry/spareParts/DrySpareParts_menu_insert.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
-- æ³¨æ„ï¼šè¯¥é¡µé¢å¯¹åº”的前台目录为views/dry文件夹下
-- å¦‚果你想更改到其他目录,请修改sql中component字段对应的值
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('2025072308576550150', NULL, '备品备件', '/dry/drySparePartsList', 'dry/spareParts/DrySparePartsList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0);
-- æƒé™æŽ§åˆ¶sql
-- æ–°å¢ž
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550151', '2025072308576550150', '添加备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
-- ç¼–辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550152', '2025072308576550150', '编辑备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
-- åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550153', '2025072308576550150', '删除备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
-- æ‰¹é‡åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550154', '2025072308576550150', '批量删除备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å‡ºexcel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550155', '2025072308576550150', '导出excel_备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å…¥excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('2025072308576550156', '2025072308576550150', '导入excel_备品备件', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_parts:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:15', NULL, NULL, 0, 0, '1', 0);
src/views/dry/spareParts/DrySpareStockLog.api.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,85 @@
import {defHttp} from '/@/utils/http/axios';
import {addStock, reduceStock} from './DrySpareParts.api';
import { useMessage } from "/@/hooks/web/useMessage";
const { createConfirm } = useMessage();
enum Api {
  list = '/dry/drySpareStockLog/list',
  save='/dry/drySpareStockLog/add',
  edit='/dry/drySpareStockLog/edit',
  deleteOne = '/dry/drySpareStockLog/delete',
  deleteBatch = '/dry/drySpareStockLog/deleteBatch',
  importExcel = '/dry/drySpareStockLog/importExcel',
  exportXls = '/dry/drySpareStockLog/exportXls',
  generateStockNo = '/dry/drySpareStockLog/generateStockNo',
}
/**
 * å¯¼å‡ºapi
 * @param params
 */
export const getExportUrl = Api.exportXls;
/**
 * å¯¼å…¥api
 */
export const getImportUrl = Api.importExcel;
/**
 * åˆ—表接口
 * @param params
 */
export const list = (params) => {
  if (params.orderNumber) {
    return defHttp.get({url: Api.list, params: { ...params, relatedOrder: params.orderNumber }});
  } else {
    return defHttp.get({url: Api.list, params});
  }
};
/**
 * åˆ é™¤å•个
 */
export const deleteOne = (params,handleSuccess) => {
  return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
    handleSuccess();
  });
}
/**
 * æ‰¹é‡åˆ é™¤
 * @param params
 */
export const batchDelete = (params, handleSuccess) => {
  createConfirm({
    iconType: 'warning',
    title: '确认删除',
    content: '是否删除选中数据',
    okText: '确认',
    cancelText: '取消',
    onOk: () => {
      return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
        handleSuccess();
      });
    }
  });
}
/**
 * ä¿å­˜æˆ–者更新
 * @param params
 */
export const saveOrUpdate = (params, isUpdate) => {
  let url = isUpdate ? Api.edit : Api.save;
  // æ ¹æ®æ“ä½œç±»åž‹æ›´æ–°åº“å­˜
  // if (params.operationType === '0') { // å…¥åº“
  //   // è°ƒç”¨å¤‡å“å¤‡ä»¶çš„æ›´æ–°æŽ¥å£ï¼Œå¢žåŠ åº“å­˜
  //   addStock({partNumber: params.partNumber, quantity: params.quantity});
  // } else if (params.operationType === '1') { // å‡ºåº“
  //   // è°ƒç”¨å¤‡å“å¤‡ä»¶çš„æ›´æ–°æŽ¥å£ï¼Œå‡å°‘库存
  //   reduceStock({partNumber: params.partNumber, quantity: params.quantity});
  // }
  return defHttp.post({url: url, params});
}
/**
 * ç”Ÿæˆå‡ºå…¥åº“单号
 * @param type å•号类型,CK(出库)或 RK(入库)
 */
export const generateStockNo = (type) => defHttp.get({url: Api.generateStockNo, params: {type}},{ successMessageMode: 'none' });
src/views/dry/spareParts/DrySpareStockLog.data.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,206 @@
import { BasicColumn } from '/@/components/Table'
import { FormSchema } from '/@/components/Table'
//列表数据
export const columns: BasicColumn[] = [
    {
        title: '操作编号',
        align: 'center',
        dataIndex: 'operationNumber',
    },
    {
        title: '零件编号',
        align: 'center',
        dataIndex: 'partNumber_dictText',
    },
    {
        title: '操作类型',
        align: 'center',
        dataIndex: 'operationType',
        customRender: ({ text }) => {
            // '入库', '出库', '调拨', '报废'
            const options = {
                '0': '入库',
                '1': '出库',
                '2': '调拨',
                '3': '报废',
            }
            return options[text] || text
        },
    },
    {
        title: '数量',
        align: 'center',
        dataIndex: 'quantity',
    },
    // {
    //     title: '操作时间',
    //     align: 'center',
    //     dataIndex: 'operationTime',
    //     customRender: ({ text }) => {
    //         return !text ? '' : text.length > 10 ? text.substr(0, 10) : text
    //     },
    // },
    // {
    //     title: '操作人',
    //     align: 'center',
    //     dataIndex: 'operator',
    // },
    // {
    //     title: '关联单号(如维修单号)',
    //     align: 'center',
    //     dataIndex: 'relatedOrder',
    // },
    // {
    //     title: '库位',
    //     align: 'center',
    //     dataIndex: 'location',
    // },
    {
        title: '备注',
        align: 'center',
        dataIndex: 'remark',
    },
]
//查询数据
export const searchFormSchema: FormSchema[] = [
    {
        label: '零件编号',
        field: 'partNumber',
        component: 'JDictSelectTag',
        componentProps: {
            dictCode: 'dry_spare_parts,part_name,part_number',
        },
        colProps: { span: 6 },
    },
    {
        label: '操作类型',
        field: 'operationType',
        component: 'JDictSelectTag',
        componentProps: {
            options: [
                { label: '入库', value: '0' },
                { label: '出库', value: '1' },
                { label: '调拨', value: '2' },
                { label: '报废', value: '3' },
            ],
        },
        colProps: { span: 6 },
    },
]
//表单数据
export const formSchema = (params): FormSchema[] => {
    const { isUpdate, stockType } = params
    return [
    {
      label: '出入库单号',
      field: 'operationNumber',
      component: 'Input',
      dynamicDisabled: ({}) => {
        return true
      },
      dynamicRules: ({}) => {
        return [
          { required: !isUpdate, message: '请输入出入库单号!' },
        ]
      },
    },
        {
            label: '零件编号',
            field: 'partNumber',
            component: 'JDictSelectTag',
            componentProps: {
                dictCode: 'dry_spare_parts,part_name,part_number',
            },
            dynamicRules: ({}) => {
                return [
                    { required: true, message: '请输入零件编号!' }, // å§‹ç»ˆå¿…å¡«
                ]
            },
        },
        {
            label: '操作类型',
            field: 'operationType',
            component: 'JDictSelectTag',
            defaultValue: stockType === 'in' ? '0' : stockType === 'out' ? '1' : undefined,
            componentProps: {
                options: [
                    { label: '入库', value: '0' },
                    { label: '出库', value: '1' },
                    { label: '调拨', value: '2' },
                    { label: '报废', value: '3' },
                ],
            },
            dynamicRules: ({}) => {
                return [
                    { required: true, message: '请输入操作类型!' }, // å§‹ç»ˆå¿…å¡«
                ]
            },
        },
        {
            label: '数量',
            field: 'quantity',
            component: 'Input',
            dynamicRules: ({}) => {
                return [
                    { required: true, message: '请输入数量!' }, // å§‹ç»ˆå¿…å¡«
                    { pattern: /^[0-9]*$/, message: '请输入数字!' },
                    {
                        validator: (_, value) => {
                            if (stockType === 'in' && parseFloat(value) <= 0) {
                                return Promise.reject('入库数量必须大于0')
                            }
                            if (stockType === 'out' && parseFloat(value) <= 0) {
                                return Promise.reject('出库数量必须大于0')
                            }
                            return Promise.resolve()
                        },
                        trigger: 'change',
                    },
                ]
            },
        },
        // {
        //     label: '操作时间',
        //     field: 'operationTime',
        //     component: 'DatePicker',
        // },
        // {
        //     label: '操作人',
        //     field: 'operator',
        //     component: 'Input',
        // },
        {
            label: '关联单号(如维修单号)',
            field: 'relatedOrder',
            component: 'Input',
      show: false,
        },
        // {
        //     label: '库位',
        //     field: 'location',
        //     component: 'Input',
        // },
        {
            label: '备注',
            field: 'remark',
            component: 'InputTextArea',
        },
        // TODO ä¸»é”®éšè—å­—段,目前写死为ID
        {
            label: '',
            field: 'id',
            component: 'Input',
            show: false,
        },
    ]
}
/**
 * æµç¨‹è¡¨å•调用这个方法获取formSchema
 * @param param
 */
export function getBpmFormSchema(_formData): FormSchema[] {
    // é»˜è®¤å’ŒåŽŸå§‹è¡¨å•ä¿æŒä¸€è‡´ å¦‚果流程中配置了权限数据,这里需要单独处理formSchema
  return formSchema(_formData);
}
src/views/dry/spareParts/DrySpareStockLogList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,170 @@
<template>
  <div>
    <!--引用表格-->
   <BasicTable @register="registerTable" :rowSelection="rowSelection">
     <!--插槽:table标题-->
      <template #tableTitle>
          <!-- <a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> æ–°å¢ž</a-button> -->
          <!-- <a-button  type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> å¯¼å‡º</a-button>
          <j-upload-button  type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button> -->
          <a-dropdown v-if="selectedRowKeys.length > 0">
              <template #overlay>
                <a-menu>
                  <a-menu-item key="1" @click="batchHandleDelete">
                    <Icon icon="ant-design:delete-outlined"></Icon>
                    åˆ é™¤
                  </a-menu-item>
                </a-menu>
              </template>
              <a-button>批量操作
                <Icon icon="mdi:chevron-down"></Icon>
              </a-button>
        </a-dropdown>
      </template>
       <!--操作栏-->
      <template #action="{ record }">
        <TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)"/>
      </template>
      <!--字段回显插槽-->
      <template #htmlSlot="{text}">
         <div v-html="text"></div>
      </template>
      <template #fileSlot="{text}">
         <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
         <a-button v-else :ghost="true" type="primary" preIcon="ant-design:download-outlined" size="small" @click="downloadFile(text)">下载</a-button>
      </template>
    </BasicTable>
    <!-- è¡¨å•区域 -->
    <DrySpareStockLogModal @register="registerModal" @success="handleSuccess"></DrySpareStockLogModal>
  </div>
</template>
<script lang="ts" name="dry-drySpareStockLog" setup>
  import {ref, computed, unref} from 'vue';
  import {BasicTable, useTable, TableAction} from '/@/components/Table';
  import {useModal} from '/@/components/Modal';
  import { useListPage } from '/@/hooks/system/useListPage'
  import DrySpareStockLogModal from './components/DrySpareStockLogModal.vue'
  import {columns, searchFormSchema} from './DrySpareStockLog.data';
  import {list, deleteOne, batchDelete, getImportUrl,getExportUrl} from './DrySpareStockLog.api';
  import { downloadFile } from '/@/utils/common/renderUtils';
  const checkedKeys = ref<Array<string | number>>([]);
  //注册model
  const [registerModal, {openModal}] = useModal();
  //注册table数据
  const { prefixCls,tableContext,onExportXls,onImportXls } = useListPage({
      tableProps:{
           title: '出入库记录表',
           api: list,
           columns,
           canResize:false,
           formConfig: {
              //labelWidth: 120,
              schemas: searchFormSchema,
              autoSubmitOnEnter:true,
              showAdvancedButton:true,
              fieldMapToNumber: [
              ],
              fieldMapToTime: [
              ],
            },
           actionColumn: {
               width: 120,
               fixed:'right'
            },
        showActionColumn: false
      },
       exportConfig: {
            name:"出入库记录表",
            url: getExportUrl,
          },
          importConfig: {
            url: getImportUrl,
            success: handleSuccess
          },
  })
  const [registerTable, {reload},{ rowSelection, selectedRowKeys }] = tableContext
   /**
    * æ–°å¢žäº‹ä»¶
    */
  function handleAdd() {
     openModal(true, {
       isUpdate: false,
       showFooter: true,
     });
  }
   /**
    * ç¼–辑事件
    */
  function handleEdit(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: true,
     });
   }
   /**
    * è¯¦æƒ…
   */
  function handleDetail(record: Recordable) {
     openModal(true, {
       record,
       isUpdate: true,
       showFooter: false,
     });
   }
   /**
    * åˆ é™¤äº‹ä»¶
    */
  async function handleDelete(record) {
     await deleteOne({id: record.id}, handleSuccess);
   }
   /**
    * æ‰¹é‡åˆ é™¤äº‹ä»¶
    */
  async function batchHandleDelete() {
     await batchDelete({ids: selectedRowKeys.value}, handleSuccess);
   }
   /**
    * æˆåŠŸå›žè°ƒ
    */
  function handleSuccess() {
      (selectedRowKeys.value = []) && reload();
   }
   /**
      * æ“ä½œæ 
      */
  function getTableAction(record){
       return [
         {
           label: '编辑',
           onClick: handleEdit.bind(null, record),
         }
       ]
   }
     /**
        * ä¸‹æ‹‰æ“ä½œæ 
        */
  function getDropDownAction(record){
       return [
         {
           label: '详情',
           onClick: handleDetail.bind(null, record),
         }, {
           label: '删除',
           popConfirm: {
             title: '是否确认删除',
             confirm: handleDelete.bind(null, record),
           }
         }
       ]
   }
</script>
<style scoped>
</style>
src/views/dry/spareParts/DrySpareStockLog_menu_insert.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
-- æ³¨æ„ï¼šè¯¥é¡µé¢å¯¹åº”的前台目录为views/dry文件夹下
-- å¦‚果你想更改到其他目录,请修改sql中component字段对应的值
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external)
VALUES ('202507230857430230', NULL, '出入库记录表', '/dry/drySpareStockLogList', 'dry/spareParts/DrySpareStockLogList', NULL, NULL, 0, NULL, '1', 0.00, 0, NULL, 1, 0, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0);
-- æƒé™æŽ§åˆ¶sql
-- æ–°å¢ž
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430231', '202507230857430230', '添加出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:add', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
-- ç¼–辑
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430232', '202507230857430230', '编辑出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:edit', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
-- åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430233', '202507230857430230', '删除出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:delete', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
-- æ‰¹é‡åˆ é™¤
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430234', '202507230857430230', '批量删除出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:deleteBatch', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å‡ºexcel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430235', '202507230857430230', '导出excel_出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:exportXls', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
-- å¯¼å…¥excel
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external)
VALUES ('202507230857430236', '202507230857430230', '导入excel_出入库记录表', NULL, NULL, 0, NULL, NULL, 2, 'dry:dry_spare_stock_log:importExcel', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2025-07-23 08:57:23', NULL, NULL, 0, 0, '1', 0);
src/views/dry/spareParts/components/DrySparePartsForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
<template>
    <div style="min-height: 400px">
        <BasicForm @register="registerForm"></BasicForm>
        <div style="width: 100%;text-align: center" v-if="!formDisabled">
            <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 äº¤</a-button>
        </div>
    </div>
</template>
<script lang="ts">
    import {BasicForm, useForm} from '/@/components/Form/index';
    import {computed, defineComponent} from 'vue';
    import {defHttp} from '/@/utils/http/axios';
    import { propTypes } from '/@/utils/propTypes';
    import {getBpmFormSchema} from '../DrySpareParts.data';
    import {saveOrUpdate} from '../DrySpareParts.api';
    export default defineComponent({
        name: "DrySparePartsForm",
        components:{
            BasicForm
        },
        props:{
            formData: propTypes.object.def({}),
            formBpm: propTypes.bool.def(true),
        },
        setup(props){
            const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
                labelWidth: 150,
                schemas: getBpmFormSchema(props.formData),
                showActionButtonGroup: false,
                baseColProps: {span: 24}
            });
            const formDisabled = computed(()=>{
                if(props.formData.disabled === false){
                    return false;
                }
                return true;
            });
            let formData = {};
            const queryByIdUrl = '/dry/drySpareParts/queryById';
            async function initFormData(){
                let params = {id: props.formData.dataId};
                const data = await defHttp.get({url: queryByIdUrl, params});
                formData = {...data}
                //设置表单的值
                await setFieldsValue(formData);
                //默认是禁用
                await setProps({disabled: formDisabled.value})
            }
            async function submitForm() {
                let data = getFieldsValue();
                let params = Object.assign({}, formData, data);
                console.log('表单数据', params)
                await saveOrUpdate(params, true)
            }
            initFormData();
            return {
                registerForm,
                formDisabled,
                submitForm,
            }
        }
    });
</script>
src/views/dry/spareParts/components/DrySparePartsModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
<template>
  <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
      <BasicForm @register="registerForm"/>
  </BasicModal>
</template>
<script lang="ts" setup>
    import {ref, computed, unref} from 'vue';
    import {BasicModal, useModalInner} from '/@/components/Modal';
    import {BasicForm, useForm} from '/@/components/Form/index';
    import {formSchema} from '../DrySpareParts.data';
    import {saveOrUpdate} from '../DrySpareParts.api';
    // Emits声明
    const emit = defineEmits(['register','success']);
    const isUpdate = ref(true);
    //表单配置
    const [registerForm, {setProps,resetFields, setFieldsValue, validate}] = useForm({
        //labelWidth: 150,
        schemas: formSchema,
        showActionButtonGroup: false,
        baseColProps: {span: 24}
    });
    //表单赋值
    const [registerModal, {setModalProps, closeModal}] = useModalInner(async (data) => {
        //重置表单
        await resetFields();
        setModalProps({confirmLoading: false,showCancelBtn:!!data?.showFooter,showOkBtn:!!data?.showFooter});
        isUpdate.value = !!data?.isUpdate;
        if (unref(isUpdate)) {
            //表单赋值
            await setFieldsValue({
                ...data.record,
            });
        }
        // éšè—åº•部时禁用整个表单
       setProps({ disabled: !data?.showFooter })
    });
    //设置标题
    const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'));
    //表单提交事件
    async function handleSubmit(v) {
        try {
            let values = await validate();
            setModalProps({confirmLoading: true});
            //提交表单
            await saveOrUpdate(values, isUpdate.value);
            //关闭弹窗
            closeModal();
            //刷新列表
            emit('success');
        } finally {
            setModalProps({confirmLoading: false});
        }
    }
</script>
<style lang="less" scoped>
    /** æ—¶é—´å’Œæ•°å­—输入框样式 */
  :deep(.ant-input-number){
        width: 100%
    }
    :deep(.ant-calendar-picker){
        width: 100%
    }
</style>
src/views/dry/spareParts/components/DrySpareStockLogForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,70 @@
<template>
    <div style="min-height: 400px">
        <BasicForm @register="registerForm" />
        <div style="width: 100%; text-align: center" v-if="!formDisabled">
            <a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 äº¤</a-button>
        </div>
    </div>
</template>
<script lang="ts">
    import { BasicForm, useForm } from '/@/components/Form/index'
    import { computed, defineComponent } from 'vue'
    import { defHttp } from '/@/utils/http/axios'
    import { propTypes } from '/@/utils/propTypes'
    import { getBpmFormSchema } from '../DrySpareStockLog.data'
    import { saveOrUpdate } from '../DrySpareStockLog.api'
    export default defineComponent({
        name: 'DrySpareStockLogForm',
        components: {
            BasicForm,
        },
        props: {
            formData: propTypes.object.def({}),
            formBpm: propTypes.bool.def(true),
        },
        setup(props) {
            const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
                labelWidth: 150,
                schemas: getBpmFormSchema(props.formData),
                showActionButtonGroup: false,
                baseColProps: { span: 24 },
            })
            const formDisabled = computed(() => {
                if (props.formData.disabled === false) {
                    return false
                }
                return true
            })
            let formData = {}
            const queryByIdUrl = '/dry/drySpareStockLog/queryById'
            async function initFormData() {
                let params = { id: props.formData.dataId }
                const data = await defHttp.get({ url: queryByIdUrl, params })
                formData = { ...data }
                //设置表单的值
                await setFieldsValue(formData)
                //默认是禁用
                await setProps({ disabled: formDisabled.value })
            }
            async function submitForm() {
                let data = getFieldsValue()
                let params = Object.assign({}, formData, data)
                console.log('表单数据', params)
                await saveOrUpdate(params, true)
            }
            initFormData()
            return {
                registerForm,
                formDisabled,
                submitForm,
            }
        },
    })
</script>
src/views/dry/spareParts/components/DrySpareStockLogModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
<template>
    <BasicModal v-bind="$attrs" @register="registerModal" destroyOnClose :title="title" :width="800" @ok="handleSubmit">
        <BasicForm @register="registerForm" />
    </BasicModal>
</template>
<script lang="ts" setup>
    import { ref, computed, unref, reactive, nextTick } from 'vue'
    import { BasicModal, useModalInner } from '/@/components/Modal'
    import { BasicForm, useForm } from '/@/components/Form/index'
    import { formSchema } from '../DrySpareStockLog.data'
    import { formatToDate } from '/@/utils/dateUtil'
    import { saveOrUpdate } from '../DrySpareStockLog.api'
    import { generateStockNo } from '../DrySpareStockLog.api'
    // Emits声明
    const emit = defineEmits(['register', 'success'])
    const isUpdate = ref(true)
  const stockType = ref('in')
  const relatedOrder = ref('');
    const modalParams = reactive({
    isUpdate: isUpdate,
    stockType: stockType,
  })
    //表单配置
    const [registerForm, { setProps, resetFields, setFieldsValue, validate }] = useForm({
        //labelWidth: 150,
        schemas: formSchema(unref(modalParams)),
        showActionButtonGroup: false,
        baseColProps: { span: 24 },
    })
    //表单赋值
    const [registerModal, { setModalProps, closeModal }] = useModalInner(async (data) => {
        //重置表单
        await resetFields()
        Object.assign(modalParams, data.record || {});
        isUpdate.value = !!data?.isUpdate
    stockType.value = data.stockType
    relatedOrder.value = data.relatedOrder;
    // ç¡®ä¿åœ¨DOM更新后执行,避免useModal实例未定义的问题
    await nextTick(async () => {
          setModalProps({ confirmLoading: false, showCancelBtn: !!data?.showFooter, showOkBtn: !!data?.showFooter})
          if (unref(isUpdate)) {
              //表单赋值
              await setFieldsValue({
                  operationTime: data.record.operationTime ? formatToDate(data.record.operationTime, 'YYYY-MM-DD') : null,
                  ...data.record,
              })
          }
      if (!unref(isUpdate)) {
        // æ–°å¢žæ—¶ç”Ÿæˆå‡ºå…¥åº“单号
        const type = stockType.value === 'in' ? 'RK' : 'CK';
        const res = await generateStockNo(type);
        await setFieldsValue({ operationNumber: res, operationType: stockType.value === 'in' ? '0' : '1', relatedOrder: unref(relatedOrder) });
      }
          // éšè—åº•部时禁用整个表单
          setProps({ disabled: !data?.showFooter })
    })
    })
    //设置标题
    const title = computed(() => (!unref(isUpdate) ? '新增' : '编辑'))
    //表单提交事件
    async function handleSubmit(v) {
        try {
            let values = await validate()
            setModalProps({ confirmLoading: true })
      values.relatedOrder = unref(relatedOrder);
            //提交表单
            await saveOrUpdate(values, unref(isUpdate))
            //关闭弹窗
            closeModal()
            //刷新列表
            emit('success')
        } finally {
            setModalProps({ confirmLoading: false })
        }
    }
</script>
<style lang="less" scoped>
    /** æ—¶é—´å’Œæ•°å­—输入框样式 */
    :deep(.ant-input-number) {
        width: 100%;
    }
    :deep(.ant-calendar-picker) {
        width: 100%;
    }
</style>