兰宝车间质量管理系统-前端
baoshiwei
2025-03-12 9d9cb926d2fdd4ba6db1daffdbc6c877a626d813
dev-init
已添加31个文件
已删除1个文件
已修改12个文件
5698 ■■■■■ 文件已修改
.env.development 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintignore 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.eslintrc.cjs 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
eslint.config.js 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
index.html 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon.ico 补丁 | 查看 | 原始文档 | blame | 历史
public/favicon_bak.ico 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/batch/index.ts 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/batch/types.ts 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/device/index.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/device/types.ts 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/retestResult/index.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/retestResult/types.ts 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensor/index.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensor/types.ts 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensorResult/index.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensorResult/types.ts 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensorRetest/index.ts 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/sensorRetest/types.ts 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/testResult/index.ts 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/qms/testResult/types.ts 201 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/icons/svg/batch-detail.svg 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo/logo.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/logo/logo_bak.png 补丁 | 查看 | 原始文档 | blame | 历史
src/layout/components/Sidebar/Logo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/index.vue 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login.vue 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/batch/index.vue 299 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/device/index.vue 280 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/retestResult/index.vue 461 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/sensor/index.vue 451 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/sensorResult/index.vue 274 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/sensorRetest/index.vue 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/testResult/index.vue 313 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/testResult/index1.vue 339 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/testResult/index2.vue 372 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/trend/index.vue 467 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qms/trend/index1.vue 349 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/register.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
tsconfig.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.ts 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite/plugins/i18n.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -1,5 +1,5 @@
# é¡µé¢æ ‡é¢˜
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
VITE_APP_TITLE = å…°å®è½¦é—´è´¨é‡ç®¡ç†ç³»ç»Ÿ
# å¼€å‘环境配置
VITE_APP_ENV = 'development'
@@ -19,7 +19,7 @@
VITE_APP_PORT = 80
# æŽ¥å£åŠ å¯†åŠŸèƒ½å¼€å…³(如需关闭 åŽç«¯ä¹Ÿå¿…须对应关闭)
VITE_APP_ENCRYPT = true
VITE_APP_ENCRYPT = false
# æŽ¥å£åŠ å¯†ä¼ è¾“ RSA å…¬é’¥ä¸ŽåŽç«¯è§£å¯†ç§é’¥å¯¹åº” å¦‚更换需前后端一同更换
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
# æŽ¥å£å“åº”解密 RSA ç§é’¥ä¸ŽåŽç«¯åŠ å¯†å…¬é’¥å¯¹åº” å¦‚更换需前后端一同更换
.env.production
@@ -1,5 +1,5 @@
# é¡µé¢æ ‡é¢˜
VITE_APP_TITLE = RuoYi-Vue-Plus多租户管理系统
VITE_APP_TITLE = å…°å®è½¦é—´è´¨é‡ç®¡ç†ç³»ç»Ÿ
# ç”Ÿäº§çŽ¯å¢ƒé…ç½®
VITE_APP_ENV = 'production'
@@ -22,7 +22,7 @@
VITE_APP_PORT = 80
# æŽ¥å£åŠ å¯†åŠŸèƒ½å¼€å…³(如需关闭 åŽç«¯ä¹Ÿå¿…须对应关闭)
VITE_APP_ENCRYPT = true
VITE_APP_ENCRYPT = false
# æŽ¥å£åŠ å¯†ä¼ è¾“ RSA å…¬é’¥ä¸ŽåŽç«¯è§£å¯†ç§é’¥å¯¹åº” å¦‚更换需前后端一同更换
VITE_APP_RSA_PUBLIC_KEY = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
# æŽ¥å£å“åº”解密 RSA ç§é’¥ä¸ŽåŽç«¯åŠ å¯†å…¬é’¥å¯¹åº” å¦‚更换需前后端一同更换
.eslintignore
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
*.sh
node_modules
*.md
*.woff
*.ttf
.vscode
.idea
dist
/public
/docs
.husky
.local
/bin
.eslintrc.cjs
prettier.config.js
src/assets
tailwind.config.js
.eslintrc.cjs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
module.exports = {
  env: {
    browser: true,
    node: true,
    es6: true
  },
  parser: 'vue-eslint-parser',
  extends: [
    'plugin:vue/vue3-recommended',
    './.eslintrc-auto-import.json',
    'plugin:@typescript-eslint/recommended',
    'prettier',
    'plugin:prettier/recommended'
  ],
  parserOptions: {
    ecmaVersion: '2020',
    sourceType: 'module',
    project: './tsconfig.*?.json',
    parser: '@typescript-eslint/parser'
  },
  plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'],
  rules: {
    '@typescript-eslint/no-empty-function': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
    '@typescript-eslint/no-unused-vars': 'off',
    '@typescript-eslint/no-this-alias': 'off',
    // vue
    'vue/multi-word-component-names': 'off',
    'vue/valid-define-props': 'off',
    'vue/no-v-model-argument': 'off',
    'prefer-rest-params': 'off',
    // prettier
    'prettier/prettier': 'error',
    '@typescript-eslint/ban-types': [
      'error',
      {
        // å…³é—­ç©ºç±»åž‹æ£€æŸ¥ {}
        extendDefaults: true,
        types: {
          '{}': false,
          Function: false
        }
      }
    ]
  },
  globals: {
    DialogOption: 'readonly',
    OptionType: 'readonly'
  }
};
eslint.config.js
ÎļþÒÑɾ³ý
index.html
@@ -6,7 +6,7 @@
    <meta name="renderer" content="webkit" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    <link rel="icon" href="/favicon.ico" />
    <title>RuoYi-Vue-Plus多租户管理系统</title>
    <title>兰宝车间质量管理系统</title>
    <!--[if lt IE 11
      ]><script>
        window.location.href = '/html/ie.html';
package.json
@@ -1,8 +1,8 @@
{
  "$schema": "https://json.schemastore.org/tsconfig",
  "name": "ruoyi-vue-plus",
  "name": "lb-qms",
  "version": "5.3.0",
  "description": "RuoYi-Vue-Plus多租户管理系统",
  "description": "兰宝车间质量管理系统",
  "author": "LionLi",
  "license": "MIT",
  "type": "module",
public/favicon.ico

public/favicon_bak.ico
src/api/qms/batch/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { BatchVO, BatchForm, BatchQuery } from '@/api/qms/batch/types';
/**
 * æŸ¥è¯¢æ‰¹æ¬¡ç®¡ç†åˆ—表
 * @param query
 * @returns {*}
 */
export const listBatch = (query?: BatchQuery): AxiosPromise<BatchVO[]> => {
  return request({
    url: '/qms/batch/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢æ‰€æœ‰äº§å“åž‹å·
 * @param query
 */
export const listProdModels = () => {
  return request({
    url: '/qms/batch/distinctProductModels',
    method: 'get'
  });
};
/**
 * æŸ¥è¯¢æ‰¹æ¬¡ç®¡ç†è¯¦ç»†
 * @param id
 */
export const getBatch = (id: string | number): AxiosPromise<BatchVO> => {
  return request({
    url: '/qms/batch/' + id,
    method: 'get'
  });
};
/**
 * æ–°å¢žæ‰¹æ¬¡ç®¡ç†
 * @param data
 */
export const addBatch = (data: BatchForm) => {
  return request({
    url: '/qms/batch',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹æ‰¹æ¬¡ç®¡ç†
 * @param data
 */
export const updateBatch = (data: BatchForm) => {
  return request({
    url: '/qms/batch',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤æ‰¹æ¬¡ç®¡ç†
 * @param id
 */
export const delBatch = (id: string | number | Array<string | number>) => {
  return request({
    url: '/qms/batch/' + id,
    method: 'delete'
  });
};
src/api/qms/batch/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
export interface BatchVO {
  /**
   *
   */
  id: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode: string;
  /**
   * äº§å“åž‹å·
   */
  prodModel: string;
  /**
   * ç”¨æˆ·ç¼–号
   */
  userId: string | number;
  /**
   * è®¾å¤‡å·
   */
  deviceCode: string;
  /**
   * æ•°é‡
   */
  num: number;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface BatchForm extends BaseEntity {
  /**
   *
   */
  id?: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * äº§å“åž‹å·
   */
  prodModel?: string;
  /**
   * ç”¨æˆ·ç¼–号
   */
  userId?: string | number;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * æ•°é‡
   */
  num?: number;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface BatchQuery extends PageQuery {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * äº§å“åž‹å·
   */
  prodModel?: string;
  /**
   * ç”¨æˆ·ç¼–号
   */
  userId?: string | number;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * æ•°é‡
   */
  num?: number;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/device/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { DeviceVO, DeviceForm, DeviceQuery } from '@/api/qms/device/types';
/**
 * æŸ¥è¯¢æµ‹è¯•仪列表
 * @param query
 * @returns {*}
 */
export const listDevice = (query?: DeviceQuery): AxiosPromise<DeviceVO[]> => {
  return request({
    url: '/qms/device/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢æµ‹è¯•仪详细
 * @param id
 */
export const getDevice = (id: string | number): AxiosPromise<DeviceVO> => {
  return request({
    url: '/qms/device/' + id,
    method: 'get'
  });
};
/**
 * æ–°å¢žæµ‹è¯•仪
 * @param data
 */
export const addDevice = (data: DeviceForm) => {
  return request({
    url: '/qms/device',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹æµ‹è¯•仪
 * @param data
 */
export const updateDevice = (data: DeviceForm) => {
  return request({
    url: '/qms/device',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤æµ‹è¯•仪
 * @param id
 */
export const delDevice = (id: string | number | Array<string | number>) => {
  return request({
    url: '/qms/device/' + id,
    method: 'delete'
  });
};
src/api/qms/device/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,111 @@
export interface DeviceVO {
  /**
   *
   */
  id: string | number;
  /**
   * è®¾å¤‡ç±»åž‹
   */
  deviceType: string;
  /**
   * è®¾å¤‡ç¼–号
   */
  deviceCode: string;
  /**
   * æ‰€åœ¨ç»„
   */
  deviceGroup: string;
  /**
   * æ‰€åœ¨éƒ¨é—¨
   */
  deviceDept: string;
  /**
   * æ‰€åœ¨å·¥ä½
   */
  deviceStation: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface DeviceForm extends BaseEntity {
  /**
   *
   */
  id?: string | number;
  /**
   * è®¾å¤‡ç±»åž‹
   */
  deviceType?: string;
  /**
   * è®¾å¤‡ç¼–号
   */
  deviceCode?: string;
  /**
   * æ‰€åœ¨ç»„
   */
  deviceGroup?: string;
  /**
   * æ‰€åœ¨éƒ¨é—¨
   */
  deviceDept?: string;
  /**
   * æ‰€åœ¨å·¥ä½
   */
  deviceStation?: string;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface DeviceQuery extends PageQuery {
  /**
   * è®¾å¤‡ç±»åž‹
   */
  deviceType?: string;
  /**
   * è®¾å¤‡ç¼–号
   */
  deviceCode?: string;
  /**
   * æ‰€åœ¨ç»„
   */
  deviceGroup?: string;
  /**
   * æ‰€åœ¨éƒ¨é—¨
   */
  deviceDept?: string;
  /**
   * æ‰€åœ¨å·¥ä½
   */
  deviceStation?: string;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/retestResult/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { RetestResultVO, RetestResultForm, RetestResultQuery } from '@/api/qms/retestResult/types';
/**
 * æŸ¥è¯¢å¤æµ‹è®°å½•列表
 * @param query
 * @returns {*}
 */
export const listRetestResult = (query?: RetestResultQuery): AxiosPromise<RetestResultVO[]> => {
  return request({
    url: '/qms/retestResult/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢å¤æµ‹è®°å½•详细
 * @param batchCode
 */
export const getRetestResult = (batchCode: string | number): AxiosPromise<RetestResultVO> => {
  return request({
    url: '/qms/retestResult/' + batchCode,
    method: 'get'
  });
};
/**
 * æ–°å¢žå¤æµ‹è®°å½•
 * @param data
 */
export const addRetestResult = (data: RetestResultForm) => {
  return request({
    url: '/qms/retestResult',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹å¤æµ‹è®°å½•
 * @param data
 */
export const updateRetestResult = (data: RetestResultForm) => {
  return request({
    url: '/qms/retestResult',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤å¤æµ‹è®°å½•
 * @param batchCode
 */
export const delRetestResult = (batchCode: string | number | Array<string | number>) => {
  return request({
    url: '/qms/retestResult/' + batchCode,
    method: 'delete'
  });
};
src/api/qms/retestResult/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
export interface RetestResultVO {
  /**
   *
   */
  id: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode: string;
  /**
   * æµ‹è¯•序号
   */
  testNum: string;
  /**
   * æµ‹è¯•项目
   */
  testItem: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName: string;
  /**
   * çŽ¯å¢ƒæ¸©åº¦
   */
  temp: string;
  /**
   * å®žé™…电压
   */
  voltage: number;
  /**
   * å®žé™…电流
   */
  loadCurrent: number;
  /**
   * æ ‡å‡†è·ç¦»
   */
  stdDistance: number;
  /**
   * æ„Ÿåº”物
   */
  inductor: string;
  /**
   * è¾“出引脚(黑;白)
   */
  output: string;
  /**
   * æµ‹è¯•数据
   */
  testValue: number;
  /**
   * åˆ¤æ–­æ¡ä»¶ï¼ˆæœ€å°å€¼<=真实值<=最大值 ï¼‰
   */
  judgeDetail: string;
  /**
   * æµ‹è¯•结果(OK; NG)
   */
  testResult: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface RetestResultForm extends BaseEntity {
  /**
   *
   */
  id?: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * æµ‹è¯•项目
   */
  testItem?: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum?: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName?: string;
  /**
   * çŽ¯å¢ƒæ¸©åº¦
   */
  temp?: string;
  /**
   * å®žé™…电压
   */
  voltage?: number;
  /**
   * å®žé™…电流
   */
  loadCurrent?: number;
  /**
   * æ ‡å‡†è·ç¦»
   */
  stdDistance?: number;
  /**
   * æ„Ÿåº”物
   */
  inductor?: string;
  /**
   * è¾“出引脚(黑;白)
   */
  output?: string;
  /**
   * æµ‹è¯•数据
   */
  testValue?: number;
  /**
   * åˆ¤æ–­æ¡ä»¶ï¼ˆæœ€å°å€¼<=真实值<=最大值 ï¼‰
   */
  judgeDetail?: string;
  /**
   * æµ‹è¯•结果(OK; NG)
   */
  testResult?: string;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface RetestResultQuery extends PageQuery {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * æµ‹è¯•项目
   */
  testItem?: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum?: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName?: string;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/sensor/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { SensorVO, SensorForm, SensorQuery } from '@/api/qms/sensor/types';
/**
 * æŸ¥è¯¢ä¼ æ„Ÿå™¨åˆ—表
 * @param query
 * @returns {*}
 */
export const listSensor = (query?: SensorQuery): AxiosPromise<SensorVO[]> => {
  return request({
    url: '/qms/sensor/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢ä¼ æ„Ÿå™¨è¯¦ç»†
 * @param prodId
 */
export const getSensor = (prodId: string | number): AxiosPromise<SensorVO> => {
  return request({
    url: '/qms/sensor/' + prodId,
    method: 'get'
  });
};
/**
 * æ–°å¢žä¼ æ„Ÿå™¨
 * @param data
 */
export const addSensor = (data: SensorForm) => {
  return request({
    url: '/qms/sensor',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹ä¼ æ„Ÿå™¨
 * @param data
 */
export const updateSensor = (data: SensorForm) => {
  return request({
    url: '/qms/sensor',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤ä¼ æ„Ÿå™¨
 * @param prodId
 */
export const delSensor = (prodId: string | number | Array<string | number>) => {
  return request({
    url: '/qms/sensor/' + prodId,
    method: 'delete'
  });
};
src/api/qms/sensor/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,181 @@
export interface SensorVO {
  /**
   *
   */
  prodId: string | number;
  /**
   * äº§å“åž‹å·
   */
  prodModel: string;
  /**
   * äº§å“æ¡ç 
   */
  prodBarcode: string;
  /**
   * äº§å“å¤§ç±»
   */
  prodClass: string;
  /**
   * äº§å“å°ç±»
   */
  prodSubclass: string;
  /**
   * ä¾›ç”µç”µæºï¼ˆDC-直流;AC-交流)
   */
  supply: string;
  /**
   * ç”µåŽ‹é«˜å€¼
   */
  supplyHigh: number;
  /**
   * ç”µåދ䏭值
   */
  supplyMiddle: string | number;
  /**
   * ç”µåŽ‹ä½Žå€¼
   */
  supplyLow: number;
  /**
   * è´Ÿè½½ç”µæµ
   */
  loadCurrent: number;
  /**
   * å¼•线数量
   */
  wire: number;
  /**
   * è¾“出信号
   */
  outputSignal: string;
  /**
   * è¾“出类型
   */
  outputType: string;
  /**
   * è¾“出极性
   */
  outputPolarity: string;
  /**
   * æ„Ÿåº”距离
   */
  distance: number;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface SensorForm extends BaseEntity {
  /**
   *
   */
  prodId?: string | number;
  /**
   * äº§å“åž‹å·
   */
  prodModel?: string;
  /**
   * äº§å“æ¡ç 
   */
  prodBarcode?: string;
  /**
   * äº§å“å¤§ç±»
   */
  prodClass?: string;
  /**
   * äº§å“å°ç±»
   */
  prodSubclass?: string;
  /**
   * ä¾›ç”µç”µæºï¼ˆDC-直流;AC-交流)
   */
  supply?: string;
  /**
   * ç”µåŽ‹é«˜å€¼
   */
  supplyHigh?: number;
  /**
   * ç”µåދ䏭值
   */
  supplyMiddle?: string | number;
  /**
   * ç”µåŽ‹ä½Žå€¼
   */
  supplyLow?: number;
  /**
   * è´Ÿè½½ç”µæµ
   */
  loadCurrent?: number;
  /**
   * å¼•线数量
   */
  wire?: number;
  /**
   * è¾“出信号
   */
  outputSignal?: string;
  /**
   * è¾“出类型
   */
  outputType?: string;
  /**
   * è¾“出极性
   */
  outputPolarity?: string;
  /**
   * æ„Ÿåº”距离
   */
  distance?: number;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface SensorQuery extends PageQuery {
  /**
   * äº§å“åž‹å·
   */
  prodModel?: string;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/sensorResult/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { SensorResultVO, SensorResultForm, SensorResultQuery } from '@/api/qms/sensorResult/types';
/**
 * æŸ¥è¯¢æ‰¹æ¬¡æ˜Žç»†åˆ—表
 * @param query
 * @returns {*}
 */
export const listSensorResult = (query?: SensorResultQuery): AxiosPromise<SensorResultVO[]> => {
  return request({
    url: '/qms/sensorResult/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢æ‰¹æ¬¡æ˜Žç»†è¯¦ç»†
 * @param batchCode
 */
export const getSensorResult = (batchCode: string | number): AxiosPromise<SensorResultVO> => {
  return request({
    url: '/qms/sensorResult/' + batchCode,
    method: 'get'
  });
};
/**
 * æ–°å¢žæ‰¹æ¬¡æ˜Žç»†
 * @param data
 */
export const addSensorResult = (data: SensorResultForm) => {
  return request({
    url: '/qms/sensorResult',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹æ‰¹æ¬¡æ˜Žç»†
 * @param data
 */
export const updateSensorResult = (data: SensorResultForm) => {
  return request({
    url: '/qms/sensorResult',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤æ‰¹æ¬¡æ˜Žç»†
 * @param batchCode
 */
export const delSensorResult = (batchCode: string | number | Array<string | number>) => {
  return request({
    url: '/qms/sensorResult/' + batchCode,
    method: 'delete'
  });
};
src/api/qms/sensorResult/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
export interface SensorResultVO {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode: string;
  /**
   * æµ‹è¯•序号
   */
  testNum: string;
  /**
   * åˆ¤å®šç»“æžœ
   */
  judgeResult: string;
  /**
   * æ€»æµ‹è¯•项数
   */
  totalCount: number;
  /**
   * OK项数
   */
  okCount: number;
  /**
   * NG项数
   */
  ngCount: number;
}
export interface SensorResultForm extends BaseEntity {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * åˆ¤å®šç»“æžœ
   */
  judgeResult?: string;
  /**
   * æ€»æµ‹è¯•项数
   */
  totalCount?: number;
  /**
   * OK项数
   */
  okCount?: number;
  /**
   * NG项数
   */
  ngCount?: number;
}
export interface SensorResultQuery extends PageQuery {
  /**
   * åˆ¤å®šç»“æžœ
   */
  judgeResult?: string;
  /**
   * æ€»æµ‹è¯•项数
   */
  totalCount?: number;
  /**
   * OK项数
   */
  okCount?: number;
  /**
   * NG项数
   */
  ngCount?: number;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/sensorRetest/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { SensorRetestVO, SensorRetestForm, SensorRetestQuery } from '@/api/qms/sensorRetest/types';
/**
 * æŸ¥è¯¢å¤æµ‹è®°å½•列表
 * @param query
 * @returns {*}
 */
export const listSensorRetest = (query?: SensorRetestQuery): AxiosPromise<SensorRetestVO[]> => {
  return request({
    url: '/qms/sensorRetest/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢å¤æµ‹è®°å½•详细
 * @param batchCode
 */
export const getSensorRetest = (batchCode: string | number): AxiosPromise<SensorRetestVO> => {
  return request({
    url: '/qms/sensorRetest/' + batchCode,
    method: 'get'
  });
};
/**
 * æ–°å¢žå¤æµ‹è®°å½•
 * @param data
 */
export const addSensorRetest = (data: SensorRetestForm) => {
  return request({
    url: '/qms/sensorRetest',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹å¤æµ‹è®°å½•
 * @param data
 */
export const updateSensorRetest = (data: SensorRetestForm) => {
  return request({
    url: '/qms/sensorRetest',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤å¤æµ‹è®°å½•
 * @param batchCode
 */
export const delSensorRetest = (batchCode: string | number | Array<string | number>) => {
  return request({
    url: '/qms/sensorRetest/' + batchCode,
    method: 'delete'
  });
};
src/api/qms/sensorRetest/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
export interface SensorRetestVO {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode: string;
  /**
   * æµ‹è¯•序号
   */
  testNum: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName: string;
  /**
   * åˆ¤å®šç»“æžœ
   */
  judgeResult: string;
  /**
   * æ€»æµ‹è¯•项数
   */
  totalCount: number;
  /**
   * OK项数
   */
  okCount: number;
  /**
   * NG项数
   */
  ngCount: number;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface SensorRetestForm extends BaseEntity {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum?: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName?: string;
  /**
   * åˆ¤å®šç»“æžœ
   */
  judgeResult?: string;
  /**
   * æ€»æµ‹è¯•项数
   */
  totalCount?: number;
  /**
   * OK项数
   */
  okCount?: number;
  /**
   * NG项数
   */
  ngCount?: number;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface SensorRetestQuery extends PageQuery {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * å¤æµ‹æ¬¡æ•°
   */
  retestNum?: string;
  /**
   * è®¾å¤‡å·
   */
  deviceCode?: string;
  /**
   * ç”¨æˆ·å¸å·
   */
  userName?: string;
    /**
     * æ—¥æœŸèŒƒå›´å‚æ•°
     */
    params?: any;
}
src/api/qms/testResult/index.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,89 @@
import request from '@/utils/request';
import { AxiosPromise } from 'axios';
import { TestResultVO, TestResultForm, TestResultQuery } from '@/api/qms/testResult/types';
/**
 * æŸ¥è¯¢æµ‹è¯•结果列表
 * @param query
 * @returns {*}
 */
export const listTestResult = (query?: TestResultQuery): AxiosPromise<TestResultVO[]> => {
  return request({
    url: '/qms/testResult/list',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢æµ‹è¯•结果列表
 * @param query
 * @returns {*}
 */
export const listTestResultAll = (query?: TestResultQuery): AxiosPromise<TestResultVO[]> => {
  return request({
    url: '/qms/testResult/listAll',
    method: 'get',
    params: query
  });
};
/**
 * æŸ¥è¯¢æµ‹è¯•项目
 * @param query
 * @returns {*}
 */
export const listTestItem = () => {
  return request({
    url: '/qms/testResult/distinctTestItems',
    method: 'get'
  });
};
/**
 * æŸ¥è¯¢æµ‹è¯•结果详细
 * @param id
 */
export const getTestResult = (id: string | number): AxiosPromise<TestResultVO> => {
  return request({
    url: '/qms/testResult/' + id,
    method: 'get'
  });
};
/**
 * æ–°å¢žæµ‹è¯•结果
 * @param data
 */
export const addTestResult = (data: TestResultForm) => {
  return request({
    url: '/qms/testResult',
    method: 'post',
    data: data
  });
};
/**
 * ä¿®æ”¹æµ‹è¯•结果
 * @param data
 */
export const updateTestResult = (data: TestResultForm) => {
  return request({
    url: '/qms/testResult',
    method: 'put',
    data: data
  });
};
/**
 * åˆ é™¤æµ‹è¯•结果
 * @param id
 */
export const delTestResult = (id: string | number | Array<string | number>) => {
  return request({
    url: '/qms/testResult/' + id,
    method: 'delete'
  });
};
src/api/qms/testResult/types.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,201 @@
export interface TestResultVO {
  /**
   *
   */
  id: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode: string;
  /**
   * æµ‹è¯•序号
   */
  testNum: string;
  /**
   * æµ‹è¯•项目
   */
  testItem: string;
  /**
   * å®žé™…电压
   */
  voltage: number;
  /**
   * å®žé™…电流
   */
  loadCurrent: number;
  /**
   * æ ‡å‡†è·ç¦»
   */
  stdDistance: number;
  /**
   * æ„Ÿåº”物
   */
  inductor: string;
  /**
   * è¾“出引脚(黑;白)
   */
  output: string;
  /**
   * æµ‹è¯•数据
   */
  testValue: number;
  /**
   * åˆ¤æ–­æ¡ä»¶ï¼ˆæœ€å°å€¼<=真实值<=最大值 ï¼‰
   */
  judgeDetail: string;
  /**
   * æµ‹è¯•结果(OK; NG)
   */
  testResult: string;
  /**
   * å¤‡æ³¨
   */
  remark: string;
}
export interface TestResultForm extends BaseEntity {
  /**
   *
   */
  id?: string | number;
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * æµ‹è¯•项目
   */
  testItem?: string;
  /**
   * å®žé™…电压
   */
  voltage?: number;
  /**
   * å®žé™…电流
   */
  loadCurrent?: number;
  /**
   * æ ‡å‡†è·ç¦»
   */
  stdDistance?: number;
  /**
   * æ„Ÿåº”物
   */
  inductor?: string;
  /**
   * è¾“出引脚(黑;白)
   */
  output?: string;
  /**
   * æµ‹è¯•数据
   */
  testValue?: number;
  /**
   * åˆ¤æ–­æ¡ä»¶ï¼ˆæœ€å°å€¼<=真实值<=最大值 ï¼‰
   */
  judgeDetail?: string;
  /**
   * æµ‹è¯•结果(OK; NG)
   */
  testResult?: string;
  /**
   * å¤‡æ³¨
   */
  remark?: string;
}
export interface TestResultQuery extends PageQuery {
  /**
   * æ‰¹æ¬¡å·
   */
  batchCode?: string;
  /**
   * æµ‹è¯•序号
   */
  testNum?: string;
  /**
   * æµ‹è¯•项目
   */
  testItem?: string;
  /**
   * å®žé™…电压
   */
  voltage?: number;
  /**
   * å®žé™…电流
   */
  loadCurrent?: number;
  /**
   * æ ‡å‡†è·ç¦»
   */
  stdDistance?: number;
  /**
   * æ„Ÿåº”物
   */
  inductor?: string;
  /**
   * è¾“出引脚(黑;白)
   */
  output?: string;
  /**
   * æµ‹è¯•数据
   */
  testValue?: number;
  /**
   * åˆ¤æ–­æ¡ä»¶ï¼ˆæœ€å°å€¼<=真实值<=最大值 ï¼‰
   */
  judgeDetail?: string;
  /**
   * æµ‹è¯•结果(OK; NG)
   */
  testResult?: string;
  /**
   * æ—¥æœŸèŒƒå›´å‚æ•°
   */
  params?: any;
}
src/assets/icons/svg/batch-detail.svg
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1733988825570" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1518" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M902.386347 299.738453c-0.02048-0.02048 0-0.054613-0.02048-0.085333-0.4096-1.93536-1.1264-3.754667-2.048-5.471573-0.211627-0.395947-0.426667-0.771413-0.648533-1.153707-1.04448-1.723733-2.22208-3.34848-3.67616-4.73088l0-0.01024L618.038613 24.139093c-0.006827 0-0.034133-0.01024-0.034133-0.03072l-0.037547-0.027307c-0.01024-0.013653-0.044373-0.013653-0.064853-0.03072-1.419947-1.355093-3.085653-2.450773-4.840107-3.42016-0.433493-0.23552-0.853333-0.457387-1.314133-0.662187-1.764693-0.836267-3.631787-1.52576-5.618347-1.921707-0.170667-0.01024-0.324267-0.01024-0.47104-0.017067-1.344853-0.24576-2.69312-0.402773-4.12672-0.402773L201.8816 17.626453c-36.939093 0-67.003733 28.699307-67.003733 63.993173l0 864.576853c0 35.283627 30.06464 64.01024 67.003733 64.01024l633.965227 0c36.94592 0 66.993493-28.726613 66.993493-64.01024L902.84032 304.049493C902.84032 302.578347 902.66624 301.134507 902.386347 299.738453M823.197013 281.82528l-198.362453 0L624.83456 93.313707 823.197013 281.82528zM856.306347 946.213547c0 10.769067-9.17504 19.554987-20.45952 19.554987L201.8816 965.768533c-11.30496 0-20.476587-8.779093-20.476587-19.554987L181.405013 81.629867c0-10.789547 9.17504-19.551573 20.476587-19.551573l376.425813 0 0 241.96096c0 12.274347 10.43456 22.224213 23.261867 22.224213l254.743893 0L856.306347 946.213547 856.306347 946.213547z" fill="#050101" p-id="1519"></path><path d="M711.3216 738.78528 313.50784 738.78528c-12.20608 0-22.09792 10.417493-22.09792 23.27552 0 12.87168 9.888427 23.27552 22.09792 23.27552l397.810347 0c12.19584 0 22.09792-10.407253 22.09792-23.27552C733.412693 749.202773 723.51744 738.78528 711.3216 738.78528" fill="#050101" p-id="1520"></path><path d="M711.3216 585.63584 313.50784 585.63584c-12.20608 0-22.09792 10.41408-22.09792 23.261867 0 12.868267 9.888427 23.272107 22.09792 23.272107l397.810347 0c12.19584 0 22.09792-10.386773 22.09792-23.272107C733.412693 596.04992 723.51744 585.63584 711.3216 585.63584" fill="#050101" p-id="1521"></path><path d="M291.396267 455.758507c0 12.8512 9.89184 23.261867 22.09792 23.261867l397.810347 0c12.209493 0 22.104747-10.410667 22.104747-23.261867 0-12.864853-9.888427-23.268693-22.104747-23.268693L313.494187 432.489813C301.29152 432.493227 291.396267 442.893653 291.396267 455.758507" fill="#050101" p-id="1522"></path></svg>
src/assets/logo/logo.png

src/assets/logo/logo_bak.png
src/layout/components/Sidebar/Logo.vue
@@ -34,7 +34,7 @@
  }
});
const title = ref('RuoYi-Vue-Plus');
const title = ref('LB-QMS');
const settingsStore = useSettingsStore();
const sideTheme = computed(() => settingsStore.sideTheme);
</script>
src/views/index.vue
@@ -2,92 +2,12 @@
  <div class="app-container home">
    <el-row :gutter="20">
      <el-col :sm="24" :lg="12" style="padding-left: 20px">
        <h2>RuoYi-Vue-Plus多租户管理系统</h2>
        <p>
          RuoYi-Vue-Plus æ˜¯åŸºäºŽ RuoYi-Vue é’ˆå¯¹ åˆ†å¸ƒå¼é›†ç¾¤ åœºæ™¯å‡çº§(不兼容原框架)
          <br />
          * å‰ç«¯å¼€å‘框架 Vue3、TS、Element Plus<br />
          * åŽç«¯å¼€å‘框架 Spring Boot<br />
          * å®¹å™¨æ¡†æž¶ Undertow åŸºäºŽ Netty çš„高性能容器<br />
          * æƒé™è®¤è¯æ¡†æž¶ Sa-Token æ”¯æŒå¤šç»ˆç«¯è®¤è¯ç³»ç»Ÿ<br />
          * å…³ç³»æ•°æ®åº“ MySQL é€‚配 8.X æœ€ä½Ž 5.7<br />
          * ç¼“存数据库 Redis é€‚配 6.X æœ€ä½Ž 4.X<br />
          * æ•°æ®åº“框架 Mybatis-Plus å¿«é€Ÿ CRUD å¢žåŠ å¼€å‘æ•ˆçŽ‡<br />
          * æ•°æ®åº“框架 p6spy æ›´å¼ºåŠ²çš„ SQL åˆ†æž<br />
          * å¤šæ•°æ®æºæ¡†æž¶ dynamic-datasource æ”¯æŒä¸»ä»Žä¸Žå¤šç§ç±»æ•°æ®åº“异构<br />
          * åºåˆ—化框架 Jackson ç»Ÿä¸€ä½¿ç”¨ jackson é«˜æ•ˆå¯é <br />
          * Redis客户端 Redisson æ€§èƒ½å¼ºåŠ²ã€API丰富<br />
          * åˆ†å¸ƒå¼é™æµ Redisson å…¨å±€ã€è¯·æ±‚IP、集群ID å¤šç§é™æµ<br />
          * åˆ†å¸ƒå¼é” Lock4j æ³¨è§£é”ã€å·¥å…·é” å¤šç§å¤šæ ·<br />
          * åˆ†å¸ƒå¼å¹‚ç­‰ Lock4j åŸºäºŽåˆ†å¸ƒå¼é”å®žçް<br />
          * åˆ†å¸ƒå¼é“¾è·¯è¿½è¸ª SkyWalking æ”¯æŒé“¾è·¯è¿½è¸ªã€ç½‘格分析、度量聚合、可视化<br />
          * åˆ†å¸ƒå¼ä»»åŠ¡è°ƒåº¦ SnailJob é«˜æ€§èƒ½ é«˜å¯é  æ˜“扩展<br />
          * æ–‡ä»¶å­˜å‚¨ Minio æœ¬åœ°å­˜å‚¨<br />
          * æ–‡ä»¶å­˜å‚¨ ä¸ƒç‰›ã€é˜¿é‡Œã€è…¾è®¯ äº‘存储<br />
          * ç›‘控框架 SpringBoot-Admin å…¨æ–¹ä½æœåŠ¡ç›‘æŽ§<br />
          * æ ¡éªŒæ¡†æž¶ Validation å¢žå¼ºæŽ¥å£å®‰å…¨æ€§ ä¸¥è°¨æ€§<br />
          * Excel框架 Alibaba EasyExcel æ€§èƒ½ä¼˜å¼‚ æ‰©å±•性强<br />
          * æ–‡æ¡£æ¡†æž¶ SpringDoc、javadoc æ— æ³¨è§£é›¶å…¥ä¾µåŸºäºŽjava注释<br />
          * å·¥å…·ç±»æ¡†æž¶ Hutool、Lombok å‡å°‘代码冗余 å¢žåŠ å®‰å…¨æ€§<br />
          * ä»£ç ç”Ÿæˆå™¨ é€‚配MP、SpringDoc规范化代码 ä¸€é”®ç”Ÿæˆå‰åŽç«¯ä»£ç <br />
          * éƒ¨ç½²æ–¹å¼ Docker å®¹å™¨ç¼–排 ä¸€é”®éƒ¨ç½²ä¸šåŠ¡é›†ç¾¤<br />
          * å›½é™…化 SpringMessage Spring标准国际化方案<br />
        </p>
        <p><b>当前版本:</b> <span>v5.3.0</span></p>
        <p>
          <el-tag type="danger">&yen;免费开源</el-tag>
        </p>
        <p>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Vue-Plus')">访问码云</el-button>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Vue-Plus')">访问GitHub</el-button>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-vue-plus/changlog')"
            >更新日志</el-button
          >
        </p>
        <h2>兰宝车间质量管理系统</h2>
      </el-col>
      <el-col :sm="24" :lg="12" style="padding-left: 20px">
        <h2>RuoYi-Cloud-Plus多租户微服务管理系统</h2>
        <p>
          RuoYi-Cloud-Plus å¾®æœåŠ¡é€šç”¨æƒé™ç®¡ç†ç³»ç»Ÿ é‡å†™ RuoYi-Cloud å…¨æ–¹ä½å‡çº§(不兼容原框架)
          <br />
          * å‰ç«¯å¼€å‘框架 Vue3、TS、Element UI<br />
          * åŽç«¯å¼€å‘框架 Spring Boot<br />
          * å¾®æœåŠ¡å¼€å‘æ¡†æž¶ Spring Cloud、Spring Cloud Alibaba<br />
          * å®¹å™¨æ¡†æž¶ Undertow åŸºäºŽ XNIO çš„高性能容器<br />
          * æƒé™è®¤è¯æ¡†æž¶ Sa-Token、Jwt æ”¯æŒå¤šç»ˆç«¯è®¤è¯ç³»ç»Ÿ<br />
          * å…³ç³»æ•°æ®åº“ MySQL é€‚配 8.X æœ€ä½Ž 5.7<br />
          * å…³ç³»æ•°æ®åº“ Oracle é€‚配 11g 12c<br />
          * å…³ç³»æ•°æ®åº“ PostgreSQL é€‚配 13 14<br />
          * å…³ç³»æ•°æ®åº“ SQLServer é€‚配 2017 2019<br />
          * ç¼“存数据库 Redis é€‚配 6.X æœ€ä½Ž 5.X<br />
          * åˆ†å¸ƒå¼æ³¨å†Œä¸­å¿ƒ Alibaba Nacos é‡‡ç”¨2.X åŸºäºŽGRPC通信高性能<br />
          * åˆ†å¸ƒå¼é…ç½®ä¸­å¿ƒ Alibaba Nacos é‡‡ç”¨2.X åŸºäºŽGRPC通信高性能<br />
          * æœåŠ¡ç½‘å…³ Spring Cloud Gateway å“åº”式高性能网关<br />
          * è´Ÿè½½å‡è¡¡ Spring Cloud Loadbalancer è´Ÿè½½å‡è¡¡å¤„理<br />
          * RPC远程调用 Apache Dubbo åŽŸç”Ÿæ€ä½¿ç”¨ä½“éªŒã€é«˜æ€§èƒ½<br />
          * åˆ†å¸ƒå¼é™æµç†”æ–­ Alibaba Sentinel æ— ä¾µå…¥ã€é«˜æ‰©å±•<br />
          * åˆ†å¸ƒå¼äº‹åŠ¡ Alibaba Seata æ— ä¾µå…¥ã€é«˜æ‰©å±• æ”¯æŒ å››ç§æ¨¡å¼<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— Apache Kafka é«˜æ€§èƒ½é«˜é€Ÿåº¦<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— Apache RocketMQ é«˜å¯ç”¨åŠŸèƒ½å¤šæ ·<br />
          * åˆ†å¸ƒå¼æ¶ˆæ¯é˜Ÿåˆ— RabbitMQ æ”¯æŒå„种扩展插件功能多样性<br />
          * åˆ†å¸ƒå¼æœç´¢å¼•擎 ElasticSearch ä¸šç•ŒçŸ¥å<br />
          * åˆ†å¸ƒå¼é“¾è·¯è¿½è¸ª Apache SkyWalking é“¾è·¯è¿½è¸ªã€ç½‘格分析、度量聚合、可视化<br />
          * åˆ†å¸ƒå¼æ—¥å¿—中心 ELK ä¸šç•Œæˆç†Ÿè§£å†³æ–¹æ¡ˆ<br />
          * åˆ†å¸ƒå¼ç›‘控 Prometheus、Grafana å…¨æ–¹ä½æ€§èƒ½ç›‘控<br />
          * å…¶ä½™ä¸Ž Vue ç‰ˆæœ¬ä¸€è‡´<br />
        </p>
        <p><b>当前版本:</b> <span>v2.3.0</span></p>
        <p>
          <el-tag type="danger">&yen;免费开源</el-tag>
        </p>
        <p>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://gitee.com/dromara/RuoYi-Cloud-Plus')">访问码云</el-button>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://github.com/dromara/RuoYi-Cloud-Plus')">访问GitHub</el-button>
          <el-button type="primary" icon="Cloudy" plain @click="goTarget('https://plus-doc.dromara.org/#/ruoyi-cloud-plus/changlog')"
            >更新日志</el-button
          >
        </p>
      </el-col>
    </el-row>
    <el-divider />
src/views/login.vue
@@ -2,7 +2,7 @@
  <div class="login">
    <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form">
      <div class="title-box">
        <h3 class="title">RuoYi-Vue-Plus多租户管理系统</h3>
        <h3 class="title">兰宝车间质量管理系统</h3>
        <lang-select />
      </div>
      <el-form-item v-if="tenantEnabled" prop="tenantId">
@@ -73,7 +73,7 @@
    </el-form>
    <!--  åº•部  -->
    <div class="el-login-footer">
      <span>Copyright Â© 2018-2024 ç–¯ç‹‚的狮子Li All Rights Reserved.</span>
      <span>Copyright Â© 2018-2024 ä¸Šæµ·å…°æµ¦æ™ºèƒ½ç§‘技有限公司 All Rights Reserved.</span>
    </div>
  </div>
</template>
@@ -95,8 +95,8 @@
const loginForm = ref<LoginData>({
  tenantId: '000000',
  username: 'admin',
  password: 'admin123',
  username: '',
  password: '',
  rememberMe: false,
  code: '',
  uuid: ''
src/views/qms/batch/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,299 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="批次号" prop="batchCode">
              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="产品型号" prop="prodModel">
              <el-input v-model="queryParams.prodModel" placeholder="请输入产品型号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <div style="display: inline" v-if="showMore">
              <el-form-item label="用户编号" prop="userId">
                <el-input v-model="queryParams.userId" placeholder="请输入用户编号" clearable @keyup.enter="handleQuery" />
              </el-form-item>
              <el-form-item label="设备号" prop="deviceCode">
                <el-input v-model="queryParams.deviceCode" placeholder="请输入设备号" clearable @keyup.enter="handleQuery" />
              </el-form-item>
              <el-form-item label="数量" prop="num">
                <el-input v-model="queryParams.num" placeholder="请输入数量" clearable @keyup.enter="handleQuery" />
              </el-form-item>
            </div>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
              <el-button v-if="!showMore" type="text" @click="showMore = !showMore">展开</el-button>
              <el-button v-if="showMore" type="text" @click="showMore = !showMore">收起</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:batch:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:batch:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:batch:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:batch:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" :columns="columns" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table
        v-loading="loading"
        :data="batchList"
        @selection-change="handleSelectionChange"
        stripe
        highlight-current-row
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="ID" align="center" prop="id" v-if="columns[0].visible"/>
        <el-table-column label="批次号" align="center" prop="batchCode" v-if="columns[1].visible" />
        <el-table-column label="产品型号" align="center" prop="prodModel" v-if="columns[2].visible" />
        <el-table-column label="用户编号" align="center" prop="userId" v-if="columns[3].visible" />
        <el-table-column label="设备号" align="center" prop="deviceCode" v-if="columns[4].visible" />
        <el-table-column label="数量" align="center" prop="num" v-if="columns[5].visible" />
        <el-table-column label="备注" align="center" prop="remark" v-if="columns[6].visible" />
        <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[7].visible" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="明细" placement="top">
              <el-button link type="primary" icon="Document" @click="handleDetail(scope.row)"></el-button>
            </el-tooltip>
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:batch:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:batch:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æ‰¹æ¬¡ç®¡ç†å¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="batchFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="产品型号" prop="prodModel">
          <el-input v-model="form.prodModel" placeholder="请输入产品型号" />
        </el-form-item>
        <el-form-item label="用户编号" prop="userId">
          <el-input v-model="form.userId" placeholder="请输入用户编号" />
        </el-form-item>
        <el-form-item label="设备号" prop="deviceCode">
          <el-input v-model="form.deviceCode" placeholder="请输入设备号" />
        </el-form-item>
        <el-form-item label="数量" prop="num">
          <el-input v-model="form.num" placeholder="请输入数量" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="Batch" lang="ts">
import { listBatch, getBatch, delBatch, addBatch, updateBatch } from '@/api/qms/batch';
import { BatchVO, BatchQuery, BatchForm } from '@/api/qms/batch/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const batchList = ref<BatchVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const showMore = ref(false);
const queryFormRef = ref<ElFormInstance>();
const batchFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: BatchForm = {
  id: undefined,
  batchCode: undefined,
  prodModel: undefined,
  userId: undefined,
  deviceCode: undefined,
  num: undefined,
  remark: undefined,
  createTime: undefined, // æ·»åŠ  createTime å­—段
}
const data = reactive<PageData<BatchForm, BatchQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    batchCode: undefined,
    prodModel: undefined,
    userId: undefined,
    deviceCode: undefined,
    num: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    prodModel: [
      { required: true, message: "产品型号不能为空", trigger: "blur" }
    ],
    userId: [
      { required: true, message: "用户编号不能为空", trigger: "blur" }
    ],
    deviceCode: [
      { required: true, message: "设备号不能为空", trigger: "blur" }
    ],
    num: [
      { required: true, message: "数量不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
// æ·»åŠ  columns æ•°ç»„
const columns = ref<FieldOption[]>([
  { key: 0, label: 'ID', align: 'center', visible: false },
  { key: 1, label: '批次号', align: 'center', visible: true },
  { key: 2, label: '产品型号', align: 'center', visible: true },
  { key: 3, label: '用户编号', align: 'center', visible: true },
  { key: 4, label: '设备号', align: 'center', visible: true },
  { key: 5, label: '数量', align: 'center', visible: true },
  { key: 6, label: '备注', align: 'center', visible: true },
  { key: 7, label: '创建时间', align: 'center', visible: true },
]);
/** æŸ¥è¯¢æ‰¹æ¬¡ç®¡ç†åˆ—表 */
const getList = async () => {
  loading.value = true;
  const res = await listBatch(queryParams.value);
  batchList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  batchFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: BatchVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加批次管理";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: BatchVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getBatch(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改批次管理";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  batchFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateBatch(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addBatch(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: BatchVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除批次管理编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delBatch(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/batch/export', {
    ...queryParams.value
  }, `batch_${new Date().getTime()}.xlsx`)
}
const handleDetail = (batch) => {
  proxy.$router.push({ path: 'sensorResult', query: {batchCode: batch.batchCode} });
}
onMounted(() => {
  getList();
});
</script>
src/views/qms/device/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,280 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="设备类型" prop="deviceType">
              <el-select v-model="queryParams.deviceType" placeholder="请选择设备类型" clearable >
                <el-option v-for="dict in lb_device_type" :key="dict.value" :label="dict.label" :value="dict.value"/>
              </el-select>
            </el-form-item>
            <el-form-item label="设备编号" prop="deviceCode">
              <el-input v-model="queryParams.deviceCode" placeholder="请输入设备编号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="所在组" prop="deviceGroup">
              <el-input v-model="queryParams.deviceGroup" placeholder="请输入所在组" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="所在部门" prop="deviceDept">
              <el-input v-model="queryParams.deviceDept" placeholder="请输入所在部门" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="所在工位" prop="deviceStation">
              <el-input v-model="queryParams.deviceStation" placeholder="请输入所在工位" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:device:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:device:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:device:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:device:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" stripe highlight-current-row :data="deviceList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="" align="center" prop="id" v-if="false" />
        <el-table-column label="设备类型" align="center" prop="deviceType">
          <template #default="scope">
            <dict-tag :options="lb_device_type" :value="scope.row.deviceType"/>
          </template>
        </el-table-column>
        <el-table-column label="设备编号" align="center" prop="deviceCode" />
        <el-table-column label="所在组" align="center" prop="deviceGroup" />
        <el-table-column label="所在部门" align="center" prop="deviceDept" />
        <el-table-column label="所在工位" align="center" prop="deviceStation" />
        <el-table-column label="备注" align="center" prop="remark" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:device:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:device:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ä»ªå¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="deviceFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="设备类型" prop="deviceType">
          <el-radio-group v-model="form.deviceType">
            <el-radio
              v-for="dict in lb_device_type"
              :key="dict.value"
              :value="dict.value"
            >{{dict.label}}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="设备编号" prop="deviceCode">
          <el-input v-model="form.deviceCode" placeholder="请输入设备编号" />
        </el-form-item>
        <el-form-item label="所在组" prop="deviceGroup">
          <el-input v-model="form.deviceGroup" placeholder="请输入所在组" />
        </el-form-item>
        <el-form-item label="所在部门" prop="deviceDept">
          <el-input v-model="form.deviceDept" placeholder="请输入所在部门" />
        </el-form-item>
        <el-form-item label="所在工位" prop="deviceStation">
          <el-input v-model="form.deviceStation" placeholder="请输入所在工位" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="Device" lang="ts">
import { listDevice, getDevice, delDevice, addDevice, updateDevice } from '@/api/qms/device';
import { DeviceVO, DeviceQuery, DeviceForm } from '@/api/qms/device/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { lb_device_type } = toRefs<any>(proxy?.useDict('lb_device_type'));
const deviceList = ref<DeviceVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const deviceFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: DeviceForm = {
  id: undefined,
  deviceType: undefined,
  deviceCode: undefined,
  deviceGroup: undefined,
  deviceDept: undefined,
  deviceStation: undefined,
  remark: undefined
}
const data = reactive<PageData<DeviceForm, DeviceQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    deviceType: undefined,
    deviceCode: undefined,
    deviceGroup: undefined,
    deviceDept: undefined,
    deviceStation: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    deviceType: [
      { required: true, message: "设备类型不能为空", trigger: "change" }
    ],
    deviceCode: [
      { required: true, message: "设备编号不能为空", trigger: "blur" }
    ],
    deviceGroup: [
      { required: true, message: "所在组不能为空", trigger: "blur" }
    ],
    deviceDept: [
      { required: true, message: "所在部门不能为空", trigger: "blur" }
    ],
    deviceStation: [
      { required: true, message: "所在工位不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢æµ‹è¯•仪列表 */
const getList = async () => {
  loading.value = true;
  const res = await listDevice(queryParams.value);
  deviceList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  deviceFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: DeviceVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加测试仪";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: DeviceVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getDevice(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改测试仪";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  deviceFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateDevice(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addDevice(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: DeviceVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试仪编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delDevice(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/device/export', {
    ...queryParams.value
  }, `device_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
  getList();
});
</script>
src/views/qms/retestResult/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,461 @@
<template>
  <div class="p-2">
<!--    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">-->
<!--      <div v-show="showSearch" class="mb-[10px]">-->
<!--        <el-card shadow="hover">-->
<!--          <el-form ref="queryFormRef" :model="queryParams" :inline="true">-->
<!--            <el-form-item label="批次号" prop="batchCode">-->
<!--              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item label="测试序号" prop="testNum">-->
<!--              <el-input v-model="queryParams.testNum" placeholder="请输入测试序号" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item label="测试项目" prop="testItem">-->
<!--              <el-input v-model="queryParams.testItem" placeholder="请输入测试项目" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item label="复测次数" prop="retestNum">-->
<!--              <el-input v-model="queryParams.retestNum" placeholder="请输入复测次数" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item label="设备号" prop="deviceCode">-->
<!--              <el-input v-model="queryParams.deviceCode" placeholder="请输入设备号" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item label="用户帐号" prop="userName">-->
<!--              <el-input v-model="queryParams.userName" placeholder="请输入用户帐号" clearable @keyup.enter="handleQuery" />-->
<!--            </el-form-item>-->
<!--            <el-form-item>-->
<!--              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>-->
<!--              <el-button icon="Refresh" @click="resetQuery">重置</el-button>-->
<!--            </el-form-item>-->
<!--          </el-form>-->
<!--        </el-card>-->
<!--      </div>-->
<!--    </transition>-->
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
<!--          <el-col :span="1.5">-->
<!--            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:retestResult:add']">新增</el-button>-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:retestResult:edit']">修改</el-button>-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:retestResult:remove']">删除</el-button>-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:retestResult:export']">导出</el-button>-->
<!--          </el-col>-->
          <right-toolbar v-model:showSearch="showSearch" :columns="columns" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" stripe highlight-current-row :data="retestResultList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="" align="center" prop="id" v-if="false"/>
        <!-- æ‰¹æ¬¡å· -->
        <el-table-column
          v-if="columns[0].visible"
          label="批次号"
          align="center"
          prop="batchCode"
        />
        <!-- æµ‹è¯•序号 -->
        <el-table-column
          v-if="columns[1].visible"
          label="测试序号"
          align="center"
          prop="testNum"
        />
        <!-- æµ‹è¯•项目 -->
        <el-table-column
          v-if="columns[2].visible"
          label="测试项目"
          align="center"
          prop="testItem"
        />
        <!-- å¤æµ‹æ¬¡æ•° -->
        <el-table-column
          v-if="columns[3].visible"
          label="复测次数"
          align="center"
          prop="retestNum"
        />
        <!-- è®¾å¤‡å· -->
        <el-table-column
          v-if="columns[4].visible"
          label="设备号"
          align="center"
          prop="deviceCode"
        />
        <!-- ç”¨æˆ·å¸å· -->
        <el-table-column
          v-if="columns[5].visible"
          label="用户帐号"
          align="center"
          prop="userName"
        />
        <!-- çŽ¯å¢ƒæ¸©åº¦ -->
        <el-table-column
          v-if="columns[6].visible"
          label="环境温度"
          align="center"
          prop="temp"
        />
        <!-- å®žé™…电压 -->
        <el-table-column
          v-if="columns[7].visible"
          label="实际电压"
          align="center"
          prop="voltage"
        />
        <!-- å®žé™…电流 -->
        <el-table-column
          v-if="columns[8].visible"
          label="实际电流"
          align="center"
          prop="loadCurrent"
        />
        <!-- æ ‡å‡†è·ç¦» -->
        <el-table-column
          v-if="columns[9].visible"
          label="标准距离"
          align="center"
          prop="stdDistance"
        />
        <!-- æ„Ÿåº”物 -->
        <el-table-column
          v-if="columns[10].visible"
          label="感应物"
          align="center"
          prop="inductor"
        />
        <!-- è¾“出引脚 -->
        <el-table-column
          v-if="columns[11].visible"
          label="输出引脚"
          align="center"
          prop="output"
        />
        <!-- æµ‹è¯•数据 -->
        <el-table-column
          v-if="columns[12].visible"
          label="测试数据"
          align="center"
          prop="testValue"
        />
        <!-- åˆ¤æ–­æ¡ä»¶ -->
        <el-table-column
          v-if="columns[13].visible"
          label="判断条件"
          align="center"
          prop="judgeDetail"
        />
        <!-- æµ‹è¯•结果 -->
        <el-table-column
          v-if="columns[14].visible"
          label="测试结果"
          align="center"
          prop="testResult"
        />
        <!-- å¤‡æ³¨ -->
        <el-table-column
          v-if="columns[15].visible"
          label="备注"
          align="center"
          prop="remark"
        />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['lb-qms:retestResult:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['lb-qms:retestResult:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹å¤æµ‹è®°å½•å¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="retestResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="" prop="id">
          <el-input v-model="form.id" placeholder="请输入" />
        </el-form-item>
        <el-form-item label="复测次数" prop="retestNum">
          <el-input v-model="form.retestNum" placeholder="请输入复测次数" />
        </el-form-item>
        <el-form-item label="设备号" prop="deviceCode">
          <el-input v-model="form.deviceCode" placeholder="请输入设备号" />
        </el-form-item>
        <el-form-item label="用户帐号" prop="userName">
          <el-input v-model="form.userName" placeholder="请输入用户帐号" />
        </el-form-item>
        <el-form-item label="环境温度" prop="temp">
          <el-input v-model="form.temp" placeholder="请输入环境温度" />
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="RetestResult" lang="ts">
import { listRetestResult, getRetestResult, delRetestResult, addRetestResult, updateRetestResult } from '@/api/qms/retestResult';
import { RetestResultVO, RetestResultQuery, RetestResultForm } from '@/api/qms/retestResult/types';
import { watch } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const retestResultList = ref<RetestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const retestResultFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: RetestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  retestNum: undefined,
  deviceCode: undefined,
  userName: undefined,
  temp: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
}
const data = reactive<PageData<RetestResultForm, RetestResultQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    retestNum: undefined,
    deviceCode: undefined,
    userName: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    testItem: [
      { required: true, message: "测试项目不能为空", trigger: "blur" }
    ],
    retestNum: [
      { required: true, message: "复测次数不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
// å®šä¹‰è¡¨æ ¼åˆ—的显示/隐藏配置
const columns = ref<FieldOption[]>([
  { key: 0, label: '批次号', align: 'center', visible: true },
  { key: 1, label: '测试序号', align: 'center', visible: true },
  { key: 2, label: '测试项目', align: 'center', visible: true },
  { key: 3, label: '复测次数', align: 'center', visible: true },
  { key: 4, label: '设备号', align: 'center', visible: true },
  { key: 5, label: '用户帐号', align: 'center', visible: true },
  { key: 6, label: '环境温度', align: 'center', visible: true },
  { key: 7, label: '实际电压', align: 'center', visible: true },
  { key: 8, label: '实际电流', align: 'center', visible: true },
  { key: 9, label: '标准距离', align: 'center', visible: true },
  { key: 10, label: '感应物', align: 'center', visible: true },
  { key: 11, label: '输出引脚', align: 'center', visible: true },
  { key: 12, label: '测试数据', align: 'center', visible: true },
  { key: 13, label: '判断条件', align: 'center', visible: true },
  { key: 14, label: '测试结果', align: 'center', visible: true },
  { key: 15, label: '备注', align: 'center', visible: true },
]);
/** æŸ¥è¯¢å¤æµ‹è®°å½•列表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.batchCode = proxy.$route.query.batchCode;
  queryParams.value.testNum = proxy.$route.query.testNum;
  if (proxy.$route.query.retestNum) {
    queryParams.value.retestNum = proxy.$route.query.retestNum;
  }
  const res = await listRetestResult(queryParams.value);
  retestResultList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  retestResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: RetestResultVO[]) => {
  ids.value = selection.map(item => item.batchCode);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加复测记录";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: RetestResultVO) => {
  reset();
  const _batchCode = row?.batchCode || ids.value[0]
  const res = await getRetestResult(_batchCode);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改复测记录";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  retestResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.batchCode) {
        await updateRetestResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addRetestResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: RetestResultVO) => {
  const _batchCodes = row?.batchCode || ids.value;
  await proxy?.$modal.confirm('是否确认删除复测记录编号为"' + _batchCodes + '"的数据项?').finally(() => loading.value = false);
  await delRetestResult(_batchCodes);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/retestResult/export', {
    ...queryParams.value
  }, `retestResult_${new Date().getTime()}.xlsx`)
}
watch(
  () => proxy.$route.query.testNum,
  (testNum) => {
    console.log('path', proxy.$route.path);
    console.log('testNum', testNum);
    if (proxy.$route.path === '/qms/retestResult' && testNum) {
      queryParams.value.pageNum = 1;
      getList();
    }
  }
);
onMounted(() => {
  getList();
});
</script>
src/views/qms/sensor/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,451 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="产品型号" prop="prodModel">
              <el-input v-model="queryParams.prodModel" placeholder="请输入产品型号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:sensor:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:sensor:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:sensor:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:sensor:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table
        v-loading="loading"
        :data="sensorList"
        @selection-change="handleSelectionChange"
        stripe
        highlight-current-row
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="" align="center" prop="prodId" v-if="false" />
        <el-table-column label="产品型号" align="center" prop="prodModel" />
        <el-table-column label="产品条码" align="center" prop="prodBarcode" />
        <el-table-column label="产品大类" align="center" prop="prodClass">
          <template #default="scope">
            <dict-tag :options="lb_sensor_class" :value="scope.row.prodClass"/>
          </template>
        </el-table-column>
        <el-table-column label="产品小类" align="center" prop="prodSubclass">
          <template #default="scope">
            <dict-tag :options="lb_sensor_l_subclass" :value="scope.row.prodSubclass"/>
          </template>
        </el-table-column>
        <el-table-column label="供电电源" align="center" prop="supply">
          <template #default="scope">
            <dict-tag :options="lb_power_supply" :value="scope.row.supply"/>
          </template>
        </el-table-column>
        <el-table-column label="电压高值" align="center" prop="supplyHigh" />
        <el-table-column label="电压中值" align="center" prop="supplyMiddle" />
        <el-table-column label="电压低值" align="center" prop="supplyLow" />
        <el-table-column label="负载电流" align="center" prop="loadCurrent" />
        <el-table-column label="引线数量" align="center" prop="wire">
          <template #default="scope">
            <dict-tag :options="lb_sensor_wire" :value="scope.row.wire"/>
          </template>
        </el-table-column>
        <el-table-column label="输出信号" align="center" prop="outputSignal">
          <template #default="scope">
            <dict-tag :options="lp_output_signal" :value="scope.row.outputSignal"/>
          </template>
        </el-table-column>
        <el-table-column label="输出类型" align="center" prop="outputType">
          <template #default="scope">
            <dict-tag :options="lb_output_type" :value="scope.row.outputType"/>
          </template>
        </el-table-column>
        <el-table-column label="输出极性" align="center" prop="outputPolarity">
          <template #default="scope">
            <dict-tag :options="lb_output_polarity" :value="scope.row.outputPolarity"/>
          </template>
        </el-table-column>
        <el-table-column label="感应距离" align="center" prop="distance" />
        <el-table-column label="备注" align="center" prop="remark" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:sensor:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:sensor:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹ä¼ æ„Ÿå™¨å¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="600px" append-to-body>
      <el-form ref="sensorFormRef" :model="form" :rules="rules" label-width="80px">
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="产品型号" prop="prodModel">
              <el-input v-model="form.prodModel" placeholder="请输入产品型号" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12">
            <el-form-item label="产品条码" prop="prodBarcode">
              <el-input v-model="form.prodBarcode" placeholder="请输入产品条码" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :xs="24" :sm="24">
            <el-form-item label="产品大类" prop="prodClass">
              <el-radio-group v-model="form.prodClass">
                <el-radio
                  v-for="dict in lb_sensor_class"
                  :key="dict.value"
                  :value="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="产品小类" prop="prodSubclass">
              <el-select v-model="form.prodSubclass" placeholder="请选择产品小类">
                <el-option
                  v-for="dict in (form.prodClass == '光电型'?lb_sensor_p_subclass:form.prodClass=='电容型'?lb_sensor_c_subclass:lb_sensor_l_subclass)"
                  :key="dict.value"
                  :label="dict.label"
                  :value="dict.value"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12">
            <el-form-item label="供电电源" prop="supply">
              <el-radio-group v-model="form.supply">
                <el-radio
                  v-for="dict in lb_power_supply"
                  :key="dict.value"
                  :value="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="电压高值" prop="supplyHigh">
              <el-input type="number" v-model="form.supplyHigh" placeholder="请输入电压高值">
                <template #append>V</template>
              </el-input>
            </el-form-item>
        </el-col>
        <el-col :xs="24" :sm="12">
          <el-form-item label="电压中值" prop="supplyMiddle">
            <el-input type="number" v-model="form.supplyMiddle" placeholder="请输入电压中值">
              <template #append>V</template>
            </el-input>
          </el-form-item>
        </el-row>
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="电压低值" prop="supplyLow">
              <el-input type="number" v-model="form.supplyLow" placeholder="请输入电压低值">
                <template #append>V</template>
              </el-input>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12">
            <el-form-item label="负载电流" prop="loadCurrent">
              <el-input type="number" v-model="form.loadCurrent" placeholder="请输入负载电流">
                <template #append>A</template>
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="引线数量" prop="wire">
              <el-select v-model="form.wire" placeholder="请选择引线数量">
                <el-option
                  v-for="dict in lb_sensor_wire"
                  :key="dict.value"
                  :label="dict.label"
                  :value="parseInt(dict.value)"
                ></el-option>
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12">
            <el-form-item label="输出信号" prop="outputSignal">
              <el-radio-group v-model="form.outputSignal">
                <el-radio
                  v-for="dict in lp_output_signal"
                  :key="dict.value"
                  :value="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="输出类型" prop="outputType">
          <el-radio-group v-model="form.outputType">
            <el-radio
              v-for="dict in lb_output_type"
              :key="dict.value"
              :value="dict.value"
            >{{dict.label}}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-row>
          <el-col :xs="24" :sm="12">
            <el-form-item label="输出极性" prop="outputPolarity">
              <el-radio-group v-model="form.outputPolarity">
                <el-radio
                  v-for="dict in lb_output_polarity"
                  :key="dict.value"
                  :value="dict.value"
                >{{dict.label}}</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :sm="12">
            <el-form-item label="感应距离" prop="distance">
              <el-input type="number" v-model="form.distance" placeholder="请输入感应距离">
                <template #append>m</template>
              </el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="Sensor" lang="ts">
import { listSensor, getSensor, delSensor, addSensor, updateSensor } from '@/api/qms/sensor';
import { SensorVO, SensorQuery, SensorForm } from '@/api/qms/sensor/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const { lp_output_signal, lb_output_polarity, lb_sensor_wire, lb_power_supply, lb_output_type, lb_sensor_class, lb_sensor_l_subclass, lb_sensor_c_subclass, lb_sensor_p_subclass } = toRefs<any>(proxy?.useDict('lp_output_signal', 'lb_output_polarity', 'lb_sensor_wire', 'lb_power_supply', 'lb_output_type', 'lb_sensor_class', 'lb_sensor_l_subclass', 'lb_sensor_c_subclass', 'lb_sensor_p_subclass'));
const sensorList = ref<SensorVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const sensorFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: SensorForm = {
  prodId: undefined,
  prodModel: undefined,
  prodBarcode: undefined,
  prodClass: undefined,
  prodSubclass: undefined,
  supply: undefined,
  supplyHigh: undefined,
  supplyMiddle: undefined,
  supplyLow: undefined,
  loadCurrent: undefined,
  wire: undefined,
  outputSignal: undefined,
  outputType: undefined,
  outputPolarity: undefined,
  distance: undefined,
  remark: undefined
}
const data = reactive<PageData<SensorForm, SensorQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    prodModel: undefined,
    params: {
    }
  },
  rules: {
    prodId: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    prodModel: [
      { required: true, message: "产品型号不能为空", trigger: "blur" }
    ],
    prodBarcode: [
      { required: true, message: "产品条码不能为空", trigger: "blur" }
    ],
    prodClass: [
      { required: true, message: "产品大类不能为空", trigger: "change" }
    ],
    prodSubclass: [
      { required: true, message: "产品小类不能为空", trigger: "change" }
    ],
    supply: [
      { required: true, message: "供电电源不能为空", trigger: "change" }
    ],
    loadCurrent: [
      { required: true, message: "负载电流不能为空", trigger: "blur" }
    ],
    wire: [
      { required: true, message: "引线数量不能为空", trigger: "change" }
    ],
    outputSignal: [
      { required: true, message: "输出信号不能为空", trigger: "change" }
    ],
    outputType: [
      { required: true, message: "输出类型不能为空", trigger: "change" }
    ],
    outputPolarity: [
      { required: true, message: "输出极性不能为空", trigger: "change" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢ä¼ æ„Ÿå™¨åˆ—表 */
const getList = async () => {
  loading.value = true;
  const res = await listSensor(queryParams.value);
  sensorList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  sensorFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: SensorVO[]) => {
  ids.value = selection.map(item => item.prodId);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加传感器";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: SensorVO) => {
  reset();
  const _prodId = row?.prodId || ids.value[0]
  const res = await getSensor(_prodId);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改传感器";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  sensorFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.prodId) {
        await updateSensor(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addSensor(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: SensorVO) => {
  const _prodIds = row?.prodId || ids.value;
  await proxy?.$modal.confirm('是否确认删除传感器编号为"' + _prodIds + '"的数据项?').finally(() => loading.value = false);
  await delSensor(_prodIds);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/sensor/export', {
    ...queryParams.value
  }, `sensor_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
  getList();
});
</script>
src/views/qms/sensorResult/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,274 @@
<template>
  <div class="p-2">
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:sensorResult:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:sensorResult:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:sensorResult:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:sensorResult:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" :columns="columns" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table
        v-loading="loading"
        :data="sensorResultList"
        :row-key="(row) => `${row.batchCode}-${row.testNum}`"
        stripe
        highlight-current-row
        indent="50"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="批次号" align="center" prop="batchCode" v-if="columns[0].visible" />
        <el-table-column label="测试序号" align="center" prop="testNum" v-if="columns[1].visible" />
        <el-table-column label="判定结果" align="center" prop="judgeResult" v-if="columns[2].visible" />
        <el-table-column label="总测试项数" align="center" prop="totalCount" v-if="columns[3].visible" />
        <el-table-column label="OK项数" align="center" prop="okCount" v-if="columns[4].visible" />
        <el-table-column label="NG项数" align="center" prop="ngCount" v-if="columns[5].visible" />
        <el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="明细" placement="top">
              <el-button link type="primary" icon="Document" @click="handleDetail(scope.row)"></el-button>
            </el-tooltip>
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:sensorResult:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:sensorResult:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æ‰¹æ¬¡æ˜Žç»†å¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="sensorResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="判定结果" prop="judgeResult">
          <el-input v-model="form.judgeResult" placeholder="请输入判定结果" />
        </el-form-item>
        <el-form-item label="总测试项数" prop="totalCount">
          <el-input v-model="form.totalCount" placeholder="请输入总测试项数" />
        </el-form-item>
        <el-form-item label="OK项数" prop="okCount">
          <el-input v-model="form.okCount" placeholder="请输入OK项数" />
        </el-form-item>
        <el-form-item label="NG项数" prop="ngCount">
          <el-input v-model="form.ngCount" placeholder="请输入NG项数" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="SensorResult" lang="ts">
import { listSensorResult, getSensorResult, delSensorResult, addSensorResult, updateSensorResult } from '@/api/qms/sensorResult';
import { SensorResultVO, SensorResultQuery, SensorResultForm } from '@/api/qms/sensorResult/types';
import { ref, reactive, watch, onMounted } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const sensorResultList = ref<SensorResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const sensorResultFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: SensorResultForm = {
  batchCode: undefined,
  testNum: undefined,
  judgeResult: undefined,
  totalCount: undefined,
  okCount: undefined,
  ngCount: undefined,
  createTime: undefined, // æ·»åŠ  createTime å­—段
}
const data = reactive<PageData<SensorResultForm, SensorResultQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    judgeResult: undefined,
    totalCount: undefined,
    okCount: undefined,
    ngCount: undefined,
    params: {
    }
  },
  rules: {
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    judgeResult: [
      { required: true, message: "判定结果不能为空", trigger: "blur" }
    ],
    totalCount: [
      { required: true, message: "总测试项数不能为空", trigger: "blur" }
    ],
    okCount: [
      { required: true, message: "OK项数不能为空", trigger: "blur" }
    ],
    ngCount: [
      { required: true, message: "NG项数不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
// æ·»åŠ  columns æ•°ç»„
const columns = ref<FieldOption[]>([
  { key: 0, label: '批次号', align: 'center', visible: true },
  { key: 1, label: '测试序号', align: 'center', visible: true },
  { key: 2, label: '判定结果', align: 'center', visible: true },
  { key: 3, label: '总测试项数', align: 'center', visible: true },
  { key: 4, label: 'OK项数', align: 'center', visible: true },
  { key: 5, label: 'NG项数', align: 'center', visible: true },
  { key: 6, label: '创建时间', align: 'center', visible: true },
]);
/** æŸ¥è¯¢æ‰¹æ¬¡æ˜Žç»†åˆ—表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.batchCode = proxy.$route.query.batchCode;
  const res = await listSensorResult(queryParams.value);
  sensorResultList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  sensorResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: SensorResultVO[]) => {
  ids.value = selection.map(item => item.batchCode);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加批次明细";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: SensorResultVO) => {
  reset();
  const _batchCode = row?.batchCode || ids.value[0]
  const res = await getSensorResult(_batchCode);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改批次明细";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  sensorResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.batchCode) {
        await updateSensorResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addSensorResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: SensorResultVO) => {
  const _batchCodes = row?.batchCode || ids.value;
  await proxy?.$modal.confirm('是否确认删除批次明细编号为"' + _batchCodes + '"的数据项?').finally(() => loading.value = false);
  await delSensorResult(_batchCodes);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/sensorResult/export', {
    ...queryParams.value
  }, `sensorResult_${new Date().getTime()}.xlsx`)
}
const handleDetail = (sensor) => {
  console.log("sensor", sensor)
  if (!sensor.retestNum) {
    proxy.$router.push({ path: 'testResult', query: {batchCode: sensor.batchCode, testNum: sensor.testNum} });
  } else {
    proxy.$router.push({ path: 'retestResult', query: {batchCode: sensor.batchCode.split("-")[0], testNum: sensor.testNum, retestNum: sensor.retestNum} });
  }
}
watch(()=>proxy.$route.query.batchCode,(batchCode)=>{
  console.log("batchCode", batchCode)
  if(batchCode) {
    getList();
  }
})
onMounted(() => {
  getList();
});
</script>
src/views/qms/sensorRetest/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,273 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="批次号" prop="batchCode">
              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试序号" prop="testNum">
              <el-input v-model="queryParams.testNum" placeholder="请输入测试序号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="复测次数" prop="retestNum">
              <el-input v-model="queryParams.retestNum" placeholder="请输入复测次数" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="设备号" prop="deviceCode">
              <el-input v-model="queryParams.deviceCode" placeholder="请输入设备号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="用户帐号" prop="userName">
              <el-input v-model="queryParams.userName" placeholder="请输入用户帐号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['lb-qms:sensorRetest:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['lb-qms:sensorRetest:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['lb-qms:sensorRetest:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['lb-qms:sensorRetest:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table
        v-loading="loading"
        :data="sensorRetestList"
        @selection-change="handleSelectionChange"
        stripe
        highlight-current-row
      >
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="批次号" align="center" prop="batchCode" v-if="true" />
        <el-table-column label="测试序号" align="center" prop="testNum" v-if="true" />
        <el-table-column label="复测次数" align="center" prop="retestNum" v-if="true" />
        <el-table-column label="设备号" align="center" prop="deviceCode" />
        <el-table-column label="用户帐号" align="center" prop="userName" />
        <el-table-column label="判定结果" align="center" prop="judgeResult" />
        <el-table-column label="总测试项数" align="center" prop="totalCount" />
        <el-table-column label="OK项数" align="center" prop="okCount" />
        <el-table-column label="NG项数" align="center" prop="ngCount" />
        <el-table-column label="备注" align="center" prop="remark" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['lb-qms:sensorRetest:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['lb-qms:sensorRetest:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹å¤æµ‹è®°å½•å¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="sensorRetestFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="设备号" prop="deviceCode">
          <el-input v-model="form.deviceCode" placeholder="请输入设备号" />
        </el-form-item>
        <el-form-item label="用户帐号" prop="userName">
          <el-input v-model="form.userName" placeholder="请输入用户帐号" />
        </el-form-item>
        <el-form-item label="判定结果" prop="judgeResult">
          <el-input v-model="form.judgeResult" placeholder="请输入判定结果" />
        </el-form-item>
        <el-form-item label="总测试项数" prop="totalCount">
          <el-input v-model="form.totalCount" placeholder="请输入总测试项数" />
        </el-form-item>
        <el-form-item label="OK项数" prop="okCount">
          <el-input v-model="form.okCount" placeholder="请输入OK项数" />
        </el-form-item>
        <el-form-item label="NG项数" prop="ngCount">
          <el-input v-model="form.ngCount" placeholder="请输入NG项数" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="SensorRetest" lang="ts">
import { listSensorRetest, getSensorRetest, delSensorRetest, addSensorRetest, updateSensorRetest } from 'src/api/qms/sensorRetest';
import { SensorRetestVO, SensorRetestQuery, SensorRetestForm } from '@/api/qms/sensorRetest/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const sensorRetestList = ref<SensorRetestVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const sensorRetestFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: SensorRetestForm = {
  batchCode: undefined,
  testNum: undefined,
  retestNum: undefined,
  deviceCode: undefined,
  userName: undefined,
  judgeResult: undefined,
  totalCount: undefined,
  okCount: undefined,
  ngCount: undefined,
  remark: undefined
}
const data = reactive<PageData<SensorRetestForm, SensorRetestQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    batchCode: undefined,
    testNum: undefined,
    retestNum: undefined,
    deviceCode: undefined,
    userName: undefined,
    params: {
    }
  },
  rules: {
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    retestNum: [
      { required: true, message: "复测次数不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢å¤æµ‹è®°å½•列表 */
const getList = async () => {
  loading.value = true;
  const res = await listSensorRetest(queryParams.value);
  sensorRetestList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  sensorRetestFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: SensorRetestVO[]) => {
  ids.value = selection.map(item => item.batchCode);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加复测记录";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: SensorRetestVO) => {
  reset();
  const _batchCode = row?.batchCode || ids.value[0]
  const res = await getSensorRetest(_batchCode);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改复测记录";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  sensorRetestFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.batchCode) {
        await updateSensorRetest(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addSensorRetest(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: SensorRetestVO) => {
  const _batchCodes = row?.batchCode || ids.value;
  await proxy?.$modal.confirm('是否确认删除复测记录编号为"' + _batchCodes + '"的数据项?').finally(() => loading.value = false);
  await delSensorRetest(_batchCodes);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/sensorRetest/export', {
    ...queryParams.value
  }, `sensorRetest_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
  getList();
});
</script>
src/views/qms/testResult/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,313 @@
<template>
  <div class="p-2">
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
<!--          <el-col :span="1.5">-->
<!--            <el-button v-hasPermi="['qms:testResult:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button v-hasPermi="['qms:testResult:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()"-->
<!--              >修改</el-button-->
<!--            >-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button v-hasPermi="['qms:testResult:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()"-->
<!--              >删除</el-button-->
<!--            >-->
<!--          </el-col>-->
<!--          <el-col :span="1.5">-->
<!--            <el-button v-hasPermi="['qms:testResult:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>-->
<!--          </el-col>-->
          <right-toolbar v-model:showSearch="showSearch" :columns="columns" @query-table="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" stripe highlight-current-row :data="testResultList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column v-if="false" label="" align="center" prop="id" />
        <el-table-column v-if="columns[0].visible" label="批次号" align="center" prop="batchCode" />
        <el-table-column v-if="columns[1].visible" label="测试序号" align="center" prop="testNum" />
        <el-table-column v-if="columns[2].visible" label="测试项目" align="center" prop="testItem" />
        <el-table-column v-if="columns[3].visible" label="实际电压" align="center" prop="voltage" />
        <el-table-column v-if="columns[4].visible" label="实际电流" align="center" prop="loadCurrent" />
        <el-table-column v-if="columns[5].visible" label="标准距离" align="center" prop="stdDistance" />
        <el-table-column v-if="columns[6].visible" label="感应物" align="center" prop="inductor" />
        <el-table-column v-if="columns[7].visible" label="输出引脚" align="center" prop="output" />
        <el-table-column v-if="columns[8].visible" label="测试数据" align="center" prop="testValue" />
        <el-table-column v-if="columns[9].visible" label="判断条件" align="center" prop="judgeDetail" />
        <el-table-column v-if="columns[10].visible" label="测试结果" align="center" prop="testResult" />
        <el-table-column v-if="columns[11].visible" label="备注" align="center" prop="remark" />
        <el-table-column v-if="columns[12].visible" label="创建时间" align="center" prop="createTime" width="160">
          <template #default="scope">
            <span>{{ scope.row.createTime }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button v-hasPermi="['qms:testResult:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button v-hasPermi="['qms:testResult:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ç»“æžœå¯¹è¯æ¡† -->
    <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body>
      <el-form ref="testResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="测试序号" prop="testNum">
          <el-input v-model="form.testNum" placeholder="请输入测试序号" />
        </el-form-item>
        <el-form-item label="测试项目" prop="testItem">
          <el-input v-model="form.testItem" placeholder="请输入测试项目" />
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="TestResult" lang="ts">
import { listTestResult, getTestResult, delTestResult, addTestResult, updateTestResult } from '@/api/qms/testResult';
import { TestResultVO, TestResultQuery, TestResultForm } from '@/api/qms/testResult/types';
import { ref, reactive, watch, onMounted, computed } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const testResultList = ref<TestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const testResultFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: TestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
};
const data = reactive<PageData<TestResultForm, TestResultQuery>>({
  form: { ...initFormData },
  queryParams: {
    pageNum: 1,
    pageSize: 20,
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    voltage: undefined,
    loadCurrent: undefined,
    stdDistance: undefined,
    inductor: undefined,
    output: undefined,
    testValue: undefined,
    judgeDetail: undefined,
    testResult: undefined,
    params: {}
  },
  rules: {
    id: [{ required: true, message: '不能为空', trigger: 'blur' }],
    batchCode: [{ required: true, message: '批次号不能为空', trigger: 'blur' }],
    testNum: [{ required: true, message: '测试序号不能为空', trigger: 'blur' }],
    testItem: [{ required: true, message: '测试项目不能为空', trigger: 'blur' }],
    voltage: [{ required: true, message: '实际电压不能为空', trigger: 'blur' }],
    loadCurrent: [{ required: true, message: '实际电流不能为空', trigger: 'blur' }],
    stdDistance: [{ required: true, message: '标准距离不能为空', trigger: 'blur' }],
    inductor: [{ required: true, message: '感应物不能为空', trigger: 'blur' }],
    output: [{ required: true, message: '输出引脚不能为空', trigger: 'blur' }],
    testValue: [{ required: true, message: '测试数据不能为空', trigger: 'blur' }],
    judgeDetail: [{ required: true, message: '判断条件不能为空', trigger: 'blur' }],
    testResult: [{ required: true, message: '测试结果不能为空', trigger: 'blur' }]
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢æµ‹è¯•结果列表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.batchCode = proxy.$route.query.batchCode;
  queryParams.value.testNum = proxy.$route.query.testNum;
  const res = await listTestResult(queryParams.value);
  testResultList.value = res.rows;
  total.value = res.total;
  loading.value = false;
};
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
};
/** è¡¨å•重置 */
const reset = () => {
  form.value = { ...initFormData };
  testResultFormRef.value?.resetFields();
};
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
};
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
};
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: TestResultVO[]) => {
  ids.value = selection.map((item) => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
};
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = '添加测试结果';
};
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: TestResultVO) => {
  reset();
  const _id = row?.id || ids.value[0];
  const res = await getTestResult(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = '修改测试结果';
};
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  testResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateTestResult(form.value).finally(() => (buttonLoading.value = false));
      } else {
        await addTestResult(form.value).finally(() => (buttonLoading.value = false));
      }
      proxy?.$modal.msgSuccess('操作成功');
      dialog.visible = false;
      await getList();
    }
  });
};
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: TestResultVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试结果编号为"' + _ids + '"的数据项?').finally(() => (loading.value = false));
  await delTestResult(_ids);
  proxy?.$modal.msgSuccess('删除成功');
  await getList();
};
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download(
    'qms/testResult/export',
    {
      ...queryParams.value
    },
    `testResult_${new Date().getTime()}.xlsx`
  );
};
watch(
  () => proxy.$route.query.testNum,
  (testNum) => {
    console.log('path', proxy.$route.path);
    console.log('testNum', testNum);
    if (proxy.$route.path === '/qms/testResult' && testNum) {
      queryParams.value.pageNum = 1;
      getList();
    }
  }
);
const columns = ref<FieldOption[]>([
  { key: 0, label: '批次号', align: 'center', visible: true },
  { key: 1, label: '测试序号', align: 'center', visible: true },
  { key: 2, label: '测试项目', align: 'center', visible: true },
  { key: 3, label: '实际电压', align: 'center', visible: true },
  { key: 4, label: '实际电流', align: 'center', visible: true },
  { key: 5, label: '标准距离', align: 'center', visible: true },
  { key: 6, label: '感应物', align: 'center', visible: true },
  { key: 7, label: '输出引脚', align: 'center', visible: true },
  { key: 8, label: '测试数据', align: 'center', visible: true },
  { key: 9, label: '判断条件', align: 'center', visible: true },
  { key: 10, label: '测试结果', align: 'center', visible: true },
  { key: 11, label: '备注', align: 'center', visible: true },
  { key: 12, label: `创建时间`, visible: true, children: [] }
]);
onMounted(() => {
  getList();
});
</script>
src/views/qms/testResult/index1.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,339 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="批次号" prop="batchCode">
              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试序号" prop="testNum">
              <el-input v-model="queryParams.testNum" placeholder="请输入测试序号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试项目" prop="testItem">
              <el-input v-model="queryParams.testItem" placeholder="请输入测试项目" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="实际电压" prop="voltage">
              <el-input v-model="queryParams.voltage" placeholder="请输入实际电压" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="实际电流" prop="loadCurrent">
              <el-input v-model="queryParams.loadCurrent" placeholder="请输入实际电流" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="标准距离" prop="stdDistance">
              <el-input v-model="queryParams.stdDistance" placeholder="请输入标准距离" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="感应物" prop="inductor">
              <el-input v-model="queryParams.inductor" placeholder="请输入感应物" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="输出引脚" prop="output">
              <el-input v-model="queryParams.output" placeholder="请输入输出引脚" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试数据" prop="testValue">
              <el-input v-model="queryParams.testValue" placeholder="请输入测试数据" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="判断条件" prop="judgeDetail">
              <el-input v-model="queryParams.judgeDetail" placeholder="请输入判断条件" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试结果" prop="testResult">
              <el-input v-model="queryParams.testResult" placeholder="请输入测试结果" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:testResult:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:testResult:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:testResult:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:testResult:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" :data="testResultList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="" align="center" prop="id" v-if="false" />
        <el-table-column label="批次号" align="center" prop="batchCode" />
        <el-table-column label="测试序号" align="center" prop="testNum" />
        <el-table-column label="测试项目" align="center" prop="testItem" />
        <el-table-column label="实际电压" align="center" prop="voltage" />
        <el-table-column label="实际电流" align="center" prop="loadCurrent" />
        <el-table-column label="标准距离" align="center" prop="stdDistance" />
        <el-table-column label="感应物" align="center" prop="inductor" />
        <el-table-column label="输出引脚" align="center" prop="output" />
        <el-table-column label="测试数据" align="center" prop="testValue" />
        <el-table-column label="判断条件" align="center" prop="judgeDetail" />
        <el-table-column label="测试结果" align="center" prop="testResult" />
        <el-table-column label="备注" align="center" prop="remark" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:testResult:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:testResult:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ç»“æžœå¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="testResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="测试序号" prop="testNum">
          <el-input v-model="form.testNum" placeholder="请输入测试序号" />
        </el-form-item>
        <el-form-item label="测试项目" prop="testItem">
          <el-input v-model="form.testItem" placeholder="请输入测试项目" />
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="TestResult" lang="ts">
import { listTestResult, getTestResult, delTestResult, addTestResult, updateTestResult } from '@/api/qms/testResult';
import { TestResultVO, TestResultQuery, TestResultForm } from '@/api/qms/testResult/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const testResultList = ref<TestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const testResultFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: TestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
}
const data = reactive<PageData<TestResultForm, TestResultQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 10,
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    voltage: undefined,
    loadCurrent: undefined,
    stdDistance: undefined,
    inductor: undefined,
    output: undefined,
    testValue: undefined,
    judgeDetail: undefined,
    testResult: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    testItem: [
      { required: true, message: "测试项目不能为空", trigger: "blur" }
    ],
    voltage: [
      { required: true, message: "实际电压不能为空", trigger: "blur" }
    ],
    loadCurrent: [
      { required: true, message: "实际电流不能为空", trigger: "blur" }
    ],
    stdDistance: [
      { required: true, message: "标准距离不能为空", trigger: "blur" }
    ],
    inductor: [
      { required: true, message: "感应物不能为空", trigger: "blur" }
    ],
    output: [
      { required: true, message: "输出引脚不能为空", trigger: "blur" }
    ],
    testValue: [
      { required: true, message: "测试数据不能为空", trigger: "blur" }
    ],
    judgeDetail: [
      { required: true, message: "判断条件不能为空", trigger: "blur" }
    ],
    testResult: [
      { required: true, message: "测试结果不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢æµ‹è¯•结果列表 */
const getList = async () => {
  loading.value = true;
  const res = await listTestResult(queryParams.value);
  testResultList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  testResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: TestResultVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加测试结果";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: TestResultVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getTestResult(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改测试结果";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  testResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateTestResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addTestResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: TestResultVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试结果编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delTestResult(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/testResult/export', {
    ...queryParams.value
  }, `testResult_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
  getList();
});
</script>
src/views/qms/testResult/index2.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,372 @@
<template>
  <div class="p-2">
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:testResult:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:testResult:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:testResult:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:testResult:export']">导出</el-button>
          </el-col>
          <right-toolbar :columns="columns" v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" :data="testResultList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <template v-for="col in visibleColumns" :key="col.prop">
          <el-table-column
            :label="col.label"
            :align="col.align"
            :prop="col.prop"
            v-if="col.visible"
          >
            <template #header="{ column }">
              <div @dblclick="handleColumnDoubleClick(column.property)">
                {{ column.label }}
              </div>
            </template>
          </el-table-column>
        </template>
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:testResult:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:testResult:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ç»“æžœå¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="testResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="测试序号" prop="testNum">
          <el-input v-model="form.testNum" placeholder="请输入测试序号" />
        </el-form-item>
        <el-form-item label="测试项目" prop="testItem">
          <el-input v-model="form.testItem" placeholder="请输入测试项目" />
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- åˆ—选择对话框 -->
    <el-dialog title="选择列" v-model="showColumnSelector" width="300px" append-to-body @close="showColumnSelector = false">
      <el-checkbox-group v-model="selectedColumns">
        <el-checkbox v-for="column in columns" :key="column.prop" :label="column.prop">{{ column.label }}</el-checkbox>
      </el-checkbox-group>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="saveColumnSelection">ç¡® å®š</el-button>
          <el-button @click="showColumnSelector = false">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="TestResult" lang="ts">
import { listTestResult, getTestResult, delTestResult, addTestResult, updateTestResult } from '@/api/qms/testResult';
import { TestResultVO, TestResultQuery, TestResultForm } from '@/api/qms/testResult/types';
import { ref, reactive, watch, onMounted, computed } from 'vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const testResultList = ref<TestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const queryFormRef = ref<ElFormInstance>();
const testResultFormRef = ref<ElFormInstance>();
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: TestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
}
const data = reactive<PageData<TestResultForm, TestResultQuery>>({
  form: {...initFormData},
  queryParams: {
    pageNum: 1,
    pageSize: 20,
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    voltage: undefined,
    loadCurrent: undefined,
    stdDistance: undefined,
    inductor: undefined,
    output: undefined,
    testValue: undefined,
    judgeDetail: undefined,
    testResult: undefined,
    params: {
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    testItem: [
      { required: true, message: "测试项目不能为空", trigger: "blur" }
    ],
    voltage: [
      { required: true, message: "实际电压不能为空", trigger: "blur" }
    ],
    loadCurrent: [
      { required: true, message: "实际电流不能为空", trigger: "blur" }
    ],
    stdDistance: [
      { required: true, message: "标准距离不能为空", trigger: "blur" }
    ],
    inductor: [
      { required: true, message: "感应物不能为空", trigger: "blur" }
    ],
    output: [
      { required: true, message: "输出引脚不能为空", trigger: "blur" }
    ],
    testValue: [
      { required: true, message: "测试数据不能为空", trigger: "blur" }
    ],
    judgeDetail: [
      { required: true, message: "判断条件不能为空", trigger: "blur" }
    ],
    testResult: [
      { required: true, message: "测试结果不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
/** æŸ¥è¯¢æµ‹è¯•结果列表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.batchCode = proxy.$route.query.batchCode;
  queryParams.value.testNum = proxy.$route.query.testNum;
  const res = await listTestResult(queryParams.value);
  testResultList.value = res.rows;
  total.value = res.total;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  testResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  queryParams.value.pageNum = 1;
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  queryFormRef.value?.resetFields();
  handleQuery();
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: TestResultVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加测试结果";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: TestResultVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getTestResult(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改测试结果";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  testResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateTestResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addTestResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: TestResultVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试结果编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delTestResult(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/testResult/export', {
    ...queryParams.value
  }, `testResult_${new Date().getTime()}.xlsx`)
}
const columns = [
  { prop: 'id', label: 'ID', align: 'center', visible: false },
  { prop: 'batchCode', label: '批次号', align: 'center', visible: true },
  { prop: 'testNum', label: '测试序号', align: 'center', visible: true },
  { prop: 'testItem', label: '测试项目', align: 'center', visible: true },
  { prop: 'voltage', label: '实际电压', align: 'center', visible: true },
  { prop: 'loadCurrent', label: '实际电流', align: 'center', visible: true },
  { prop: 'stdDistance', label: '标准距离', align: 'center', visible: true },
  { prop: 'inductor', label: '感应物', align: 'center', visible: true },
  { prop: 'output', label: '输出引脚', align: 'center', visible: true },
  { prop: 'testValue', label: '测试数据', align: 'center', visible: true },
  { prop: 'judgeDetail', label: '判断条件', align: 'center', visible: true },
  { prop: 'testResult', label: '测试结果', align: 'center', visible: true },
  { prop: 'remark', label: '备注', align: 'center', visible: true }
];
const selectedColumns = ref(columns.map(column => column.prop));
const visibleColumns = computed(() => {
  // æ·»åŠ ä¾èµ–é¡¹ï¼Œç¡®ä¿å½“ selectedColumns å˜åŒ–时,visibleColumns ä¹Ÿä¼šé‡æ–°è®¡ç®—
  return columns.filter(column => selectedColumns.value.includes(column.prop));
});
// æ–°å¢ž watch ç›‘听器,监听 selectedColumns çš„变化
watch(()=> selectedColumns.value, (newSelectedColumns) => {
  console.log("selectedColumns", selectedColumns.value)
  columns.forEach(column => {
    column.visible = newSelectedColumns.includes(column.prop);
  });
});
const handleColumnDoubleClick = (prop: string) => {
  // æ–°å¢žåŒå‡»äº‹ä»¶å¤„理函数
  console.log('双击列:', prop);
  const column = columns.find(col => col.prop === prop);
  console.log(column)
  if (column) {
    column.visible = !column.visible;
  }
  selectedColumns.value = columns.filter(col => col.visible).map(col => col.prop);
  // // ç¡®ä¿ columns çš„ visible å±žæ€§åŒæ­¥æ›´æ–°
  // columns.forEach(col => {
  //   col.visible = selectedColumns.value.includes(col.prop);
  // });
};
const saveColumnSelection = () => {
  columns.forEach(column => {
    column.visible = selectedColumns.value.includes(column.prop);
  });
};
watch(() => proxy.$route.query.testNum, (testNum) => {
  console.log("testNum", testNum)
  if(testNum) {
    queryParams.value.pageNum = 1;
    getList();
  }
})
onMounted(() => {
  getList();
});
</script>
src/views/qms/trend/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,467 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="产品型号" prop="prodModel">
              <el-select v-model="queryParams.prodModel" placeholder="请选择产品型号" clearable @keyup.enter="handleQuery">
                <el-option v-for="item in prodModelOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="测试项目" prop="testItem">
              <el-select v-model="selectedTestItems" :multiple="true" placeholder="请选择测试项目" clearable @keyup.enter="handleQuery">
                <el-option v-for="item in testItemsOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="批次号" prop="batchCode">
              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="创建时间" style="width: 308px">
              <el-date-picker
                v-model="dateRangeCreateTime"
                value-format="YYYY-MM-DD"
                type="daterange"
                range-separator="-"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                unlink-panels
                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:testResult:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:testResult:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:testResult:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:testResult:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="handleQuery"></right-toolbar>
        </el-row>
      </template>
      <div ref="chartRef" style="width: 100%; height: 660px;"></div>
      <!--      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />-->
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ç»“æžœå¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="testResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="测试序号" prop="testNum">
          <el-input v-model="form.testNum" placeholder="请输入测试序号" />
        </el-form-item>
        <el-form-item label="测试项目" prop="testItem">
          <el-select v-model="form.testItem" placeholder="请选择测试项目">
            <el-option v-for="item in testItemsOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="TestResult" lang="ts">
import { listTestResultAll, getTestResult, delTestResult, addTestResult, updateTestResult, listTestItem } from '@/api/qms/testResult';
import { TestResultVO, TestResultQuery, TestResultForm } from '@/api/qms/testResult/types';
import * as echarts from 'echarts';
import { listProdModels} from '@/api/qms/batch';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const testResultList = ref<TestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
// è®¾ç½®é»˜è®¤æ—¶é—´ä¸ºæœ€è¿‘一个月
const now = new Date();
const dateRangeCreateTime = ref<[DateModelType, DateModelType]>([]);
const oneMonthAgo = new Date(now.getFullYear(), now.getMonth() - 1, now.getDate());
dateRangeCreateTime.value = [oneMonthAgo.toISOString().split('T')[0], now.toISOString().split('T')[0]] as [DateModelType, DateModelType];
const queryFormRef = ref<ElFormInstance>();
const testResultFormRef = ref<ElFormInstance>();
const chartRef = ref<HTMLDivElement | null>(null); // æ–°å¢ž chartRef å¼•用
const testItemsOptions = ref<{ label: string, value: string }[]>([]); // æ–°å¢žæµ‹è¯•项目选项
const selectedTestItems = ref<string | string[]>([]); // ä¿®æ”¹ä¸ºå…¼å®¹å•选的类型
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: TestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
}
const prodModelOptions = ref<{ label: string, value: string }[]>([]);
const data = reactive<PageData<TestResultForm, TestResultQuery>>({
  form: {...initFormData},
  queryParams: {
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    voltage: undefined,
    loadCurrent: undefined,
    stdDistance: undefined,
    inductor: undefined,
    output: undefined,
    testValue: undefined,
    judgeDetail: undefined,
    testResult: undefined,
    startTime: undefined, // æ–°å¢ž startTime å­—段
    endTime: undefined, // æ–°å¢ž endTime å­—段
    prodModel: undefined, // æ–°å¢žäº§å“åž‹å·å­—段
    params: {
      createTime: undefined,
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    testItem: [
      { required: true, message: "测试项目不能为空", trigger: "blur" }
    ],
    voltage: [
      { required: true, message: "实际电压不能为空", trigger: "blur" }
    ],
    loadCurrent: [
      { required: true, message: "实际电流不能为空", trigger: "blur" }
    ],
    stdDistance: [
      { required: true, message: "标准距离不能为空", trigger: "blur" }
    ],
    inductor: [
      { required: true, message: "感应物不能为空", trigger: "blur" }
    ],
    output: [
      { required: true, message: "输出引脚不能为空", trigger: "blur" }
    ],
    testValue: [
      { required: true, message: "测试数据不能为空", trigger: "blur" }
    ],
    judgeDetail: [
      { required: true, message: "判断条件不能为空", trigger: "blur" }
    ],
    testResult: [
      { required: true, message: "测试结果不能为空", trigger: "blur" }
    ],
    prodModel: [
      { required: true, message: "产品型号不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
// èŽ·å–æ‰€æœ‰æµ‹è¯•é¡¹ç›®
const fetchTestItems = async () => {
  const res = await listTestItem();
  testItemsOptions.value = res.data.map(item => ({ label: item, value: item }));
}
// èŽ·å–æ‰€æœ‰äº§å“åž‹å·
const fetchProdModels = async () => {
  const res = await listProdModels();
  prodModelOptions.value = res.data.map(item => ({ label: item, value: item }));
}
/** æŸ¥è¯¢æµ‹è¯•结果列表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.params = {};
  // å¤„理 selectedTestItems çš„值,兼容单选和多选
  if (Array.isArray(selectedTestItems.value)) {
    queryParams.value.testItem = selectedTestItems.value.join(','); // å¤šé€‰æ¨¡å¼
  } else {
    queryParams.value.testItem = selectedTestItems.value; // å•选模式
  }
  proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, 'CreateTime');
  const res = await listTestResultAll(queryParams.value);
  testResultList.value = res.data;
  loading.value = false;
  updateChart(); // æ›´æ–°å›¾è¡¨
}
// ç›‘听 testResultList çš„变化,动态更新图表
watch(testResultList, () => {
  updateChart();
});
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  testResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  // æ ¡éªŒæ—¶é—´èŒƒå›´æ˜¯å¦è¶…过三个月
  if (dateRangeCreateTime.value[0] && dateRangeCreateTime.value[1]) {
    const startDate = new Date(dateRangeCreateTime.value[0]);
    const endDate = new Date(dateRangeCreateTime.value[1]);
    const timeDiff = endDate.getTime() - startDate.getTime();
    const maxDuration = 90 * 24 * 60 * 60 * 1000; // ä¸‰ä¸ªæœˆçš„æ¯«ç§’æ•°
    if (timeDiff > maxDuration) {
      proxy?.$modal.msgWarning("时间范围不能超过三个月,请重新选择!");
      return;
    }
  }
  // æ ¡éªŒäº§å“åž‹å·æ˜¯å¦é€‰æ‹©
  if (!queryParams.value.prodModel) {
    proxy?.$modal.msgWarning("请选择产品型号!");
    return;
  }
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  dateRangeCreateTime.value = ['', ''];
  queryFormRef.value?.resetFields();
  selectedTestItems.value = []; // é‡ç½®é€‰ä¸­çš„æµ‹è¯•项目
  reset(); // è°ƒç”¨é‡ç½®æ–¹æ³•以清空时间段字段
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: TestResultVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加测试结果";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: TestResultVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getTestResult(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改测试结果";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  testResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateTestResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addTestResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await handleQuery();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: TestResultVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试结果编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delTestResult(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await handleQuery();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/testResult/export', {
    ...queryParams.value
  }, `testResult_${new Date().getTime()}.xlsx`)
}
// æ›´æ–°å›¾è¡¨
const updateChart = () => {
  if (!chartRef.value) return;
  const chart = echarts.init(chartRef.value);
  // å®šä¹‰20个不重复的颜色池
  const colorPool = [
    '#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de',
    '#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#5e7ce0',
    '#f0c757', '#ff9f7f', '#d48265', '#7fb80e', '#b37feb',
    '#4dc9b0', '#f47920', '#65b581', '#f08585', '#4a90e2',
    // æ–°å¢žé¢œè‰²ä»¥æé«˜å¯¹æ¯”度
    '#ff6f61', '#ffd700', '#00ced1', '#da70d6', '#adff2f'
  ];
  // ä½¿ç”¨Map替代Object更高效
  const seriesMap = new Map<string, [string, number][]>();
  testResultList.value.forEach(item => {
    const key = item.testItem;
    if (!seriesMap.has(key)) {
      seriesMap.set(key, []);
    }
    seriesMap.get(key)?.push([item.createTime, item.testValue]);
  });
  const option = {
    grid: {
      top: '15%',
      left: '5%',
      right: '5%',
      containLabel: true
    },
    xAxis: {
      type: 'time',
      name: '时间'
    },
    yAxis: {
      type: 'value',
      name: '测试数据'
    },
    legend: {
      data: Array.from(seriesMap.keys())
    },
    series: Array.from(seriesMap).map(([name, data], index) => ({
      name: name,
      data: data,
      type: 'line',
      animationDuration: 1000,
      lineStyle: {
        color: colorPool[index % colorPool.length],
        width: 3 // å¢žåŠ çº¿æ¡å®½åº¦
      },
      itemStyle: {
        color: colorPool[index % colorPool.length],
        opacity: 0.8 // æ·»åŠ é€æ˜Žåº¦
      }
    })),
    // æ–°å¢ž dataZoom é…ç½®
    dataZoom: [
      {
        type: 'slider', // X轴滑动条
        xAxisIndex: 0,
        start: 0, // åˆå§‹èŒƒå›´èµ·ç‚¹ç™¾åˆ†æ¯”
        end: 100 // åˆå§‹èŒƒå›´ç»ˆç‚¹ç™¾åˆ†æ¯”
      },
      {
        type: 'slider', // Y轴滑动条
        yAxisIndex: 0,
        start: 0, // åˆå§‹èŒƒå›´èµ·ç‚¹ç™¾åˆ†æ¯”
        end: 100 // åˆå§‹èŒƒå›´ç»ˆç‚¹ç™¾åˆ†æ¯”
      },
      {
        type: 'inside', // X轴内置拖动和框选
        xAxisIndex: 0,
        start: 0,
        end: 100
      },
      {
        type: 'inside', // Y轴内置拖动和框选
        yAxisIndex: 0,
        start: 0,
        end: 100
      }
    ]
  };
  chart.setOption(option, true);
  window.addEventListener('resize', () => {
    chart.resize();
  });
}
onMounted(() => {
  fetchTestItems(); // è°ƒç”¨èŽ·å–æµ‹è¯•é¡¹ç›®æŽ¥å£
  fetchProdModels(); // è°ƒç”¨èŽ·å–äº§å“åž‹å·æŽ¥å£
});
</script>
src/views/qms/trend/index1.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,349 @@
<template>
  <div class="p-2">
    <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
      <div v-show="showSearch" class="mb-[10px]">
        <el-card shadow="hover">
          <el-form ref="queryFormRef" :model="queryParams" :inline="true">
            <el-form-item label="批次号" prop="batchCode">
              <el-input v-model="queryParams.batchCode" placeholder="请输入批次号" clearable @keyup.enter="handleQuery" />
            </el-form-item>
            <el-form-item label="测试项目" prop="testItem">
              <el-select v-model="selectedTestItems" :multiple="true" placeholder="请选择测试项目" clearable @keyup.enter="handleQuery">
                <el-option v-for="item in testItemsOptions" :key="item.value" :label="item.label" :value="item.value" />
              </el-select>
            </el-form-item>
            <el-form-item label="创建时间" style="width: 308px">
              <el-date-picker
                v-model="dateRangeCreateTime"
                value-format="YYYY-MM-DD"
                type="daterange"
                range-separator="-"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                unlink-panels
                :default-time="[new Date(2000, 1, 1, 0, 0, 0), new Date(2000, 1, 1, 23, 59, 59)]"
              />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
              <el-button icon="Refresh" @click="resetQuery">重置</el-button>
            </el-form-item>
          </el-form>
        </el-card>
      </div>
    </transition>
    <el-card shadow="never">
      <template #header>
        <el-row :gutter="10" class="mb8">
          <el-col :span="1.5">
            <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['qms:testResult:add']">新增</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" v-hasPermi="['qms:testResult:edit']">修改</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" v-hasPermi="['qms:testResult:remove']">删除</el-button>
          </el-col>
          <el-col :span="1.5">
            <el-button type="warning" plain icon="Download" @click="handleExport" v-hasPermi="['qms:testResult:export']">导出</el-button>
          </el-col>
          <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
        </el-row>
      </template>
      <el-table v-loading="loading" :data="testResultList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="" align="center" prop="id" v-if="false" />
        <el-table-column label="批次号" align="center" prop="batchCode" />
        <el-table-column label="测试序号" align="center" prop="testNum" />
        <el-table-column label="测试项目" align="center" prop="testItem" />
        <el-table-column label="实际电压" align="center" prop="voltage" />
        <el-table-column label="实际电流" align="center" prop="loadCurrent" />
        <el-table-column label="标准距离" align="center" prop="stdDistance" />
        <el-table-column label="感应物" align="center" prop="inductor" />
        <el-table-column label="输出引脚" align="center" prop="output" />
        <el-table-column label="测试数据" align="center" prop="testValue" />
        <el-table-column label="判断条件" align="center" prop="judgeDetail" />
        <el-table-column label="测试结果" align="center" prop="testResult" />
        <el-table-column label="备注" align="center" prop="remark" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-tooltip content="修改" placement="top">
              <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['qms:testResult:edit']"></el-button>
            </el-tooltip>
            <el-tooltip content="删除" placement="top">
              <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['qms:testResult:remove']"></el-button>
            </el-tooltip>
          </template>
        </el-table-column>
      </el-table>
<!--      <pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" @pagination="getList" />-->
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹æµ‹è¯•ç»“æžœå¯¹è¯æ¡† -->
    <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body>
      <el-form ref="testResultFormRef" :model="form" :rules="rules" label-width="80px">
        <el-form-item label="批次号" prop="batchCode">
          <el-input v-model="form.batchCode" placeholder="请输入批次号" />
        </el-form-item>
        <el-form-item label="测试序号" prop="testNum">
          <el-input v-model="form.testNum" placeholder="请输入测试序号" />
        </el-form-item>
        <el-form-item label="测试项目" prop="testItem">
          <el-select v-model="form.testItem" placeholder="请选择测试项目">
            <el-option v-for="item in testItemsOptions" :key="item.value" :label="item.label" :value="item.value" />
          </el-select>
        </el-form-item>
        <el-form-item label="实际电压" prop="voltage">
          <el-input v-model="form.voltage" placeholder="请输入实际电压" />
        </el-form-item>
        <el-form-item label="实际电流" prop="loadCurrent">
          <el-input v-model="form.loadCurrent" placeholder="请输入实际电流" />
        </el-form-item>
        <el-form-item label="标准距离" prop="stdDistance">
          <el-input v-model="form.stdDistance" placeholder="请输入标准距离" />
        </el-form-item>
        <el-form-item label="感应物" prop="inductor">
          <el-input v-model="form.inductor" placeholder="请输入感应物" />
        </el-form-item>
        <el-form-item label="输出引脚" prop="output">
          <el-input v-model="form.output" placeholder="请输入输出引脚" />
        </el-form-item>
        <el-form-item label="测试数据" prop="testValue">
          <el-input v-model="form.testValue" placeholder="请输入测试数据" />
        </el-form-item>
        <el-form-item label="判断条件" prop="judgeDetail">
          <el-input v-model="form.judgeDetail" placeholder="请输入判断条件" />
        </el-form-item>
        <el-form-item label="测试结果" prop="testResult">
          <el-input v-model="form.testResult" placeholder="请输入测试结果" />
        </el-form-item>
        <el-form-item label="备注" prop="remark">
          <el-input v-model="form.remark" placeholder="请输入备注" />
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button :loading="buttonLoading" type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup name="TestResult" lang="ts">
import { listTestResultAll, getTestResult, delTestResult, addTestResult, updateTestResult, listTestItem } from '@/api/qms/testResult';
import { TestResultVO, TestResultQuery, TestResultForm } from '@/api/qms/testResult/types';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const testResultList = ref<TestResultVO[]>([]);
const buttonLoading = ref(false);
const loading = ref(true);
const showSearch = ref(true);
const ids = ref<Array<string | number>>([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const dateRangeCreateTime = ref<[DateModelType, DateModelType]>(['', '']);
const queryFormRef = ref<ElFormInstance>();
const testResultFormRef = ref<ElFormInstance>();
const testItemsOptions = ref<{ label: string, value: string }[]>([]); // æ–°å¢žæµ‹è¯•项目选项
const selectedTestItems = ref<string | string[]>([]); // ä¿®æ”¹ä¸ºå…¼å®¹å•选的类型
const dialog = reactive<DialogOption>({
  visible: false,
  title: ''
});
const initFormData: TestResultForm = {
  id: undefined,
  batchCode: undefined,
  testNum: undefined,
  testItem: undefined,
  voltage: undefined,
  loadCurrent: undefined,
  stdDistance: undefined,
  inductor: undefined,
  output: undefined,
  testValue: undefined,
  judgeDetail: undefined,
  testResult: undefined,
  remark: undefined
}
const data = reactive<PageData<TestResultForm, TestResultQuery>>({
  form: {...initFormData},
  queryParams: {
    batchCode: undefined,
    testNum: undefined,
    testItem: undefined,
    voltage: undefined,
    loadCurrent: undefined,
    stdDistance: undefined,
    inductor: undefined,
    output: undefined,
    testValue: undefined,
    judgeDetail: undefined,
    testResult: undefined,
    startTime: undefined, // æ–°å¢ž startTime å­—段
    endTime: undefined, // æ–°å¢ž endTime å­—段
    params: {
      createTime: undefined,
    }
  },
  rules: {
    id: [
      { required: true, message: "不能为空", trigger: "blur" }
    ],
    batchCode: [
      { required: true, message: "批次号不能为空", trigger: "blur" }
    ],
    testNum: [
      { required: true, message: "测试序号不能为空", trigger: "blur" }
    ],
    testItem: [
      { required: true, message: "测试项目不能为空", trigger: "blur" }
    ],
    voltage: [
      { required: true, message: "实际电压不能为空", trigger: "blur" }
    ],
    loadCurrent: [
      { required: true, message: "实际电流不能为空", trigger: "blur" }
    ],
    stdDistance: [
      { required: true, message: "标准距离不能为空", trigger: "blur" }
    ],
    inductor: [
      { required: true, message: "感应物不能为空", trigger: "blur" }
    ],
    output: [
      { required: true, message: "输出引脚不能为空", trigger: "blur" }
    ],
    testValue: [
      { required: true, message: "测试数据不能为空", trigger: "blur" }
    ],
    judgeDetail: [
      { required: true, message: "判断条件不能为空", trigger: "blur" }
    ],
    testResult: [
      { required: true, message: "测试结果不能为空", trigger: "blur" }
    ],
  }
});
const { queryParams, form, rules } = toRefs(data);
// èŽ·å–æ‰€æœ‰æµ‹è¯•é¡¹ç›®
const fetchTestItems = async () => {
  const res = await listTestItem();
  testItemsOptions.value = res.data.map(item => ({ label: item, value: item }));
}
/** æŸ¥è¯¢æµ‹è¯•结果列表 */
const getList = async () => {
  loading.value = true;
  queryParams.value.params = {};
  // å¤„理 selectedTestItems çš„值,兼容单选和多选
  if (Array.isArray(selectedTestItems.value)) {
    queryParams.value.testItem = selectedTestItems.value.join(','); // å¤šé€‰æ¨¡å¼
  } else {
    queryParams.value.testItem = selectedTestItems.value; // å•选模式
  }
  proxy?.addDateRange(queryParams.value, dateRangeCreateTime.value, 'CreateTime');
  const res = await listTestResultAll(queryParams.value);
  testResultList.value = res.data;
  loading.value = false;
}
/** å–消按钮 */
const cancel = () => {
  reset();
  dialog.visible = false;
}
/** è¡¨å•重置 */
const reset = () => {
  form.value = {...initFormData};
  testResultFormRef.value?.resetFields();
}
/** æœç´¢æŒ‰é’®æ“ä½œ */
const handleQuery = () => {
  console.log("queryParams::",queryParams.value)
  getList();
}
/** é‡ç½®æŒ‰é’®æ“ä½œ */
const resetQuery = () => {
  dateRangeCreateTime.value = ['', ''];
  queryFormRef.value?.resetFields();
  selectedTestItems.value = []; // é‡ç½®é€‰ä¸­çš„æµ‹è¯•项目
  reset(); // è°ƒç”¨é‡ç½®æ–¹æ³•以清空时间段字段
}
/** å¤šé€‰æ¡†é€‰ä¸­æ•°æ® */
const handleSelectionChange = (selection: TestResultVO[]) => {
  ids.value = selection.map(item => item.id);
  single.value = selection.length != 1;
  multiple.value = !selection.length;
}
/** æ–°å¢žæŒ‰é’®æ“ä½œ */
const handleAdd = () => {
  reset();
  dialog.visible = true;
  dialog.title = "添加测试结果";
}
/** ä¿®æ”¹æŒ‰é’®æ“ä½œ */
const handleUpdate = async (row?: TestResultVO) => {
  reset();
  const _id = row?.id || ids.value[0]
  const res = await getTestResult(_id);
  Object.assign(form.value, res.data);
  dialog.visible = true;
  dialog.title = "修改测试结果";
}
/** æäº¤æŒ‰é’® */
const submitForm = () => {
  testResultFormRef.value?.validate(async (valid: boolean) => {
    if (valid) {
      buttonLoading.value = true;
      if (form.value.id) {
        await updateTestResult(form.value).finally(() =>  buttonLoading.value = false);
      } else {
        await addTestResult(form.value).finally(() =>  buttonLoading.value = false);
      }
      proxy?.$modal.msgSuccess("操作成功");
      dialog.visible = false;
      await getList();
    }
  });
}
/** åˆ é™¤æŒ‰é’®æ“ä½œ */
const handleDelete = async (row?: TestResultVO) => {
  const _ids = row?.id || ids.value;
  await proxy?.$modal.confirm('是否确认删除测试结果编号为"' + _ids + '"的数据项?').finally(() => loading.value = false);
  await delTestResult(_ids);
  proxy?.$modal.msgSuccess("删除成功");
  await getList();
}
/** å¯¼å‡ºæŒ‰é’®æ“ä½œ */
const handleExport = () => {
  proxy?.download('qms/testResult/export', {
    ...queryParams.value
  }, `testResult_${new Date().getTime()}.xlsx`)
}
onMounted(() => {
  getList();
  fetchTestItems(); // è°ƒç”¨èŽ·å–æµ‹è¯•é¡¹ç›®æŽ¥å£
});
</script>
src/views/register.vue
@@ -2,7 +2,7 @@
  <div class="register">
    <el-form ref="registerRef" :model="registerForm" :rules="registerRules" class="register-form">
      <div class="title-box">
        <h3 class="title">RuoYi-Vue-Plus多租户管理系统</h3>
        <h3 class="title">兰宝车间质量管理系统</h3>
        <lang-select />
      </div>
      <el-form-item v-if="tenantEnabled" prop="tenantId">
tsconfig.json
@@ -2,7 +2,7 @@
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    //    "useDefineForClassFields": true,
//    "useDefineForClassFields": true,
    "moduleResolution": "bundler",
    "strict": true,
    "jsx": "preserve",
vite.config.ts
@@ -64,6 +64,16 @@
        'echarts',
        'vue-i18n',
        '@vueup/vue-quill',
        'bpmn-js/lib/Viewer',
        'bpmn-js/lib/Modeler.js',
        'bpmn-js-properties-panel',
        'min-dash',
        'diagram-js/lib/navigation/movecanvas',
        'diagram-js/lib/navigation/zoomscroll',
        'bpmn-js/lib/features/palette/PaletteProvider',
        'bpmn-js/lib/features/context-pad/ContextPadProvider',
        'diagram-js/lib/draw/BaseRenderer',
        'tiny-svg',
        'image-conversion',
        'element-plus/es/components/**/css'
      ]
vite/plugins/i18n.ts
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
export default (path: any) => {
  return VueI18nPlugin({
    include: [path.resolve(__dirname, '../../src/lang/**.json')]
  });
};