已添加1个文件
已修改26个文件
已删除57个文件
| | |
| | | "env": { |
| | | "VITE_APP_TITLE": "è¯å¯¼äºï¼ç®¡çä¿¡æ¯ç³»ç»ï¼" |
| | | }, |
| | | "screen": "screen/PCDZView.png", |
| | | "logo": "logo/Logo.png", |
| | | "favicon": "favicon/favicon.ico" |
| | | }, |
| | | "TEST": { |
| | | "DLS": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "工忰ååMOMç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9048", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9049" |
| | | "VITE_APP_TITLE": "æ°ç大ç½ç´ 马éè¯ä¿¡æ¯ç®¡ç", |
| | | "VITE_BASE_API": "http://1.15.17.182:9027", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9026" |
| | | }, |
| | | "logo": "logo/XDRJ.png", |
| | | "screen": "screen/login-background.png", |
| | | "logo": "logo/Logo.png", |
| | | "favicon": "favicon/favicon.ico" |
| | | }, |
| | | "BTYX": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ²³å帮太ä¼éé£åæéå
¬å¸", |
| | | "VITE_BASE_API": "http://1.15.17.182:9056", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9057" |
| | | }, |
| | | "logo": "logo/BTYXLogo.png", |
| | | "favicon": "favicon/BTYXfavicon.ico" |
| | | }, |
| | | "ZXZN": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ²³åæºè¯æºè½æºå¨äººæéå
¬å¸", |
| | | "VITE_BASE_API": "http://127.0.0.1:9001", |
| | | "VITE_JAVA_API": "http://127.0.0.1:9000" |
| | | }, |
| | | "logo": "logo/ZXZNLogo.png", |
| | | "favicon": "favicon/ZXZNfavicon.ico" |
| | | }, |
| | | "SDTX": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ²³ååé¼éä¿¡ç§ææéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.213.156.184:9001", |
| | | "VITE_JAVA_API": "http://36.213.156.184:9000" |
| | | }, |
| | | "logo": "logo/SDTXLogo.png", |
| | | "favicon": "favicon/SDTXfavicon.ico" |
| | | }, |
| | | "QXY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "强信å®çµå¨ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://36.134.154.10:9001", |
| | | "VITE_JAVA_API": "http://36.134.154.10:9000" |
| | | }, |
| | | "logo": "logo/QXYLogo.png", |
| | | "favicon": "favicon/QXYfavicon.ico" |
| | | }, |
| | | "HQJC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å强建æç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://36.134.77.64:9001", |
| | | "VITE_JAVA_API": "http://36.134.77.64:9000" |
| | | }, |
| | | "logo": "logo/HQJCLogo.png", |
| | | "favicon": "favicon/HQJCfavicon.ico" |
| | | }, |
| | | "XCDQ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ææ¨çµå¨ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://36.133.45.183:9001", |
| | | "VITE_JAVA_API": "http://36.133.45.183:9002" |
| | | }, |
| | | "logo": "logo/XCDQLogo.png", |
| | | "favicon": "favicon/XCDQfavicon.ico" |
| | | }, |
| | | "BWSM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å
«ç»´å贸管çç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9070", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9069" |
| | | }, |
| | | "logo": "logo/BWSMLogo.png", |
| | | "favicon": "favicon/BWSMfavicon.ico" |
| | | }, |
| | | "CKGM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "宸康工贸管çç³»ç»", |
| | | "VITE_BASE_API": "http://1.15.17.182:9072", |
| | | "VITE_JAVA_API": "http://1.15.17.182:9071" |
| | | }, |
| | | "logo": "logo/CKGMLogo.png", |
| | | "favicon": "favicon/CKGMfavicon.ico" |
| | | }, |
| | | "ZQSY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æ³½æ·å®ä¸", |
| | | "VITE_BASE_API": "http://36.213.128.159:9000", |
| | | "VITE_JAVA_API": "http://36.213.128.159:9001" |
| | | }, |
| | | "logo": "logo/ZQSYLogo.png", |
| | | "favicon": "favicon/ZQSYfavicon.ico" |
| | | }, |
| | | "JXJH": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "æµå¿æ±æµ·æ°´æ³¥å¶åæéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.139.201.20:9000", |
| | | "VITE_JAVA_API": "http://36.139.201.20:9001" |
| | | }, |
| | | "logo": "logo/JXJHLogo.png", |
| | | "favicon": "favicon/JXJHfavicon.ico" |
| | | }, |
| | | "YTJZ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "è±«æ³°å»ºçæææéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.139.201.181:9000", |
| | | "VITE_JAVA_API": "http://36.139.201.181:9001" |
| | | }, |
| | | "logo": "logo/YTJZLogo.png", |
| | | "favicon": "favicon/YTJZfavicon.ico" |
| | | }, |
| | | "HYLQ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "èªé¸è·¯æ¡¥å·¥ç¨æéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.139.202.111:9000", |
| | | "VITE_JAVA_API": "http://36.139.202.111:9001" |
| | | }, |
| | | "logo": "logo/HYLQLogo.png", |
| | | "favicon": "favicon/HYLQfavicon.ico" |
| | | }, |
| | | "QXY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "强信å®çµå¨äºä¸»æº", |
| | | "VITE_BASE_API": "http://36.134.154.10:9000", |
| | | "VITE_JAVA_API": "http://36.134.154.10:9001" |
| | | }, |
| | | "logo": "logo/QXYLogo.png", |
| | | "favicon": "favicon/QXYfavicon.ico" |
| | | }, |
| | | "HYJC": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ææ´å»ºæ", |
| | | "VITE_BASE_API": "http://36.138.94.178:9000", |
| | | "VITE_JAVA_API": "http://36.138.94.178:9001" |
| | | }, |
| | | "logo": "logo/HYJCLogo.png", |
| | | "favicon": "favicon/HYJCfavicon.ico" |
| | | }, |
| | | "JHY": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å±±è¥¿çæ¦ç¤¾å¿æååé£åæéå
¬å¸", |
| | | "VITE_BASE_API": "http://223.15.233.27:9001", |
| | | "VITE_JAVA_API": "http://223.15.233.27:9002" |
| | | }, |
| | | "logo": "logo/JHYLogo.png", |
| | | "favicon": "favicon/JHYfavicon.ico" |
| | | }, |
| | | "XCDQ": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "ææ¨çµå¨ç®¡çç³»ç»", |
| | | "VITE_BASE_API": "http://36.133.45.183:9001", |
| | | "VITE_JAVA_API": "http://36.133.45.183:9002" |
| | | }, |
| | | "logo": "logo/XCDQLogo.png", |
| | | "favicon": "favicon/XCDQfavicon.ico" |
| | | }, |
| | | "KYHG": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "å±±è¥¿å¤æºåå·¥æéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.137.13.29:9001", |
| | | "VITE_JAVA_API": "http://36.137.13.29:9002" |
| | | }, |
| | | "logo": "logo/KYHGLogo.png", |
| | | "favicon": "favicon/KYHGfavicon.ico" |
| | | }, |
| | | "JXSM": { |
| | | "env": { |
| | | "VITE_APP_TITLE": "è¥å£å¿æ´é«åè´¸æéå
¬å¸", |
| | | "VITE_BASE_API": "http://36.134.76.148:9001", |
| | | "VITE_JAVA_API": "http://36.134.76.148:9002" |
| | | }, |
| | | "logo": "logo/JXSMLogo.png", |
| | | "favicon": "favicon/JXSMico.ico" |
| | | }, |
| | | "screen": "/src/assets/images/login-background.png", |
| | | "logo": "/src/assets/logo/logo.png", |
| | | "favicon": "/public/favicon.ico" |
| | | } |
| | | } |
| | |
| | | import fs from "fs/promises"; |
| | | import fsSync from "fs"; |
| | | import path from "path"; |
| | | import { fileURLToPath } from "url"; |
| | | import fs from 'fs/promises'; |
| | | import fsSync from 'fs'; |
| | | import path from 'path'; |
| | | import { fileURLToPath } from 'url'; |
| | | import { execSync } from "child_process"; |
| | | |
| | | // è·å __dirname |
| | | const __filename = fileURLToPath(import.meta.url); |
| | | const __dirname = path.dirname(__filename); |
| | | |
| | | const data = await fs.readFile(path.join(__dirname, "config.json"), "utf-8"); |
| | | // 读å JSON é
ç½® |
| | | const data = await fs.readFile(path.join(__dirname, 'config.json'), 'utf-8'); |
| | | const config = JSON.parse(data); |
| | | |
| | | const rootPath = path.resolve(__dirname, ".."); |
| | | const resourcePath = path.join(rootPath, "multiple", "assets"); |
| | | const replacePath = path.join(rootPath, "replace"); |
| | | const envFilePath = path.join(rootPath, ".env.production.local"); |
| | | // 项ç®è·¯å¾ |
| | | const rootPath = path.resolve(__dirname, '..'); |
| | | const resourcePath = path.join(rootPath, 'multiple', 'assets'); |
| | | const replacePath = path.join(rootPath, 'replace'); |
| | | |
| | | // è·åå½ä»¤è¡åæ° |
| | | const params = parseArgs(process.argv); |
| | | const company = resolveCompany(params); |
| | | const company = params["company"] ?? "default"; |
| | | const companyMap = config[company]; |
| | | |
| | | if (!companyMap) { |
| | | const availableCompanies = Object.entries(config) |
| | | .filter(([, value]) => value && typeof value === "object" && value.env) |
| | | .map(([key]) => key) |
| | | .sort(); |
| | | throw new Error( |
| | | `æªç¥ company: "${company}"ãå¯éå¼: ${availableCompanies.join(", ")}` |
| | | ); |
| | | } |
| | | |
| | | console.log(`å½å company: ${company}`); |
| | | |
| | | async function copyFileWithOverwrite(src, dest) { |
| | | await fs.mkdir(path.dirname(dest), { recursive: true }); |
| | | if (fsSync.existsSync(dest)) { |
| | | try { |
| | | await fs.chmod(dest, 0o666); |
| | | } catch { |
| | | // Ignore chmod failure and continue. |
| | | } |
| | | await fs.rm(dest, { force: true }); |
| | | } |
| | | await fs.copyFile(src, dest); |
| | | } |
| | | const envFilePath = path.join(process.cwd(), '.env.production.local'); |
| | | |
| | | try { |
| | | console.log("=======çæ.env======="); |
| | | const envContent = |
| | | Object.entries(companyMap.env) |
| | | .map(([key, value]) => `${key}='${value}'`) |
| | | .join("\n") + "\n"; |
| | | await fs.writeFile(envFilePath, envContent, "utf-8"); |
| | | // 1ï¸â£ çæ .env |
| | | console.log("=======çæ.env======="); |
| | | const envContent = Object.entries(companyMap.env) |
| | | .map(([key, value]) => `${key}='${value}'`) |
| | | .join('\n') + '\n'; |
| | | await fs.writeFile(envFilePath, envContent, 'utf-8'); |
| | | |
| | | console.log("=======ä¿®æ¹èµæº======="); |
| | | for (const [key] of Object.entries(companyMap)) { |
| | | if (key === "env") continue; |
| | | // 2ï¸â£ å¤ä»½åå§èµæºå¹¶æ¿æ¢ |
| | | console.log("=======ä¿®æ¹èµæº======="); |
| | | for (const [key, value] of Object.entries(companyMap)) { |
| | | if (key === 'env') continue; |
| | | |
| | | const originFile = path.join(rootPath, config[key]); |
| | | const backupFile = path.join(replacePath, config[key]); |
| | | const replaceFile = path.join(resourcePath, companyMap[key]); |
| | | const originFile = path.join(rootPath, config[key]); |
| | | const backupFile = path.join(replacePath, config[key]); |
| | | const replaceFile = path.join(resourcePath, companyMap[key]); |
| | | |
| | | await copyFileWithOverwrite(originFile, backupFile); |
| | | await copyFileWithOverwrite(replaceFile, originFile); |
| | | } |
| | | await fs.mkdir(path.dirname(backupFile), { recursive: true }); |
| | | await fs.copyFile(originFile, backupFile); |
| | | await fs.copyFile(replaceFile, originFile); |
| | | } |
| | | |
| | | console.log("=====å¼å§æå
====="); |
| | | const buildEnv = createBuildEnv(companyMap.env); |
| | | execSync("vite build", { stdio: "inherit", cwd: rootPath, env: buildEnv }); |
| | | console.log("=====æå
宿======"); |
| | | console.log("=====å¼å§æå
======"); |
| | | execSync("vite build", { stdio: "inherit" }); |
| | | console.log("=====æå
宿======"); |
| | | } finally { |
| | | console.log("=====æ¢å¤èµæº======"); |
| | | console.log("=====æ¢å¤èµæº======"); |
| | | |
| | | if (fsSync.existsSync(envFilePath)) { |
| | | await fs.unlink(envFilePath); |
| | | console.log(`ðï¸ å·²å é¤ ${envFilePath}`); |
| | | } |
| | | |
| | | if (fsSync.existsSync(replacePath)) { |
| | | for (const [key] of Object.entries(companyMap)) { |
| | | if (key === "env") continue; |
| | | |
| | | const originFile = path.join(rootPath, config[key]); |
| | | const backupFile = path.join(replacePath, config[key]); |
| | | await copyFileWithOverwrite(backupFile, originFile); |
| | | // å é¤ä¸´æ¶ .env æä»¶ |
| | | if (fsSync.existsSync(envFilePath)) { |
| | | await fs.unlink(envFilePath); |
| | | console.log(`ðï¸ å·²å é¤ ${envFilePath}`); |
| | | } |
| | | await fs.rm(replacePath, { recursive: true, force: true }); |
| | | console.log(`ðï¸ å·²å é¤ ${replacePath}`); |
| | | } |
| | | |
| | | // æ¢å¤èµæºæä»¶ |
| | | if (fsSync.existsSync(replacePath)) { |
| | | for (const [key, value] of Object.entries(companyMap)) { |
| | | if (key === 'env') continue; |
| | | |
| | | const originFile = path.join(rootPath, config[key]); |
| | | const backupFile = path.join(replacePath, config[key]); |
| | | |
| | | await fs.copyFile(backupFile, originFile); |
| | | } |
| | | await fs.rm(replacePath, { recursive: true, force: true }); |
| | | console.log(`ðï¸ å·²å é¤ ${replacePath}`); |
| | | } |
| | | } |
| | | |
| | | // ç®åå½ä»¤è¡åæ°è§£æ |
| | | function parseArgs(argv) { |
| | | const params = {}; |
| | | for (let index = 2; index < argv.length; index++) { |
| | | const arg = argv[index]; |
| | | if (!arg.startsWith("--")) continue; |
| | | |
| | | const normalized = arg.slice(2); |
| | | const equalIndex = normalized.indexOf("="); |
| | | if (equalIndex >= 0) { |
| | | const key = normalized.slice(0, equalIndex); |
| | | const value = normalized.slice(equalIndex + 1); |
| | | params[key] = value || true; |
| | | continue; |
| | | const params = {}; |
| | | for (const arg of argv.slice(2)) { |
| | | if (arg.startsWith('--')) { |
| | | const [key, value] = arg.slice(2).split('='); |
| | | params[key] = value ?? true; |
| | | } |
| | | } |
| | | |
| | | const nextArg = argv[index + 1]; |
| | | if (nextArg && !nextArg.startsWith("--")) { |
| | | params[normalized] = nextArg; |
| | | index += 1; |
| | | continue; |
| | | } |
| | | |
| | | params[normalized] = true; |
| | | } |
| | | return params; |
| | | } |
| | | |
| | | function resolveCompany(parsedParams) { |
| | | const fromArg = parseValue(parsedParams.company); |
| | | if (fromArg) return fromArg; |
| | | |
| | | const fromNpmConfig = parseValue(process.env.npm_config_company); |
| | | if (fromNpmConfig) return fromNpmConfig; |
| | | |
| | | const fromEnv = parseValue(process.env.COMPANY ?? process.env.company); |
| | | if (fromEnv) return fromEnv; |
| | | |
| | | return "default"; |
| | | } |
| | | |
| | | function parseValue(value) { |
| | | if (value == null || value === true) return undefined; |
| | | if (typeof value !== "string") return undefined; |
| | | const trimmed = value.trim(); |
| | | if (!trimmed) return undefined; |
| | | return trimmed.replace(/^["']|["']$/g, ""); |
| | | } |
| | | |
| | | function createBuildEnv(companyEnv) { |
| | | const env = { ...process.env }; |
| | | for (const key of Object.keys(env)) { |
| | | if (key.startsWith("VITE_")) { |
| | | delete env[key]; |
| | | } |
| | | } |
| | | return { |
| | | ...env, |
| | | ...companyEnv, |
| | | VITE_APP_ENV: "production", |
| | | }; |
| | | return params; |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | import request from "@/utils/request"; |
| | | |
| | | export function getDeviceAreaTree(params) { |
| | | return request({ |
| | | url: "/device/area/tree", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | } |
| | | |
| | | export function getDeviceAreaTreeWithDevices(params) { |
| | | return request({ |
| | | url: "/device/area/treeWithDevices", |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function getDeviceAreaPage(params) { |
| | | return request({ |
| | | url: "/device/area/page", |
| | | method: "get", |
| | | params, |
| | | }); |
| | | } |
| | | |
| | | export function getDeviceAreaDetail(id) { |
| | | return request({ |
| | | url: `/device/area/${id}`, |
| | | method: "get", |
| | | }); |
| | | } |
| | | |
| | | export function addDeviceArea(data) { |
| | | return request({ |
| | | url: "/device/area", |
| | | method: "post", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | export function updateDeviceArea(data) { |
| | | return request({ |
| | | url: "/device/area", |
| | | method: "put", |
| | | data, |
| | | }); |
| | | } |
| | | |
| | | export function deleteDeviceArea(ids) { |
| | | return request({ |
| | | url: "/device/area", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | |
| | | method:"post", |
| | | data |
| | | }) |
| | | } |
| | | |
| | | // éç¨éä»¶æ¥è¯¢ |
| | | export function getStorageAttachmentList(query) { |
| | | return request({ |
| | | url: "/storageAttachment/list", |
| | | method: "get", |
| | | params: query, |
| | | }); |
| | | } |
| | | |
| | | // éç¨éä»¶ä¿å |
| | | export function addStorageAttachment(data) { |
| | | return request({ |
| | | url: "/storageAttachment/add", |
| | | method: "post", |
| | | data: data, |
| | | }); |
| | | } |
| | | |
| | | // éç¨éä»¶å é¤ |
| | | export function delStorageAttachment(ids) { |
| | | return request({ |
| | | url: "/storageAttachment/delete", |
| | | method: "delete", |
| | | data: ids, |
| | | }); |
| | | } |
| | |
| | | data, |
| | | }); |
| | | }; |
| | | |
| | | /** |
| | | * @desc éªæ¶å®¡æ¹ |
| | | * @param {éªæ¶åæ°} data |
| | | * @returns |
| | | */ |
| | | export const repairAcceptance = (data) => { |
| | | return request({ |
| | | url: `/device/repair/acceptance`, |
| | | method: "post", |
| | | data, |
| | | }); |
| | | }; |
| | |
| | | data: params, |
| | | }); |
| | | }; |
| | | |
| | | // 设å¤ä¿å
»å®æ¶ä»»å¡å¯ç¨ç¶æåæ¢ |
| | | export const deviceMaintenanceTaskChangeEnable = (params) => { |
| | | return request({ |
| | | url: '/deviceMaintenanceTask/changeEnable', |
| | | method: "post", |
| | | data: params, |
| | | }); |
| | | }; |
| | |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | | } |
| | | |
| | | // 宿¶å·¡æ£ä»»å¡å¯ç¨ç¶æåæ¢ |
| | | export function changeTimingTaskEnable(query) { |
| | | return request({ |
| | | url: '/timingTask/changeEnable', |
| | | method: 'post', |
| | | data: query |
| | | }) |
| | | } |
| | |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | <el-button @click="visible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="handleSubmit">ç¡®å®</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">æ£å®æ¥æï¼</span> |
| | | <el-date-picker |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="submitDefectForm">ç¡®å®</el-button> |
| | | <el-button @click="showRegisterDialog = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitDefectForm">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <template> |
| | | <div> |
| | | <el-dialog title="æ¥çéä»¶" v-model="dialogVisitable" width="800px" @close="cancel"> |
| | | <el-dialog title="æ¥çéä»¶" |
| | | v-model="dialogVisitable" width="800px" @close="cancel"> |
| | | <div class="upload-container"> |
| | | <!-- ç产å --> |
| | | <div class="form-container"> |
| | | <div class="title">ç产å</div> |
| | | |
| | | <div class="media-list"> |
| | | <img |
| | | v-for="(item, index) in beforeProductionImgs" |
| | | :key="`before-img-${index}`" |
| | | :src="item" |
| | | alt="" |
| | | class="media-image" |
| | | @click="showMedia(beforeProductionImgs, index, 'image')" |
| | | /> |
| | | |
| | | <!-- å¾çå表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <img v-for="(item, index) in beforeProductionImgs" :key="index" |
| | | @click="showMedia(beforeProductionImgs, index, 'image')" |
| | | :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt=""> |
| | | </div> |
| | | |
| | | <div class="media-list"> |
| | | |
| | | <!-- è§é¢å表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <div |
| | | v-for="(videoUrl, index) in beforeProductionVideos" |
| | | :key="`before-video-${index}`" |
| | | class="video-item" |
| | | @click="showMedia(beforeProductionVideos, index, 'video')" |
| | | v-for="(videoUrl, index) in beforeProductionVideos" |
| | | :key="index" |
| | | @click="showMedia(beforeProductionVideos, index, 'video')" |
| | | style="position: relative; margin: 10px; cursor: pointer;" |
| | | > |
| | | <div class="video-thumb"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" class="video-icon" /> |
| | | <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" style="width: 30px; height: 30px; opacity: 0.8;" /> |
| | | </div> |
| | | <div class="video-text">ç¹å»ææ¾</div> |
| | | <div style="text-align: center; font-size: 12px; color: #666;">ç¹å»ææ¾</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div class="form-container"> |
| | | <div class="title">ç产ä¸</div> |
| | | |
| | | <div class="media-list"> |
| | | <img |
| | | v-for="(item, index) in afterProductionImgs" |
| | | :key="`during-img-${index}`" |
| | | :src="item" |
| | | alt="" |
| | | class="media-image" |
| | | @click="showMedia(afterProductionImgs, index, 'image')" |
| | | /> |
| | | </div> |
| | | |
| | | <div class="media-list"> |
| | | <div |
| | | v-for="(videoUrl, index) in afterProductionVideos" |
| | | :key="`during-video-${index}`" |
| | | class="video-item" |
| | | @click="showMedia(afterProductionVideos, index, 'video')" |
| | | > |
| | | <div class="video-thumb"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" class="video-icon" /> |
| | | </div> |
| | | <div class="video-text">ç¹å»ææ¾</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | |
| | | <!-- çäº§ä¸ --> |
| | | <div class="form-container"> |
| | | <div class="title">ç产ä¸</div> |
| | | |
| | | <!-- å¾çå表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <img v-for="(item, index) in productionIssuesImgs" :key="index" |
| | | @click="showMedia(productionIssuesImgs, index, 'image')" |
| | | :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt=""> |
| | | </div> |
| | | |
| | | <!-- è§é¢å表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <div |
| | | v-for="(videoUrl, index) in productionIssuesVideos" |
| | | :key="index" |
| | | @click="showMedia(productionIssuesVideos, index, 'video')" |
| | | style="position: relative; margin: 10px; cursor: pointer;" |
| | | > |
| | | <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" style="width: 30px; height: 30px; opacity: 0.8;" /> |
| | | </div> |
| | | <div style="text-align: center; font-size: 12px; color: #666;">ç¹å»ææ¾</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- ç产å --> |
| | | <div class="form-container"> |
| | | <div class="title">ç产å</div> |
| | | |
| | | <div class="media-list"> |
| | | <img |
| | | v-for="(item, index) in productionIssuesImgs" |
| | | :key="`after-img-${index}`" |
| | | :src="item" |
| | | alt="" |
| | | class="media-image" |
| | | @click="showMedia(productionIssuesImgs, index, 'image')" |
| | | /> |
| | | |
| | | <!-- å¾çå表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <img v-for="(item, index) in afterProductionImgs" :key="index" |
| | | @click="showMedia(afterProductionImgs, index, 'image')" |
| | | :src="item" style="max-width: 100px; height: 100px; margin: 5px;" alt=""> |
| | | </div> |
| | | |
| | | <div class="media-list"> |
| | | |
| | | <!-- è§é¢å表 --> |
| | | <div style="display: flex; flex-wrap: wrap;"> |
| | | <div |
| | | v-for="(videoUrl, index) in productionIssuesVideos" |
| | | :key="`after-video-${index}`" |
| | | class="video-item" |
| | | @click="showMedia(productionIssuesVideos, index, 'video')" |
| | | v-for="(videoUrl, index) in afterProductionVideos" |
| | | :key="index" |
| | | @click="showMedia(afterProductionVideos, index, 'video')" |
| | | style="position: relative; margin: 10px; cursor: pointer;" |
| | | > |
| | | <div class="video-thumb"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" class="video-icon" /> |
| | | <div style="width: 160px; height: 90px; background-color: #333; display: flex; align-items: center; justify-content: center;"> |
| | | <img src="@/assets/images/video.png" alt="ææ¾" style="width: 30px; height: 30px; opacity: 0.8;" /> |
| | | </div> |
| | | <div class="video-text">ç¹å»ææ¾</div> |
| | | <div style="text-align: center; font-size: 12px; color: #666;">ç¹å»ææ¾</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | |
| | | <!-- ç»ä¸åªä½æ¥çå¨ --> |
| | | <div v-if="isMediaViewerVisible" class="media-viewer-overlay" @click.self="closeMediaViewer"> |
| | | <div class="media-viewer-content" @click.stop> |
| | | <!-- å¾ç --> |
| | | <vue-easy-lightbox |
| | | v-if="mediaType === 'image'" |
| | | :visible="isMediaViewerVisible" |
| | | :imgs="mediaList" |
| | | :index="currentMediaIndex" |
| | | @hide="closeMediaViewer" |
| | | /> |
| | | |
| | | <div v-else-if="mediaType === 'video'" class="video-player-wrap"> |
| | | <video :src="mediaList[currentMediaIndex]" autoplay controls class="video-player" /> |
| | | v-if="mediaType === 'image'" |
| | | :visible="isMediaViewerVisible" |
| | | :imgs="mediaList" |
| | | :index="currentMediaIndex" |
| | | @hide="closeMediaViewer" |
| | | ></vue-easy-lightbox> |
| | | |
| | | <!-- è§é¢ --> |
| | | <div v-else-if="mediaType === 'video'" style="position: relative;"> |
| | | <video |
| | | :src="mediaList[currentMediaIndex]" |
| | | autoplay |
| | | controls |
| | | style="max-width: 90vw; max-height: 80vh;" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref } from "vue"; |
| | | import VueEasyLightbox from "vue-easy-lightbox"; |
| | | import { ref } from 'vue'; |
| | | import VueEasyLightbox from 'vue-easy-lightbox'; |
| | | const { proxy } = getCurrentInstance(); |
| | | |
| | | // æ§å¶å¼¹çªæ¾ç¤º |
| | | const dialogVisitable = ref(false); |
| | | |
| | | // å¾çæ°ç» |
| | | const beforeProductionImgs = ref([]); |
| | | const afterProductionImgs = ref([]); |
| | | const productionIssuesImgs = ref([]); |
| | | |
| | | // è§é¢æ°ç» |
| | | const beforeProductionVideos = ref([]); |
| | | const afterProductionVideos = ref([]); |
| | | const productionIssuesVideos = ref([]); |
| | | |
| | | // åªä½æ¥çå¨ç¶æ |
| | | const isMediaViewerVisible = ref(false); |
| | | const currentMediaIndex = ref(0); |
| | | const mediaList = ref([]); |
| | | const mediaType = ref("image"); |
| | | const mediaList = ref([]); // åå¨å½åè¦æ¥ççåªä½å表ï¼å«å¾çåè§é¢å¯¹è±¡ï¼ |
| | | const mediaType = ref('image'); // image | video |
| | | const javaApi = proxy.javaApi; |
| | | |
| | | const processFileUrl = fileUrl => { |
| | | if (!fileUrl) return ""; |
| | | |
| | | let currentUrl = String(fileUrl); |
| | | if (currentUrl.includes("\\")) { |
| | | const uploadsIndex = currentUrl.toLowerCase().indexOf("uploads"); |
| | | // å¤ç URLï¼å° Windows è·¯å¾è½¬æ¢ä¸ºå¯è®¿é®ç URL |
| | | function processFileUrl(fileUrl) { |
| | | if (!fileUrl) return ''; |
| | | |
| | | // 妿 URL æ¯ Windows è·¯å¾æ ¼å¼ï¼å
å«åææ ï¼ï¼éè¦è½¬æ¢ |
| | | if (fileUrl && fileUrl.indexOf('\\') > -1) { |
| | | // æ¥æ¾ uploads å
³é®åçä½ç½®ï¼ä»é£éå¼å§æåç¸å¯¹è·¯å¾ |
| | | const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads'); |
| | | if (uploadsIndex > -1) { |
| | | currentUrl = `/${currentUrl.substring(uploadsIndex).replace(/\\/g, "/")}`; |
| | | // ä» uploads å¼å§æåè·¯å¾ï¼å¹¶å°åææ æ¿æ¢ä¸ºæ£ææ |
| | | const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/'); |
| | | fileUrl = '/' + relativePath; |
| | | } else { |
| | | const fileName = currentUrl.split("\\").pop(); |
| | | currentUrl = `/uploads/${fileName}`; |
| | | // å¦ææ²¡ææ¾å° uploadsï¼æåæåä¸ä¸ªç®å½åæä»¶å |
| | | const parts = fileUrl.split('\\'); |
| | | const fileName = parts[parts.length - 1]; |
| | | fileUrl = '/uploads/' + fileName; |
| | | } |
| | | } |
| | | |
| | | if (currentUrl && !currentUrl.startsWith("http")) { |
| | | if (!currentUrl.startsWith("/")) { |
| | | currentUrl = `/${currentUrl}`; |
| | | |
| | | // ç¡®ä¿ææé http å¼å¤´ç URL 齿¼æ¥ baseUrl |
| | | if (fileUrl && !fileUrl.startsWith('http')) { |
| | | // ç¡®ä¿è·¯å¾ä»¥ / å¼å¤´ |
| | | if (!fileUrl.startsWith('/')) { |
| | | fileUrl = '/' + fileUrl; |
| | | } |
| | | currentUrl = __BASE_API__ + currentUrl; |
| | | // æ¼æ¥ baseUrl |
| | | fileUrl = javaApi + fileUrl; |
| | | } |
| | | |
| | | return fileUrl; |
| | | } |
| | | |
| | | return currentUrl; |
| | | }; |
| | | |
| | | const processItems = items => { |
| | | // å¤çæ¯ä¸ç±»æ°æ®ï¼å离å¾çåè§é¢ |
| | | function processItems(items) { |
| | | const images = []; |
| | | const videos = []; |
| | | |
| | | if (!Array.isArray(items)) { |
| | | |
| | | // æ£æ¥ items æ¯å¦åå¨ä¸ä¸ºæ°ç» |
| | | if (!items || !Array.isArray(items)) { |
| | | return { images, videos }; |
| | | } |
| | | |
| | | |
| | | items.forEach(item => { |
| | | if (!item) return; |
| | | |
| | | const fileUrl = processFileUrl( |
| | | item.previewURL || item.url || item.downloadUrl || item.path || "" |
| | | ); |
| | | const contentType = String(item.contentType || "").toLowerCase(); |
| | | |
| | | if (!fileUrl) return; |
| | | |
| | | if (contentType.startsWith("video/")) { |
| | | if (!item || !item.url) return; |
| | | |
| | | // å¤çæä»¶ URL |
| | | const fileUrl = processFileUrl(item.url); |
| | | |
| | | // æ ¹æ®æä»¶æ©å±å夿æ¯å¾çè¿æ¯è§é¢ |
| | | const urlLower = fileUrl.toLowerCase(); |
| | | if (urlLower.match(/\.(jpg|jpeg|png|gif|bmp|webp)$/)) { |
| | | images.push(fileUrl); |
| | | } else if (urlLower.match(/\.(mp4|avi|mov|wmv|flv|mkv|webm)$/)) { |
| | | videos.push(fileUrl); |
| | | return; |
| | | } else if (item.contentType) { |
| | | // 妿æ contentTypeï¼ä½¿ç¨ contentType 夿 |
| | | if (item.contentType.startsWith('image/')) { |
| | | images.push(fileUrl); |
| | | } else if (item.contentType.startsWith('video/')) { |
| | | videos.push(fileUrl); |
| | | } |
| | | } |
| | | |
| | | images.push(fileUrl); |
| | | }); |
| | | |
| | | |
| | | return { images, videos }; |
| | | }; |
| | | } |
| | | |
| | | const openDialog = row => { |
| | | const { images: beforeImgs, videos: beforeVids } = processItems( |
| | | row.commonFileListBeforeVO || [] |
| | | ); |
| | | const { images: afterImgs, videos: afterVids } = processItems( |
| | | row.commonFileListVO || [] |
| | | ); |
| | | const { images: issueImgs, videos: issueVids } = processItems( |
| | | row.commonFileListAfterVO || [] |
| | | ); |
| | | |
| | | // æå¼å¼¹çªå¹¶å è½½æ°æ® |
| | | const openDialog = async (row) => { |
| | | // ä½¿ç¨æ£ç¡®çåæ®µåï¼commonFileListBefore, commonFileListAfter |
| | | // productionIssues å¯è½ä¸åå¨ï¼ä½¿ç¨ç©ºæ°ç» |
| | | const { images: beforeImgs, videos: beforeVids } = processItems(row.commonFileListBefore || []); |
| | | const { images: afterImgs, videos: afterVids } = processItems(row.commonFileListAfter || []); |
| | | const { images: issueImgs, videos: issueVids } = processItems(row.productionIssues || []); |
| | | |
| | | beforeProductionImgs.value = beforeImgs; |
| | | beforeProductionVideos.value = beforeVids; |
| | | |
| | | afterProductionImgs.value = afterImgs; |
| | | afterProductionVideos.value = afterVids; |
| | | |
| | | productionIssuesImgs.value = issueImgs; |
| | | productionIssuesVideos.value = issueVids; |
| | | |
| | | dialogVisitable.value = true; |
| | | }; |
| | | |
| | | const showMedia = (items, index, type) => { |
| | | mediaList.value = items; |
| | | // æ¾ç¤ºåªä½ï¼å¾ç or è§é¢ï¼ |
| | | function showMedia(mediaArray, index, type) { |
| | | mediaList.value = mediaArray; |
| | | currentMediaIndex.value = index; |
| | | mediaType.value = type; |
| | | isMediaViewerVisible.value = true; |
| | | }; |
| | | } |
| | | |
| | | const closeMediaViewer = () => { |
| | | // å
³éåªä½æ¥çå¨ |
| | | function closeMediaViewer() { |
| | | isMediaViewerVisible.value = false; |
| | | mediaList.value = []; |
| | | mediaType.value = "image"; |
| | | }; |
| | | mediaType.value = 'image'; |
| | | } |
| | | |
| | | // 表åå
³éæ¹æ³ |
| | | const cancel = () => { |
| | | dialogVisitable.value = false; |
| | | }; |
| | | |
| | | defineExpose({ openDialog }); |
| | | </script> |
| | | |
| | | <style scoped lang="scss"> |
| | | .upload-container { |
| | | display: flex; |
| | |
| | | padding: 20px; |
| | | border: 1px solid #dcdfe6; |
| | | box-sizing: border-box; |
| | | |
| | | |
| | | .form-container { |
| | | flex: 1; |
| | | width: 100%; |
| | |
| | | padding-left: 10px; |
| | | position: relative; |
| | | margin: 6px 0; |
| | | |
| | | |
| | | &::before { |
| | | content: ""; |
| | | position: absolute; |
| | |
| | | } |
| | | } |
| | | |
| | | .media-list { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | .media-image { |
| | | max-width: 100px; |
| | | height: 100px; |
| | | margin: 5px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .video-item { |
| | | position: relative; |
| | | margin: 10px; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .video-thumb { |
| | | width: 160px; |
| | | height: 90px; |
| | | background-color: #333; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .video-icon { |
| | | width: 30px; |
| | | height: 30px; |
| | | opacity: 0.8; |
| | | } |
| | | |
| | | .video-text { |
| | | text-align: center; |
| | | font-size: 12px; |
| | | color: #666; |
| | | } |
| | | |
| | | .media-viewer-overlay { |
| | | position: fixed; |
| | | inset: 0; |
| | | top: 0; |
| | | left: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, 0.8); |
| | | z-index: 9999; |
| | | display: flex; |
| | |
| | | max-height: 90vh; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .video-player-wrap { |
| | | position: relative; |
| | | } |
| | | |
| | | .video-player { |
| | | max-width: 90vw; |
| | | max-height: 80vh; |
| | | } |
| | | </style> |
| | | </style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :inline="true" |
| | | :model="queryParams" |
| | | class="search-form"> |
| | | <el-form :inline="true" :model="queryParams" class="search-form"> |
| | | <el-form-item label="å·¡æ£ä»»å¡åç§°"> |
| | | <el-input v-model="queryParams.taskName" |
| | | placeholder="请è¾å
¥å·¡æ£ä»»å¡åç§°" |
| | | clearable |
| | | style="width: 200px " /> |
| | | <el-input |
| | | v-model="queryParams.taskName" |
| | | placeholder="请è¾å
¥å·¡æ£ä»»å¡åç§°" |
| | | clearable |
| | | style="width: 200px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æå±åºå"> |
| | | <el-tree-select |
| | | v-model="queryParams.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="è¯·éæ©æå±åºå" |
| | | style="width: 220px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item v-show="activeRadio === 'taskManage'" label="æ¯å¦å¯ç¨"> |
| | | <el-select |
| | | v-model="queryParams.isEnabled" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 140px" |
| | | > |
| | | <el-option label="å¯ç¨" :value="1" /> |
| | | <el-option label="ç¦ç¨" :value="0" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-show="activeRadio === 'task'" label="æ§è¡æ¥æ"> |
| | | <el-date-picker |
| | | v-model="queryDate" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥æ" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | style="width: 180px" |
| | | @change="handleQuery" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="handleQuery">æ¥è¯¢</el-button> |
| | | <el-button type="primary" @click="handleQuery">æ¥è¯¢</el-button> |
| | | <el-button @click="resetQuery">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <el-card> |
| | | <div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom: 10px;"> |
| | | <el-radio-group v-model="activeRadio" |
| | | @change="radioChange"> |
| | | <el-radio-button v-for="tab in radios" |
| | | :key="tab.name" |
| | | :label="tab.label" |
| | | :value="tab.name" /> |
| | | <div class="toolbar"> |
| | | <el-radio-group v-model="activeRadio" @change="radioChange"> |
| | | <el-radio-button |
| | | v-for="tab in radios" |
| | | :key="tab.name" |
| | | :label="tab.label" |
| | | :value="tab.name" |
| | | /> |
| | | </el-radio-group> |
| | | <!-- æä½æé®åº --> |
| | | <el-space v-if="activeRadio !== 'task'"> |
| | | <el-button type="primary" |
| | | :icon="Plus" |
| | | @click="handleAdd(undefined)">æ°å»º</el-button> |
| | | <el-button type="danger" |
| | | :icon="Delete" |
| | | @click="handleDelete">å é¤</el-button> |
| | | <el-button type="primary" :icon="Plus" @click="handleAdd(undefined)">æ°å»º</el-button> |
| | | <el-button type="danger" :icon="Delete" @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </el-space> |
| | | <el-space v-else> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </el-space> |
| | | </div> |
| | | <div> |
| | | <PIMTable :table-loading="tableLoading" |
| | | :table-data="tableData" |
| | | :column="tableColumns" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="handlePagination" |
| | | :is-selection="true" |
| | | :border="true" |
| | | :page="{ |
| | | current: pageNum, |
| | | size: pageSize, |
| | | total: total, |
| | | layout: 'total, sizes, prev, pager, next, jumper' |
| | | }" |
| | | height="calc(100vh - 23em)" |
| | | :table-style="{ width: '100%' }"> |
| | | <template #inspector="{ row }"> |
| | | <div class="person-tags"> |
| | | <!-- è°è¯ä¿¡æ¯ï¼ä¸çº¿æ¶å é¤ --> |
| | | <!-- {{ console.log('inspector data:', row.inspector) }} --> |
| | | <template v-if="row.inspector && row.inspector.length > 0"> |
| | | <el-tag v-for="(person, index) in row.inspector" |
| | | :key="index" |
| | | size="small" |
| | | type="primary" |
| | | class="person-tag"> |
| | | {{ person }} |
| | | </el-tag> |
| | | </template> |
| | | <span v-else |
| | | class="no-data">--</span> |
| | | </div> |
| | | </template> |
| | | <template #isEnabled="{ row }"> |
| | | <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" |
| | | size="small"> |
| | | {{ row.isEnabled == 1 ? 'æ¯' : 'å¦' }} |
| | | </el-tag> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <PIMTable |
| | | :table-loading="tableLoading" |
| | | :table-data="tableData" |
| | | :column="tableColumns" |
| | | :is-selection="true" |
| | | :border="true" |
| | | :page="{ |
| | | current: pageNum, |
| | | size: pageSize, |
| | | total, |
| | | layout: 'total, sizes, prev, pager, next, jumper', |
| | | }" |
| | | :table-style="{ width: '100%', height: 'calc(100vh - 23em)' }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="handlePagination" |
| | | > |
| | | <template #inspector="{ row }"> |
| | | <div class="person-tags"> |
| | | <template v-if="row.inspector && row.inspector.length > 0"> |
| | | <el-tag |
| | | v-for="(person, index) in row.inspector" |
| | | :key="index" |
| | | size="small" |
| | | type="primary" |
| | | class="person-tag" |
| | | > |
| | | {{ person }} |
| | | </el-tag> |
| | | </template> |
| | | <span v-else class="no-data">--</span> |
| | | </div> |
| | | </template> |
| | | <template #isEnabledSwitch="{ row }"> |
| | | <el-switch |
| | | v-model="row.isEnabled" |
| | | :active-value="1" |
| | | :inactive-value="0" |
| | | :loading="row.enableSwitchLoading" |
| | | :before-change="() => handleTimingTaskEnableBeforeChange(row)" |
| | | /> |
| | | </template> |
| | | </PIMTable> |
| | | </el-card> |
| | | <form-dia ref="formDia" |
| | | @closeDia="handleQuery"></form-dia> |
| | | <view-files ref="viewFiles"></view-files> |
| | | <upload-files ref="uploadFiles" |
| | | @success="handleQuery" |
| | | @closeDia="handleQuery"></upload-files> |
| | | <form-dia ref="formDia" @closeDia="handleQuery" /> |
| | | <view-files ref="viewFiles" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { Delete, Plus } from "@element-plus/icons-vue"; |
| | | import { onMounted, ref, reactive, getCurrentInstance, nextTick } from "vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import { Delete, Plus } from "@element-plus/icons-vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import { getCurrentInstance, nextTick, onMounted, reactive, ref } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import FormDia from "@/views/equipmentManagement/inspectionManagement/components/formDia.vue"; |
| | | import ViewFiles from "@/views/equipmentManagement/inspectionManagement/components/viewFiles.vue"; |
| | | import { |
| | | changeTimingTaskEnable, |
| | | delTimingTask, |
| | | inspectionTaskList, |
| | | timingTaskList, |
| | | } from "@/api/inspectionManagement/index.js"; |
| | | import { getDeviceAreaTree } from "@/api/equipmentManagement/deviceArea"; |
| | | |
| | | // ç»ä»¶å¼å
¥ |
| | | import PIMTable from "@/components/PIMTable/PIMTable.vue"; |
| | | import FormDia from "@/views/equipmentManagement/inspectionManagement/components/formDia.vue"; |
| | | import UploadFiles from "@/views/equipmentManagement/inspectionManagement/components/uploadFiles.vue"; |
| | | import ViewFiles from "@/views/equipmentManagement/inspectionManagement/components/viewFiles.vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const formDia = ref(); |
| | | const viewFiles = ref(); |
| | | |
| | | // æ¥å£å¼å
¥ |
| | | import { |
| | | delTimingTask, |
| | | inspectionTaskList, |
| | | timingTaskList, |
| | | } from "@/api/inspectionManagement/index.js"; |
| | | const queryParams = reactive({ |
| | | taskName: "", |
| | | areaId: undefined, |
| | | isEnabled: undefined, |
| | | createTimeStart: undefined, |
| | | createTimeEnd: undefined, |
| | | }); |
| | | |
| | | // å
¨å±åé |
| | | const { proxy } = getCurrentInstance(); |
| | | const formDia = ref(); |
| | | const viewFiles = ref(); |
| | | const uploadFiles = ref(); |
| | | // æ¥è¯¢æ¥æï¼ç¨äºå®æ¶ä»»å¡è®°å½ï¼ |
| | | const queryDate = ref(dayjs().format("YYYY-MM-DD")); |
| | | |
| | | // æ¥è¯¢åæ° |
| | | const queryParams = reactive({ |
| | | taskName: "", |
| | | }); |
| | | const areaOptions = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | |
| | | // åéæ¡é
ç½® |
| | | const activeRadio = ref("taskManage"); |
| | | const radios = reactive([ |
| | | { name: "taskManage", label: "å·¡æ£ä»»å¡" }, |
| | | { name: "task", label: "å·¡æ£è®°å½" }, |
| | | ]); |
| | | const activeRadio = ref("taskManage"); |
| | | const radios = reactive([ |
| | | { name: "taskManage", label: "宿¶ä»»å¡ç®¡ç" }, |
| | | { name: "task", label: "宿¶ä»»å¡è®°å½" }, |
| | | ]); |
| | | |
| | | // è¡¨æ ¼æ°æ® |
| | | const selectedRows = ref([]); |
| | | const tableData = ref([]); |
| | | const operationsArr = ref([]); |
| | | const tableColumns = ref([]); |
| | | const tableLoading = ref(false); |
| | | const total = ref(0); |
| | | const pageNum = ref(1); |
| | | const pageSize = ref(10); |
| | | const selectedRows = ref([]); |
| | | const tableData = ref([]); |
| | | const tableColumns = ref([]); |
| | | const tableLoading = ref(false); |
| | | const total = ref(0); |
| | | const pageNum = ref(1); |
| | | const pageSize = ref(10); |
| | | |
| | | // åé
ç½® |
| | | const columns = ref([ |
| | | { prop: "taskName", label: "å·¡æ£ä»»å¡åç§°", minWidth: 200 }, |
| | | { prop: "inspectionProject", label: "å·¡æ£é¡¹ç®", minWidth: 180 }, |
| | | { prop: "remarks", label: "夿³¨", minWidth: 180 }, |
| | | { prop: "inspector", label: "æ§è¡å·¡æ£äºº", minWidth: 180, slot: "inspector" }, |
| | | { |
| | | prop: "isEnabled", |
| | | label: "æ¯å¦å¯ç¨", |
| | | minWidth: 100, |
| | | dataType: "slot", |
| | | slot: "isEnabled", |
| | | }, |
| | | { |
| | | prop: "frequencyType", |
| | | label: "颿¬¡", |
| | | minWidth: 120, |
| | | formatData: params => { |
| | | return params === "DAILY" |
| | | ? "æ¯æ¥" |
| | | : params === "WEEKLY" |
| | | ? "æ¯å¨" |
| | | : params === "MONTHLY" |
| | | ? "æ¯æ" |
| | | : params === "QUARTERLY" |
| | | ? "å£åº¦" |
| | | : ""; |
| | | }, |
| | | }, |
| | | { |
| | | prop: "frequencyDetail", |
| | | label: "å¼å§æ¥æä¸æ¶é´", |
| | | minWidth: 200, |
| | | formatter: (row, column, cellValue) => { |
| | | // å
夿æ¯å¦æ¯å符串 |
| | | if (typeof cellValue !== "string") return ""; |
| | | let val = cellValue; |
| | | const replacements = { |
| | | MON: "å¨ä¸", |
| | | TUE: "å¨äº", |
| | | WED: "å¨ä¸", |
| | | THU: "å¨å", |
| | | FRI: "å¨äº", |
| | | SAT: "å¨å
", |
| | | SUN: "卿¥", |
| | | }; |
| | | // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é
项 |
| | | return val.replace( |
| | | /MON|TUE|WED|THU|FRI|SAT|SUN/g, |
| | | match => replacements[match] |
| | | ); |
| | | }, |
| | | }, |
| | | { prop: "registrant", label: "ç»è®°äºº", minWidth: 120 }, |
| | | { |
| | | prop: "createTime", |
| | | label: "ç»è®°æ¥æ", |
| | | minWidth: 180, |
| | | formatData: cell => { |
| | | if (!cell) return "-"; |
| | | try { |
| | | return dayjs(cell).format("YYYY-MM-DD HH:mm:ss"); |
| | | } catch { |
| | | return cell; |
| | | } |
| | | }, |
| | | }, |
| | | // { |
| | | // prop: "inspectionResult", |
| | | // label: "å·¡æ£ç»æ", |
| | | // minWidth: 100, |
| | | // dataType: "tag", |
| | | // formatData: val => { |
| | | // return val == 1 ? "æ£å¸¸" : "å¼å¸¸"; |
| | | // }, |
| | | // formatType: val => { |
| | | // return val == 1 ? "success" : "danger"; |
| | | // }, |
| | | // }, |
| | | { prop: "abnormalDescription", label: "å¼å¸¸æè¿°", minWidth: 150 }, |
| | | ]); |
| | | |
| | | // æä½åé
ç½® |
| | | const getOperationColumn = operations => { |
| | | if (!operations || operations.length === 0) return null; |
| | | |
| | | const operationConfig = { |
| | | label: "æä½", |
| | | width: operations.length > 1 ? 180 : 130, |
| | | fixed: "right", |
| | | align: "center", |
| | | dataType: "action", |
| | | operation: operations |
| | | .map(op => { |
| | | switch (op) { |
| | | case "edit": |
| | | return { |
| | | name: "ç¼è¾", |
| | | clickFun: handleAdd, |
| | | color: "#409EFF", |
| | | }; |
| | | case "upload": |
| | | return { |
| | | name: "ä¸ä¼ ", |
| | | clickFun: openUploadDialog, |
| | | color: "#409EFF", |
| | | }; |
| | | case "viewFile": |
| | | return { |
| | | name: "æ¥çéä»¶", |
| | | clickFun: viewFile, |
| | | color: "#67C23A", |
| | | }; |
| | | default: |
| | | return null; |
| | | } |
| | | }) |
| | | .filter(Boolean), |
| | | }; |
| | | |
| | | return operationConfig; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | radioChange("taskManage"); |
| | | }); |
| | | |
| | | // åéåå |
| | | const radioChange = value => { |
| | | if (value === "taskManage") { |
| | | const operationColumn = getOperationColumn(["edit"]); |
| | | tableColumns.value = [ |
| | | ...columns.value, |
| | | ...(operationColumn ? [operationColumn] : []), |
| | | ]; |
| | | operationsArr.value = ["edit"]; |
| | | } else if (value === "task") { |
| | | const operationColumn = getOperationColumn(["upload", "viewFile"]); |
| | | // å·¡æ£è®°å½ä¸å±ç¤º"æ¯å¦å¯ç¨"å |
| | | const taskColumns = columns.value.filter(col => col.prop !== "isEnabled"); |
| | | tableColumns.value = [ |
| | | ...taskColumns, |
| | | ...(operationColumn ? [operationColumn] : []), |
| | | ]; |
| | | operationsArr.value = ["upload", "viewFile"]; |
| | | } |
| | | pageNum.value = 1; |
| | | pageSize.value = 10; |
| | | getList(); |
| | | }; |
| | | |
| | | // æ¥è¯¢æä½ |
| | | const handleQuery = () => { |
| | | pageNum.value = 1; |
| | | pageSize.value = 10; |
| | | getList(); |
| | | }; |
| | | // å页å¤ç |
| | | const handlePagination = val => { |
| | | pageNum.value = val.page; |
| | | pageSize.value = val.limit; |
| | | getList(); |
| | | }; |
| | | // è·ååè¡¨æ°æ® |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | |
| | | const params = { |
| | | ...queryParams, |
| | | size: pageSize.value, |
| | | current: pageNum.value, |
| | | }; |
| | | |
| | | let apiCall; |
| | | if (activeRadio.value === "task") { |
| | | apiCall = inspectionTaskList(params); |
| | | } else { |
| | | apiCall = timingTaskList(params); |
| | | } |
| | | |
| | | apiCall |
| | | .then(res => { |
| | | const rawData = res.data.records || []; |
| | | // å¤ç inspector åæ®µï¼å°å符串转æ¢ä¸ºæ°ç»ï¼éç¨äºæææ
åµï¼ |
| | | tableData.value = rawData.map(item => { |
| | | const processedItem = { ...item }; |
| | | processedItem.__raw = { ...item }; |
| | | |
| | | // å¤ç inspector åæ®µ |
| | | if (processedItem.inspector) { |
| | | if (typeof processedItem.inspector === "string") { |
| | | // å符串æéå·åå² |
| | | processedItem.inspector = processedItem.inspector |
| | | .split(",") |
| | | .map(s => s.trim()) |
| | | .filter(s => s); |
| | | } else if (!Array.isArray(processedItem.inspector)) { |
| | | // éæ°ç»è½¬ä¸ºæ°ç» |
| | | processedItem.inspector = [processedItem.inspector]; |
| | | } |
| | | } else { |
| | | // 空å¼è®¾ä¸ºç©ºæ°ç» |
| | | processedItem.inspector = []; |
| | | } |
| | | |
| | | return processedItem; |
| | | }); |
| | | total.value = res.data.total || 0; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | // éç½®æ¥è¯¢ |
| | | const resetQuery = () => { |
| | | for (const key in queryParams) { |
| | | if (!["pageNum", "pageSize"].includes(key)) { |
| | | queryParams[key] = ""; |
| | | const columns = ref([ |
| | | { |
| | | label: "æå¨åºå", |
| | | prop: "areaName", |
| | | }, |
| | | { prop: "taskName", label: "å·¡æ£ä»»å¡åç§°", minWidth: 160 }, |
| | | { prop: "remarks", label: "夿³¨", minWidth: 150 }, |
| | | { prop: "inspector", label: "æ§è¡å·¡æ£äºº", minWidth: 150, slot: "inspector" }, |
| | | { |
| | | prop: "frequencyType", |
| | | label: "颿¬¡", |
| | | minWidth: 150, |
| | | formatData: (value) => |
| | | ({ |
| | | DAILY: "æ¯æ¥", |
| | | WEEKLY: "æ¯å¨", |
| | | MONTHLY: "æ¯æ", |
| | | QUARTERLY: "å£åº¦", |
| | | YEARLY: "æ¯å¹´", |
| | | }[value] || ""), |
| | | }, |
| | | { |
| | | prop: "frequencyDetail", |
| | | label: "å¼å§æ¥æä¸æ¶é´", |
| | | minWidth: 150, |
| | | formatter: (row, column, cellValue) => { |
| | | if (typeof cellValue !== "string") { |
| | | return ""; |
| | | } |
| | | } |
| | | handleQuery(); |
| | | }; |
| | | const replacements = { |
| | | MON: "å¨ä¸", |
| | | TUE: "å¨äº", |
| | | WED: "å¨ä¸", |
| | | THU: "å¨å", |
| | | FRI: "å¨äº", |
| | | SAT: "å¨å
", |
| | | SUN: "卿¥", |
| | | }; |
| | | return cellValue.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, (match) => replacements[match]); |
| | | }, |
| | | }, |
| | | { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, |
| | | { prop: "createTime", label: "ç»è®°æ¥æ", width: 130 }, |
| | | ]); |
| | | |
| | | // æ°å¢ / ç¼è¾ |
| | | const handleAdd = row => { |
| | | const type = row ? "edit" : "add"; |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | const isEnabledColumn = { |
| | | prop: "isEnabled", |
| | | label: "æ¯å¦å¯ç¨", |
| | | minWidth: 110, |
| | | dataType: "slot", |
| | | slot: "isEnabledSwitch", |
| | | }; |
| | | |
| | | // æ¥çéä»¶ |
| | | const viewFile = row => { |
| | | nextTick(() => { |
| | | viewFiles.value?.openDialog(row); |
| | | }); |
| | | }; |
| | | // å·¡æ£ç¶æåï¼ä»
宿¶ä»»å¡è®°å½æ¾ç¤ºï¼ |
| | | const inspectionStatusColumn = { |
| | | prop: "inspectionStatus", |
| | | label: "å·¡æ£ç¶æ", |
| | | minWidth: 100, |
| | | dataType: "tag", |
| | | formatData: (value) => |
| | | ({ |
| | | 1: "å¾
å·¡æ£", |
| | | 2: "已巡æ£", |
| | | }[value] || ""), |
| | | formatType: (value) => |
| | | ({ |
| | | 1: "warning", |
| | | 2: "success", |
| | | }[value] || "info"), |
| | | }; |
| | | // å·¡æ£ç»æåï¼ä»
宿¶ä»»å¡è®°å½æ¾ç¤ºï¼ |
| | | const inspectionResultColumn = { |
| | | prop: "inspectionResult", |
| | | label: "å·¡æ£ç»æ", |
| | | minWidth: 100, |
| | | dataType: "tag", |
| | | formatData: (value) => |
| | | ({ |
| | | 1: "æ£å¸¸", |
| | | 2: "å¼å¸¸", |
| | | }[value] || "-"), |
| | | formatType: (value) => |
| | | ({ |
| | | 1: "success", |
| | | 2: "error", |
| | | }[value] || "info"), |
| | | }; |
| | | |
| | | const openUploadDialog = row => { |
| | | nextTick(() => { |
| | | uploadFiles.value?.openDialog(row); |
| | | }); |
| | | }; |
| | | |
| | | // å é¤æä½ |
| | | const handleDelete = () => { |
| | | if (!selectedRows.value.length) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return; |
| | | } |
| | | |
| | | const deleteIds = selectedRows.value.map(item => item.id); |
| | | |
| | | proxy.$modal |
| | | .confirm("æ¯å¦ç¡®è®¤å 餿鿰æ®é¡¹ï¼") |
| | | .then(() => { |
| | | return delTimingTask(deleteIds); |
| | | }) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | handleQuery(); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | // å¤éåæ´ |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | // æ ¹æ®å½åéä¸çæ ç¾é¡µè°ç¨ä¸åçå¯¼åºæ¥å£ |
| | | if (activeRadio.value === "taskManage") { |
| | | // å·¡æ£ä»»å¡ |
| | | proxy.download("/timingTask/export", {}, "å·¡æ£ä»»å¡.xlsx"); |
| | | } else if (activeRadio.value === "task") { |
| | | // å·¡æ£è®°å½ |
| | | proxy.download("/inspectionTask/export", {}, "å·¡æ£è®°å½.xlsx"); |
| | | const getOperationColumn = (operations) => { |
| | | if (!operations || operations.length === 0) { |
| | | return null; |
| | | } |
| | | return { |
| | | label: "æä½", |
| | | width: 130, |
| | | fixed: "right", |
| | | dataType: "action", |
| | | operation: operations |
| | | .map((op) => { |
| | | switch (op) { |
| | | case "edit": |
| | | return { |
| | | name: "ç¼è¾", |
| | | clickFun: handleAdd, |
| | | color: "#409EFF", |
| | | }; |
| | | case "viewFile": |
| | | return { |
| | | name: "æ¥çéä»¶", |
| | | clickFun: viewFile, |
| | | color: "#67C23A", |
| | | }; |
| | | default: |
| | | return null; |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | .filter(Boolean), |
| | | }; |
| | | }; |
| | | |
| | | const loadAreaTree = async () => { |
| | | const { data } = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(data) ? data : []; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | loadAreaTree(); |
| | | radioChange("taskManage"); |
| | | }); |
| | | |
| | | const radioChange = (value) => { |
| | | if (value === "taskManage") { |
| | | const operationColumn = getOperationColumn(["edit"]); |
| | | tableColumns.value = [...columns.value, isEnabledColumn, ...(operationColumn ? [operationColumn] : [])]; |
| | | } else { |
| | | const operationColumn = getOperationColumn(["viewFile"]); |
| | | // 宿¶ä»»å¡è®°å½æ·»å å·¡æ£ç¶æå |
| | | tableColumns.value = [...columns.value, inspectionStatusColumn, inspectionResultColumn, ...(operationColumn ? [operationColumn] : [])]; |
| | | // 忢å°å®æ¶ä»»å¡è®°å½æ¶ï¼é»è®¤æ¥è¯¢å½å¤© |
| | | queryDate.value = dayjs().format("YYYY-MM-DD"); |
| | | queryParams.isEnabled = undefined; |
| | | } |
| | | pageNum.value = 1; |
| | | pageSize.value = 10; |
| | | getList(); |
| | | }; |
| | | |
| | | const handleQuery = () => { |
| | | pageNum.value = 1; |
| | | pageSize.value = 10; |
| | | getList(); |
| | | }; |
| | | |
| | | const handlePagination = (val) => { |
| | | pageNum.value = val.page; |
| | | pageSize.value = val.limit; |
| | | getList(); |
| | | }; |
| | | |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | // è®¾ç½®æ¥æåæ°ï¼å®æ¶ä»»å¡è®°å½æ¶ï¼ |
| | | if (activeRadio.value === "task" && queryDate.value) { |
| | | queryParams.createTimeStart = `${queryDate.value} 00:00:00`; |
| | | queryParams.createTimeEnd = `${queryDate.value} 23:59:59`; |
| | | } else { |
| | | queryParams.createTimeStart = undefined; |
| | | queryParams.createTimeEnd = undefined; |
| | | } |
| | | const params = { |
| | | ...queryParams, |
| | | size: pageSize.value, |
| | | current: pageNum.value, |
| | | }; |
| | | const apiCall = |
| | | activeRadio.value === "task" ? inspectionTaskList(params) : timingTaskList(params); |
| | | |
| | | apiCall |
| | | .then((res) => { |
| | | const rawData = res?.data?.records || []; |
| | | tableData.value = rawData.map((item) => { |
| | | const processedItem = { ...item }; |
| | | if (activeRadio.value === "taskManage") { |
| | | processedItem.isEnabled = Number( |
| | | processedItem.isEnabled ?? processedItem.status ?? 1 |
| | | ); |
| | | processedItem.enableSwitchLoading = false; |
| | | } |
| | | if (processedItem.inspector) { |
| | | if (typeof processedItem.inspector === "string") { |
| | | processedItem.inspector = processedItem.inspector |
| | | .split(",") |
| | | .map((text) => text.trim()) |
| | | .filter(Boolean); |
| | | } else if (!Array.isArray(processedItem.inspector)) { |
| | | processedItem.inspector = [processedItem.inspector]; |
| | | } |
| | | } else { |
| | | processedItem.inspector = []; |
| | | } |
| | | return processedItem; |
| | | }); |
| | | total.value = res?.data?.total || 0; |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | |
| | | const resetQuery = () => { |
| | | queryParams.taskName = ""; |
| | | queryParams.areaId = undefined; |
| | | queryParams.isEnabled = undefined; |
| | | queryParams.createTimeStart = undefined; |
| | | queryParams.createTimeEnd = undefined; |
| | | // 宿¶ä»»å¡è®°å½æ¶é置为å½å¤© |
| | | queryDate.value = dayjs().format("YYYY-MM-DD"); |
| | | handleQuery(); |
| | | }; |
| | | |
| | | const handleAdd = (row) => { |
| | | const type = row ? "edit" : "add"; |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | |
| | | const viewFile = (row) => { |
| | | nextTick(() => { |
| | | viewFiles.value?.openDialog(row); |
| | | }); |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | if (!selectedRows.value.length) { |
| | | proxy.$modal.msgWarning("è¯·éæ©è¦å é¤çæ°æ®"); |
| | | return; |
| | | } |
| | | const deleteIds = selectedRows.value.map((item) => item.id); |
| | | proxy.$modal |
| | | .confirm("æ¯å¦ç¡®è®¤å 餿鿰æ®é¡¹ï¼") |
| | | .then(() => delTimingTask(deleteIds)) |
| | | .then(() => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | handleQuery(); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | |
| | | const handleTimingTaskEnableBeforeChange = async (row) => { |
| | | if (row.enableSwitchLoading) { |
| | | return false; |
| | | } |
| | | const nextValue = Number(row.isEnabled) === 1 ? 0 : 1; |
| | | row.enableSwitchLoading = true; |
| | | try { |
| | | const res = await changeTimingTaskEnable({ |
| | | id: row.id, |
| | | isEnabled: nextValue, |
| | | }); |
| | | if (res?.code !== 200) { |
| | | throw new Error(res?.msg || "æ´æ°å¤±è´¥"); |
| | | } |
| | | ElMessage.success("å¯ç¨ç¶æå·²æ´æ°"); |
| | | return true; |
| | | } catch (error) { |
| | | proxy.$modal.msgError(error?.message || "å¯ç¨ç¶ææ´æ°å¤±è´¥"); |
| | | return false; |
| | | } finally { |
| | | row.enableSwitchLoading = false; |
| | | } |
| | | }; |
| | | |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | if (activeRadio.value === "taskManage") { |
| | | proxy.download("/timingTask/export", {}, "宿¶ä»»å¡ç®¡ç.xlsx"); |
| | | } else { |
| | | proxy.download("/inspectionTask/export", {}, "宿¶ä»»å¡è®°å½.xlsx"); |
| | | } |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .person-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 4px; |
| | | } |
| | | .toolbar { |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | |
| | | .person-tag { |
| | | margin-right: 4px; |
| | | margin-bottom: 2px; |
| | | } |
| | | .person-tags { |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | gap: 4px; |
| | | } |
| | | |
| | | .no-data { |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | .person-tag { |
| | | margin-right: 4px; |
| | | margin-bottom: 2px; |
| | | } |
| | | |
| | | .no-data { |
| | | color: #909399; |
| | | font-size: 14px; |
| | | } |
| | | </style> |
| | |
| | | formRef.value.loadForm(id); |
| | | }; |
| | | |
| | | const openCreateModal = async (areaId) => { |
| | | openModal(); |
| | | await nextTick(); |
| | | formRef.value.setAreaId(areaId); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openModal, |
| | | loadForm, |
| | | openCreateModal, |
| | | }); |
| | | </script> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <div class="app-container ledger-view"> |
| | | <div class="left-panel"> |
| | | <div class="tree-toolbar"> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 200px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | v-model="treeKeyword" |
| | | style="width: calc(100% - 102px)" |
| | | placeholder="请è¾å
¥åºååç§°" |
| | | clearable |
| | | @change="getTableData" |
| | | prefix-icon="Search" |
| | | @input="filterTree" |
| | | @clear="filterTree" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | <el-button type="primary" @click="openAreaDialog('addRoot')">æ°å¢åºå</el-button> |
| | | </div> |
| | | <div class="tree-actions"> |
| | | <el-button link type="primary" @click="resetTreeSelection">å
¨é¨åºå</el-button> |
| | | </div> |
| | | <el-tree |
| | | ref="treeRef" |
| | | v-loading="treeLoading" |
| | | :data="treeData" |
| | | :props="treeProps" |
| | | node-key="id" |
| | | highlight-current |
| | | default-expand-all |
| | | :expand-on-click-node="false" |
| | | :filter-node-method="filterTreeNode" |
| | | class="ledger-tree" |
| | | @node-click="handleTreeNodeClick" |
| | | > |
| | | <template #default="{ node, data }"> |
| | | <div class="tree-node"> |
| | | <span class="tree-node-content"> |
| | | <el-icon class="tree-node-icon"> |
| | | <component |
| | | :is=" |
| | | data.children && data.children.length > 0 |
| | | ? node.expanded |
| | | ? 'FolderOpened' |
| | | : 'Folder' |
| | | : 'Tickets' |
| | | " |
| | | /> |
| | | </el-icon> |
| | | <span class="tree-node-label">{{ data.areaName }}</span> |
| | | </span> |
| | | <div class="tree-node-actions"> |
| | | <el-button link type="primary" @click.stop="openAreaDialog('edit', data)">ç¼è¾</el-button> |
| | | <el-button link type="primary" @click.stop="openAreaDialog('addChild', data)">æ°å¢</el-button> |
| | | <el-button |
| | | v-if="!hasChildren(data)" |
| | | link |
| | | type="danger" |
| | | @click.stop="handleDeleteArea(data)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-tree> |
| | | </div> |
| | | |
| | | <div class="right-panel"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 200px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="filters.deviceModel" |
| | | style="width: 200px" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºå"> |
| | | <el-input |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºå"> |
| | | <el-input |
| | | v-model="filters.supplierName" |
| | | style="width: 200px" |
| | | placeholder="请è¾å
¥ä¾åºå" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æ:"> |
| | | <el-date-picker v-model="filters.entryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD" type="daterange" |
| | | placeholder="è¯·éæ©" clearable @change="changeDaterange" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData">æç´¢</el-button> |
| | | <el-button @click="resetFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <div></div> |
| | | <div> |
| | | <el-button type="primary" @click="add" icon="Plus"> æ°å¢ </el-button> |
| | | <el-button type="info" @click="handleImport" icon="Upload">导å
¥</el-button> |
| | | <el-button @click="handleOut" icon="download">导åº</el-button> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | @click="deleteRow(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥æ¥æ"> |
| | | <el-date-picker |
| | | v-model="filters.entryDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="daterange" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | @change="changeDaterange" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="getTableData">æç´¢</el-button> |
| | | <el-button @click="handleResetFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <div class="actions-tip"> |
| | | <span v-if="selectedAreaName">å½ååºåï¼{{ selectedAreaName }}</span> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" icon="Plus" @click="add">æ°å¢</el-button> |
| | | <el-button type="info" icon="Upload" @click="handleImport">导å
¥</el-button> |
| | | <el-button icon="download" @click="handleOut">导åº</el-button> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0" |
| | | @click="deleteRow(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | /> |
| | | </div> |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | > |
| | | </PIMTable> |
| | | </div> |
| | | <Modal ref="modalRef" @success="getTableData"></Modal> |
| | | |
| | | <Modal ref="modalRef" @success="getTableData" /> |
| | | |
| | | <el-dialog |
| | | v-model="areaDialogVisible" |
| | | :title="areaDialogTitle" |
| | | width="480px" |
| | | @close="closeAreaDialog" |
| | | > |
| | | <el-form ref="areaFormRef" :model="areaForm" :rules="areaRules" label-width="88px"> |
| | | <el-form-item label="åºååç§°" prop="areaName"> |
| | | <el-input v-model="areaForm.areaName" placeholder="请è¾å
¥åºååç§°" /> |
| | | </el-form-item> |
| | | <el-form-item label="æåº" prop="sort"> |
| | | <el-input-number v-model="areaForm.sort" :min="0" :step="1" style="width: 100%" /> |
| | | </el-form-item> |
| | | <el-form-item label="夿³¨" prop="remark"> |
| | | <el-input |
| | | v-model="areaForm.remark" |
| | | type="textarea" |
| | | :rows="4" |
| | | maxlength="200" |
| | | show-word-limit |
| | | placeholder="请è¾å
¥å¤æ³¨" |
| | | /> |
| | | </el-form-item> |
| | | </el-form> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitAreaForm">ç¡®å®</el-button> |
| | | <el-button @click="closeAreaDialog">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <el-dialog v-model="qrDialogVisible" title="äºç»´ç " width="300px" draggable> |
| | | <div style="text-align:center;"> |
| | | <img :src="qrCodeUrl" alt="äºç»´ç " style="width:200px;height:200px;" /> |
| | | <div style="margin:10px 0;"> |
| | | <div class="qr-dialog"> |
| | | <img :src="qrCodeUrl" alt="äºç»´ç " class="qr-image" /> |
| | | <div class="qr-footer"> |
| | | <el-button type="primary" @click="downloadQRCode">ä¸è½½äºç»´ç å¾ç</el-button> |
| | | </div> |
| | | </div> |
| | | </el-dialog> |
| | | |
| | | <!-- 导å
¥å¯¹è¯æ¡ --> |
| | | |
| | | <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body> |
| | | <el-upload |
| | | ref="uploadRef" |
| | |
| | | <div class="el-upload__text">å°æä»¶æå°æ¤å¤ï¼æ<em>ç¹å»ä¸ä¼ </em></div> |
| | | <template #tip> |
| | | <div class="el-upload__tip text-center"> |
| | | <span>ä»
å
许导å
¥xlsãxlsxæ ¼å¼æä»¶ã</span> |
| | | <el-link type="primary" :underline="false" style="font-size: 12px; vertical-align: baseline; margin-left: 5px;" @click="importTemplate">ä¸è½½æ¨¡æ¿</el-link> |
| | | <span>ä»
å
许导å
¥ xlsãxlsx æ ¼å¼æä»¶ã</span> |
| | | <el-link |
| | | type="primary" |
| | | :underline="false" |
| | | style="font-size: 12px; vertical-align: baseline; margin-left: 5px" |
| | | @click="importTemplate" |
| | | > |
| | | ä¸è½½æ¨¡æ¿ |
| | | </el-link> |
| | | </div> |
| | | </template> |
| | | </el-upload> |
| | | <template #footer> |
| | | <div class="dialog-footer"> |
| | | <el-button type="primary" @click="submitFileForm">ç¡® å®</el-button> |
| | | <el-button @click="upload.open = false">å æ¶</el-button> |
| | | <el-button type="primary" @click="submitFileForm">ç¡®å®</el-button> |
| | | <el-button @click="upload.open = false">åæ¶</el-button> |
| | | </div> |
| | | </template> |
| | | </el-dialog> |
| | | |
| | | <!-- 详æ
å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="detailDialogVisible" title="设å¤å°è´¦è¯¦æ
" width="60%" draggable> |
| | | <el-descriptions :column="2" border> |
| | | <el-descriptions-item label="设å¤åç§°">{{ detailData.deviceName }}</el-descriptions-item> |
| | | <el-descriptions-item label="è§æ ¼åå·">{{ detailData.deviceModel }}</el-descriptions-item> |
| | | <el-descriptions-item label="设å¤åç">{{ detailData.deviceBrand }}</el-descriptions-item> |
| | | <el-descriptions-item label="设å¤ç±»å">{{ detailData.type }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¾åºå">{{ detailData.supplierName }}</el-descriptions-item> |
| | | <el-descriptions-item label="åæ¾ä½ç½®">{{ detailData.storageLocation }}</el-descriptions-item> |
| | | <el-descriptions-item label="åä½">{{ detailData.unit }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ°é">{{ detailData.number }}</el-descriptions-item> |
| | | <el-descriptions-item label="å¯ç¨ææ§">{{ detailData.isDepr === 1 ? 'æ¯' : 'å¦' }}</el-descriptions-item> |
| | | <el-descriptions-item label="æ¯å¹´ææ§éé¢">{{ detailData.annualDepreciationAmount }}</el-descriptions-item> |
| | | <el-descriptions-item label="å«ç¨åä»·">{{ detailData.taxIncludingPriceUnit }}</el-descriptions-item> |
| | | <el-descriptions-item label="å«ç¨æ»ä»·">{{ detailData.taxIncludingPriceTotal }}</el-descriptions-item> |
| | | <el-descriptions-item label="ç¨ç(%)">{{ detailData.taxRate }}</el-descriptions-item> |
| | | <el-descriptions-item label="ä¸å«ç¨æ»ä»·">{{ detailData.unTaxIncludingPriceTotal }}</el-descriptions-item> |
| | | <el-descriptions-item label="å½å
¥æ¥æ">{{ detailData.createTime }}</el-descriptions-item> |
| | | <el-descriptions-item label="é¢è®¡è¿è¡æ¶é´">{{ detailData.planRuntimeTime ? dayjs(detailData.planRuntimeTime).format('YYYY-MM-DD') : '' }}</el-descriptions-item> |
| | | <el-descriptions-item label="设å¤å¾ç" :span="2"> |
| | | <div v-if="detailData.storageBlobVOs && detailData.storageBlobVOs.length > 0" style="display: flex; gap: 10px; flex-wrap: wrap;"> |
| | | <el-image |
| | | v-for="(file, index) in detailData.storageBlobVOs" |
| | | :key="index" |
| | | :src="file.previewURL || file.url" |
| | | :preview-src-list="detailData.storageBlobVOs.map(u => u.previewURL || u.url)" |
| | | :initial-index="index" |
| | | style="width: 100px; height: 100px" |
| | | fit="cover" |
| | | /> |
| | | </div> |
| | | <span v-else>æ å¾ç</span> |
| | | </el-descriptions-item> |
| | | </el-descriptions> |
| | | <template #footer> |
| | | <el-button @click="detailDialogVisible = false">å
³é</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | |
| | | |
| | | <script setup> |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | // import { Search } from "@element-plus/icons-vue"; |
| | | import { getLedgerPage, delLedger, getLedgerById } from "@/api/equipmentManagement/ledger"; |
| | | import { getLedgerPage, delLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { |
| | | getDeviceAreaTree, |
| | | getDeviceAreaDetail, |
| | | addDeviceArea, |
| | | updateDeviceArea, |
| | | deleteDeviceArea, |
| | | } from "@/api/equipmentManagement/deviceArea"; |
| | | import { onMounted, getCurrentInstance, ref, reactive } from "vue"; |
| | | import Modal from "./Modal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | |
| | | name: "设å¤å°è´¦", |
| | | }); |
| | | |
| | | // è¡¨æ ¼å¤éæ¡éä¸é¡¹ |
| | | const multipleList = ref([]); |
| | | const { proxy } = getCurrentInstance(); |
| | | const modalRef = ref(); |
| | | const treeRef = ref(); |
| | | const areaFormRef = ref(); |
| | | const treeKeyword = ref(""); |
| | | const treeLoading = ref(false); |
| | | const treeData = ref([]); |
| | | const selectedAreaName = ref(""); |
| | | const areaDialogVisible = ref(false); |
| | | const areaDialogTitle = ref("æ°å¢åºå"); |
| | | const areaDialogMode = ref("addRoot"); |
| | | const qrDialogVisible = ref(false); |
| | | const qrCodeUrl = ref(""); |
| | | const qrRowData = ref(null); |
| | | const uploadRef = ref(null); |
| | | |
| | | const detailDialogVisible = ref(false); |
| | | const detailData = ref({}); |
| | | const treeProps = { |
| | | children: "children", |
| | | label: "areaName", |
| | | }; |
| | | |
| | | // 导å
¥ç¸å
³ |
| | | const uploadRef = ref(null) |
| | | const upload = reactive({ |
| | | // æ¯å¦æ¾ç¤ºå¼¹åºå± |
| | | open: false, |
| | | // å¼¹åºå±æ é¢ |
| | | title: "", |
| | | // æ¯å¦ç¦ç¨ä¸ä¼ |
| | | isUploading: false, |
| | | // 设置ä¸ä¼ ç请æ±å¤´é¨ |
| | | headers: { Authorization: "Bearer " + getToken() }, |
| | | // ä¸ä¼ çå°å |
| | | url: import.meta.env.VITE_APP_BASE_API + "/device/ledger/import" |
| | | }) |
| | | url: import.meta.env.VITE_APP_BASE_API + "/device/ledger/import", |
| | | }); |
| | | |
| | | const areaForm = reactive({ |
| | | id: undefined, |
| | | areaName: "", |
| | | parentId: undefined, |
| | | sort: 0, |
| | | remark: "", |
| | | }); |
| | | |
| | | const areaRules = { |
| | | areaName: [{ required: true, message: "请è¾å
¥åºååç§°", trigger: "blur" }], |
| | | }; |
| | | |
| | | const { |
| | | filters, |
| | |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | getLedgerPage, |
| | |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | supplierName: undefined, |
| | | entryDate: undefined, |
| | | entryDateStart: undefined, |
| | | entryDateEnd: undefined, |
| | | areaId: undefined, |
| | | areaName: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "æå¨åºå", |
| | | prop: "areaName", |
| | | }, |
| | | { |
| | | label: "设å¤åç§°", |
| | | prop: "deviceName", |
| | |
| | | label: "è§æ ¼åå·", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "设å¤åç", |
| | | prop: "deviceBrand", |
| | | }, |
| | | // { |
| | | // label: "设å¤åç", |
| | | // prop: "deviceBrand", |
| | | // }, |
| | | { |
| | | label: "设å¤ç±»å", |
| | | prop: "type", |
| | |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "createTime", |
| | | formatData: (v) => { |
| | | if (!v) return ''; |
| | | // 妿å
嫿¶åç§ï¼åªåæ¥æé¨å |
| | | if (v.includes(' ')) { |
| | | return v.split(' ')[0]; |
| | | } |
| | | return v; |
| | | if (!v) return ""; |
| | | return v.includes(" ") ? v.split(" ")[0] : v; |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: 'right', |
| | | width: 180, |
| | | operation: [ |
| | | { |
| | | label: "ç©è设å¤", |
| | | prop: "isIotDevice", |
| | | formatData: (v) => { |
| | | return v === 1 ? "æ¯" : "å¦"; |
| | | }, |
| | | }, |
| | | { |
| | | label: "å¤é¨ç¼ç ", |
| | | prop: "externalCode", |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | fixed: "right", |
| | | width: 150, |
| | | operation: [ |
| | | { |
| | | name: "详æ
", |
| | | name: "ç¼è¾", |
| | | clickFun: (row) => { |
| | | handleDetail(row); |
| | | edit(row.id); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ç¼è¾", |
| | | clickFun: (row) => { |
| | | edit(row.id) |
| | | }, |
| | | }, |
| | | { |
| | | name: "äºç»´ç ", |
| | | clickFun: (row) => { |
| | | showQRCode(row) |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | { |
| | | name: "çæäºç»´ç ", |
| | | clickFun: (row) => { |
| | | showQRCode(row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ] |
| | | ); |
| | | |
| | | // å¤éååä»ä¹ |
| | | const loadTreeData = async () => { |
| | | treeLoading.value = true; |
| | | try { |
| | | const res = await getDeviceAreaTree(); |
| | | treeData.value = Array.isArray(res?.data) ? res.data : Array.isArray(res) ? res : []; |
| | | } finally { |
| | | treeLoading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const resetAreaForm = () => { |
| | | areaForm.id = undefined; |
| | | areaForm.areaName = ""; |
| | | areaForm.parentId = undefined; |
| | | areaForm.sort = 0; |
| | | areaForm.remark = ""; |
| | | }; |
| | | |
| | | const filterTree = () => { |
| | | treeRef.value?.filter(treeKeyword.value); |
| | | }; |
| | | |
| | | const filterTreeNode = (value, data) => { |
| | | if (!value) { |
| | | return true; |
| | | } |
| | | return String(data.areaName || "").includes(value); |
| | | }; |
| | | |
| | | const handleTreeNodeClick = (data) => { |
| | | filters.areaId = data.id; |
| | | filters.areaName = data.areaName; |
| | | selectedAreaName.value = data.areaName || ""; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const openAreaDialog = async (mode, row) => { |
| | | areaDialogMode.value = mode; |
| | | areaDialogTitle.value = |
| | | mode === "edit" ? "ç¼è¾åºå" : mode === "addChild" ? "æ°å¢ååºå" : "æ°å¢åºå"; |
| | | resetAreaForm(); |
| | | areaDialogVisible.value = true; |
| | | if (mode === "addChild") { |
| | | areaForm.parentId = row.id; |
| | | areaForm.sort = 0; |
| | | return; |
| | | } |
| | | if (mode === "edit" && row?.id) { |
| | | const res = await getDeviceAreaDetail(row.id); |
| | | const detail = res?.data || {}; |
| | | areaForm.id = detail.id; |
| | | areaForm.areaName = detail.areaName || ""; |
| | | areaForm.parentId = detail.parentId; |
| | | areaForm.sort = detail.sort ?? 0; |
| | | areaForm.remark = detail.remark || ""; |
| | | } |
| | | }; |
| | | |
| | | const closeAreaDialog = () => { |
| | | areaDialogVisible.value = false; |
| | | areaFormRef.value?.resetFields(); |
| | | resetAreaForm(); |
| | | }; |
| | | |
| | | const submitAreaForm = () => { |
| | | areaFormRef.value?.validate(async (valid) => { |
| | | if (!valid) { |
| | | return; |
| | | } |
| | | const submitData = { |
| | | id: areaForm.id, |
| | | areaName: areaForm.areaName, |
| | | parentId: areaForm.parentId, |
| | | sort: areaForm.sort, |
| | | remark: areaForm.remark, |
| | | }; |
| | | const request = areaDialogMode.value === "edit" ? updateDeviceArea : addDeviceArea; |
| | | const { code } = await request(submitData); |
| | | if (code === 200) { |
| | | ElMessage.success(areaDialogMode.value === "edit" ? "ä¿®æ¹æå" : "æ°å¢æå"); |
| | | closeAreaDialog(); |
| | | await loadTreeData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const handleDeleteArea = (row) => { |
| | | if (hasChildren(row)) { |
| | | ElMessage.warning("å½ååºååå¨ä¸çº§åºåï¼ä¸è½å é¤"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("æ¤æä½å°å é¤è¯¥è®¾å¤åºåï¼æ¯å¦ç»§ç»ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const { code } = await deleteDeviceArea([row.id]); |
| | | if (code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | if (filters.areaId === row.id) { |
| | | resetTreeSelection(); |
| | | } |
| | | await loadTreeData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | const hasChildren = (row) => Array.isArray(row?.children) && row.children.length > 0; |
| | | |
| | | const resetTreeSelection = () => { |
| | | treeRef.value?.setCurrentKey(null); |
| | | selectedAreaName.value = ""; |
| | | filters.areaId = undefined; |
| | | filters.areaName = undefined; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleSelectionChange = (selectionList) => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | |
| | | const add = () => { |
| | | modalRef.value.openModal(); |
| | | }; |
| | | |
| | | const edit = (id) => { |
| | | modalRef.value.loadForm(id); |
| | | }; |
| | | const handleDetail = async (row) => { |
| | | const { code, data } = await getLedgerById(row.id); |
| | | if (code == 200) { |
| | | detailData.value = data; |
| | | detailDialogVisible.value = true; |
| | | } |
| | | }; |
| | | |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | const deleteRow = (id) => { |
| | | ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥æä»¶, æ¯å¦ç»§ç»?", "æç¤º", { |
| | | ElMessageBox.confirm("æ¤æä½å°æ°¸ä¹
å é¤è¯¥æ°æ®ï¼æ¯å¦ç»§ç»ï¼", "æç¤º", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleResetFilters = () => { |
| | | filters.deviceName = undefined; |
| | | filters.deviceModel = undefined; |
| | | filters.supplierName = undefined; |
| | | filters.entryDate = undefined; |
| | | filters.entryDateStart = undefined; |
| | | filters.entryDateEnd = undefined; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | ElMessageBox.confirm("å½åæ¥è¯¢ç»æå°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download(`/device/ledger/export`, {}, "设å¤å°è´¦æ¡£æ¡.xlsx"); |
| | | proxy.download("/device/ledger/export", {}, "设å¤å°è´¦æ¡£æ¡.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | |
| | | }; |
| | | |
| | | const showQRCode = async (row) => { |
| | | // ç´æ¥ä½¿ç¨URLï¼ä¸è¦ç¨JSON.stringifyå
è£
|
| | | const qrContent = proxy.javaApi + '/device-info?deviceId=' + row.id; |
| | | const qrDataUrl = await QRCode.toDataURL(qrContent, { width: 200, margin: 2 }); |
| | | |
| | | // å建canvasåæå¸¦åç§°çäºç»´ç å¾ç |
| | | const canvas = document.createElement('canvas'); |
| | | const ctx = canvas.getContext('2d'); |
| | | const qrSize = 200; |
| | | const textHeight = 30; |
| | | const padding = 10; |
| | | canvas.width = qrSize + padding * 2; |
| | | canvas.height = qrSize + textHeight + padding * 2; |
| | | |
| | | // å¡«å
ç½è²èæ¯ |
| | | ctx.fillStyle = '#ffffff'; |
| | | ctx.fillRect(0, 0, canvas.width, canvas.height); |
| | | |
| | | // ç»å¶äºç»´ç |
| | | const qrImg = new Image(); |
| | | qrImg.src = qrDataUrl; |
| | | await new Promise((resolve) => { qrImg.onload = resolve; }); |
| | | ctx.drawImage(qrImg, padding, padding, qrSize, qrSize); |
| | | |
| | | // ç»å¶è®¾å¤åç§° |
| | | ctx.fillStyle = '#333333'; |
| | | ctx.font = 'bold 14px Arial'; |
| | | ctx.textAlign = 'center'; |
| | | ctx.fillText(row.deviceName || '', canvas.width / 2, qrSize + padding + 20); |
| | | |
| | | qrCodeUrl.value = canvas.toDataURL('image/png'); |
| | | const qrContent = proxy.javaApi + "/device-info?deviceId=" + row.id; |
| | | qrCodeUrl.value = await QRCode.toDataURL(qrContent); |
| | | qrRowData.value = row; |
| | | qrDialogVisible.value = true; |
| | | }; |
| | |
| | | a.click(); |
| | | }; |
| | | |
| | | // 导å
¥æé®æä½ |
| | | const handleImport = () => { |
| | | upload.title = "设å¤å°è´¦å¯¼å
¥" |
| | | upload.open = true |
| | | } |
| | | upload.title = "设å¤å°è´¦å¯¼å
¥"; |
| | | upload.open = true; |
| | | }; |
| | | |
| | | // ä¸è½½æ¨¡æ¿æä½ |
| | | const importTemplate = () => { |
| | | proxy.download("/device/ledger/downloadTemplate", {}, `设å¤å°è´¦å¯¼å
¥æ¨¡æ¿_${new Date().getTime()}.xlsx`) |
| | | } |
| | | proxy.download("/device/ledger/downloadTemplate", {}, `设å¤å°è´¦å¯¼å
¥æ¨¡æ¿_${new Date().getTime()}.xlsx`); |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ ä¸å¤ç |
| | | const handleFileUploadProgress = (event, file, fileList) => { |
| | | upload.isUploading = true |
| | | } |
| | | const handleFileUploadProgress = () => { |
| | | upload.isUploading = true; |
| | | }; |
| | | |
| | | // æä»¶ä¸ä¼ æåå¤ç |
| | | const handleFileSuccess = (response, file, fileList) => { |
| | | upload.open = false |
| | | upload.isUploading = false |
| | | proxy.$refs["uploadRef"].handleRemove(file) |
| | | proxy.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导å
¥ç»æ", { dangerouslyUseHTMLString: true }) |
| | | getTableData() |
| | | } |
| | | const handleFileSuccess = (response, file) => { |
| | | upload.open = false; |
| | | upload.isUploading = false; |
| | | uploadRef.value?.handleRemove(file); |
| | | proxy.$alert( |
| | | "<div style='overflow:auto;overflow-x:hidden;max-height:70vh;padding:10px 20px 0;'>" + |
| | | response.msg + |
| | | "</div>", |
| | | "导å
¥ç»æ", |
| | | { dangerouslyUseHTMLString: true } |
| | | ); |
| | | getTableData(); |
| | | }; |
| | | |
| | | // æäº¤ä¸ä¼ æä»¶ |
| | | const submitFileForm = () => { |
| | | proxy.$refs["uploadRef"].submit() |
| | | } |
| | | uploadRef.value?.submit(); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | onMounted(async () => { |
| | | await loadTreeData(); |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | .ledger-view { |
| | | display: flex; |
| | | gap: 20px; |
| | | } |
| | | |
| | | .left-panel { |
| | | width: 320px; |
| | | min-width: 320px; |
| | | padding: 16px; |
| | | background: #fff; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .right-panel { |
| | | flex: 1; |
| | | min-width: 0; |
| | | padding: 16px; |
| | | background: #fff; |
| | | border-radius: 4px; |
| | | } |
| | | |
| | | .tree-toolbar { |
| | | display: flex; |
| | | gap: 10px; |
| | | align-items: center; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .tree-actions { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-bottom: 8px; |
| | | } |
| | | |
| | | .ledger-tree { |
| | | height: calc(100vh - 230px); |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .tree-node { |
| | | flex: 1; |
| | | min-width: 0; |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: space-between; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .tree-node-content { |
| | | display: flex; |
| | | align-items: center; |
| | | min-width: 0; |
| | | } |
| | | |
| | | .tree-node-icon { |
| | | color: #e6a23c; |
| | | margin-right: 8px; |
| | | font-size: 18px; |
| | | } |
| | | |
| | | .tree-node-label { |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | white-space: nowrap; |
| | | } |
| | | |
| | | .tree-node-actions { |
| | | flex-shrink: 0; |
| | | } |
| | | |
| | | .table_list { |
| | | margin-top: 0; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 10px; |
| | | gap: 12px; |
| | | } |
| | | |
| | | .actions-tip { |
| | | color: #606266; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .qr-dialog { |
| | | text-align: center; |
| | | } |
| | | |
| | | .qr-image { |
| | | width: 200px; |
| | | height: 200px; |
| | | } |
| | | |
| | | .qr-footer { |
| | | margin: 10px 0; |
| | | } |
| | | </style> |
| | |
| | | form.value.entryDate = getCurrentDate(); |
| | | } |
| | | |
| | | // ä¸ä¼ åæ ¡æ£ |
| | | function handleBeforeUpload(file) { |
| | | proxy.$modal.loading("æ£å¨ä¸ä¼ æä»¶ï¼è¯·ç¨å..."); |
| | | return true; |
| | | } |
| | | // ä¸ä¼ 失败 |
| | | function handleUploadError(err) { |
| | | proxy.$modal.msgError("ä¸ä¼ æä»¶å¤±è´¥"); |
| | | proxy.$modal.closeLoading(); |
| | | } |
| | | // ä¸ä¼ æååè° |
| | | function handleUploadSuccess(res, file, uploadFiles) { |
| | | proxy.$modal.closeLoading(); |
| | | if (res.code === 200) { |
| | | file.tempId = res.data.tempId; |
| | | form.value.tempFileIds.push(file.tempId); |
| | | proxy.$modal.msgSuccess("ä¸ä¼ æå"); |
| | | } else { |
| | | proxy.$modal.msgError(res.msg); |
| | | proxy.$refs.fileUpload.handleRemove(file); |
| | | } |
| | | } |
| | | // ç§»é¤æä»¶ |
| | | function handleRemove(file) { |
| | | if (operationType.value === "edit") { |
| | | let ids = []; |
| | | ids.push(file.id); |
| | | delLedgerFile(ids).then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | // å¤çæææ¥æè¾å
¥ï¼åªå
è®¸æ£æ´æ° |
| | | const handleValidInput = (value) => { |
| | | if (value === '' || value === null || value === undefined) { |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <div class="search_form mb20"> |
| | | <div> |
| | | <span class="search_title">å½å
¥æ¥æï¼</span> |
| | | <el-date-picker v-model="searchForm.recordDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 160px" |
| | | @change="handleQuery" /> |
| | | <span class="search_title ml10">计éå¨å
·ç¼å·ï¼</span> |
| | | <el-input v-model="searchForm.code" |
| | | placeholder="请è¾å
¥ç¼å·" |
| | | clearable |
| | | style="width: 240px" |
| | | @change="handleQuery" /> |
| | | <span class="search_title ml10">ç¶æï¼</span> |
| | | <el-select v-model="searchForm.status" |
| | | placeholder="è¯·éæ©ç¶æ" |
| | | @change="handleQuery" |
| | | style="width: 160px" |
| | | clearable> |
| | | <el-option label="ææ" |
| | | :value="1"></el-option> |
| | | <el-option label="龿" |
| | | :value="2"></el-option> |
| | | </el-select> |
| | | <el-button type="primary" |
| | | @click="handleQuery" |
| | | style="margin-left: 10px">æç´¢</el-button> |
| | | <el-button @click="handleReset" |
| | | style="margin-left: 10px">éç½®</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" |
| | | @click="openForm('add')">æ°å¢è®¡éå¨å
·</el-button> |
| | | <el-button type="danger" |
| | | plain |
| | | @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :dbRowClick="dbRowClick" |
| | | :rowClassName="rowClassName"></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" |
| | | @close="handleQuery"></form-dia> |
| | | <calibration-dia ref="calibrationDia" |
| | | @close="handleQuery"></calibration-dia> |
| | | <div class="app-container"> |
| | | <div class="search_form"> |
| | | <div> |
| | | <span class="search_title">å½å
¥æ¥æï¼</span> |
| | | <el-date-picker |
| | | v-model="searchForm.recordDate" |
| | | value-format="YYYY-MM-DD" |
| | | format="YYYY-MM-DD" |
| | | type="date" |
| | | placeholder="è¯·éæ©" |
| | | clearable |
| | | style="width: 160px" |
| | | @change="handleQuery" |
| | | /> |
| | | <span class="search_title ml10">计éå¨å
·ç¼å·ï¼</span> |
| | | <el-input v-model="searchForm.code" placeholder="请è¾å
¥ç¼å·" clearable style="width: 240px" @change="handleQuery"/> |
| | | <span class="search_title ml10">ç¶æï¼</span> |
| | | <el-select v-model="searchForm.status" placeholder="è¯·éæ©ç¶æ" @change="handleQuery" style="width: 160px" clearable> |
| | | <el-option label="ææ" :value="1"></el-option> |
| | | <el-option label="龿" :value="2"></el-option> |
| | | </el-select> |
| | | <el-button type="primary" @click="handleQuery" style="margin-left: 10px" |
| | | >æç´¢</el-button |
| | | > |
| | | <el-button @click="handleReset" style="margin-left: 10px">éç½®</el-button> |
| | | </div> |
| | | <div> |
| | | <el-button type="primary" @click="openForm('add')">æ°å¢è®¡éå¨å
·</el-button> |
| | | <el-button type="danger" plain @click="handleDelete">å é¤</el-button> |
| | | <el-button @click="handleOut">导åº</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="table_list"> |
| | | <PIMTable |
| | | rowKey="id" |
| | | :column="tableColumn" |
| | | :tableData="tableData" |
| | | :page="page" |
| | | :isSelection="true" |
| | | @selection-change="handleSelectionChange" |
| | | :tableLoading="tableLoading" |
| | | @pagination="pagination" |
| | | :dbRowClick="dbRowClick" |
| | | ></PIMTable> |
| | | </div> |
| | | <form-dia ref="formDia" @close="handleQuery"></form-dia> |
| | | <calibration-dia ref="calibrationDia" @close="handleQuery"></calibration-dia> |
| | | <files-dia ref="filesDia"></files-dia> |
| | | <rowClickDataForm ref="rowClickData"></rowClickDataForm> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | onMounted, |
| | | ref, |
| | | reactive, |
| | | toRefs, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | } from "vue"; |
| | | import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue"; |
| | | import { ElMessageBox } from "element-plus"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; |
| | | import { |
| | | measuringInstrumentDelete, |
| | | measuringInstrumentListPage, |
| | | } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | | import rowClickDataForm from "./components/rowClickData.vue"; |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore(); |
| | | import {onMounted, ref, reactive, toRefs, getCurrentInstance, nextTick} from "vue"; |
| | | import FormDia from "@/views/equipmentManagement/measurementEquipment/components/formDia.vue"; |
| | | import {ElMessageBox} from "element-plus"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | import CalibrationDia from "@/views/equipmentManagement/measurementEquipment/components/calibrationDia.vue"; |
| | | import { |
| | | measuringInstrumentDelete, |
| | | measuringInstrumentListPage, |
| | | } from "@/api/equipmentManagement/measurementEquipment.js"; |
| | | import FilesDia from "./filesDia.vue"; |
| | | import rowClickDataForm from "./components/rowClickData.vue" |
| | | const { proxy } = getCurrentInstance(); |
| | | const userStore = useUserStore() |
| | | |
| | | const data = reactive({ |
| | | searchForm: { |
| | | recordDate: "", |
| | | code: "", |
| | | status: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | const data = reactive({ |
| | | searchForm: { |
| | | recordDate: "", |
| | | code: "", |
| | | status: "", |
| | | }, |
| | | }); |
| | | const { searchForm } = toRefs(data); |
| | | |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "åºåç¼å·", |
| | | prop: "code", |
| | | minWidth: 150, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "计éå¨å
·åç§°", |
| | | prop: "name", |
| | | width: "160px", |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "æ£å®åä½", |
| | | prop: "unit", |
| | | width: 200, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "è¯ä¹¦ç¼å·", |
| | | prop: "model", |
| | | width: 200, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "ææ°é´å®æ¥æ", |
| | | prop: "mostDate", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "userName", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "recordDate", |
| | | align: "center", |
| | | minWidth: 130, |
| | | }, |
| | | { |
| | | label: "æææ¥æ", |
| | | prop: "valid", |
| | | width: 130, |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | width: 130, |
| | | align: "center", |
| | | formatData: params => { |
| | | if (params === 1) { |
| | | return "ææ"; |
| | | } else if (params === 2) { |
| | | return "龿"; |
| | | } else { |
| | | return null; |
| | | } |
| | | }, |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | width: "130", |
| | | fixed: "right", |
| | | operation: [ |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "ç¼è¾", |
| | | type: "text", |
| | | clickFun: row => { |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const rowClickData = ref([]); |
| | | const filesDia = ref(); |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = row => { |
| | | filesDia.value?.openDialog(row, "measuring_instrument_ledger"); |
| | | }; |
| | | |
| | | const dbRowClick = row => { |
| | | rowClickData.value?.openDialog(row); |
| | | }; |
| | | |
| | | // è¡æ ·å¼ï¼å¿«å°æï¼7天å
ï¼æé¾ææ 红 |
| | | const rowClassName = ({ row }) => { |
| | | console.log("rowClassName called:", row); |
| | | // valid æ¯ææå¤©æ°ï¼mostDate æ¯ææ°æ£å®æ¥æ |
| | | if (row.valid && row.mostDate) { |
| | | const mostDate = new Date(row.mostDate); |
| | | // 计ç®å°ææ¥æ = æ£å®æ¥æ + ææå¤©æ° |
| | | const validDays = parseInt(row.valid) || 0; |
| | | const expireDate = new Date(mostDate); |
| | | expireDate.setDate(expireDate.getDate() + validDays); |
| | | |
| | | const now = new Date(); |
| | | const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24)); |
| | | console.log( |
| | | "row:", |
| | | row.code, |
| | | "validDays:", |
| | | validDays, |
| | | "expireDate:", |
| | | expireDate, |
| | | "diffDays:", |
| | | diffDays |
| | | ); |
| | | // 7天å
å°ææå·²é¾æé½æ 红 |
| | | if (diffDays <= 7) { |
| | | console.log("return warning-row"); |
| | | return "warning-row"; |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "åºåç¼å·", |
| | | prop: "code", |
| | | minWidth:150, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "计éå¨å
·åç§°", |
| | | prop: "name", |
| | | width: '160px', |
| | | align: "center", |
| | | }, |
| | | { |
| | | label: "å®è£
ä½ç½®", |
| | | prop: "instationLocation", |
| | | width: 150, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "æ£å®åä½", |
| | | prop: "unit", |
| | | width: 200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "è¯ä¹¦ç¼å·", |
| | | prop: "model", |
| | | width:200, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "ææ°é´å®æ¥æ", |
| | | prop: "mostDate", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | prop: "userName", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "å½å
¥æ¥æ", |
| | | prop: "recordDate", |
| | | align:"center", |
| | | minWidth: 130 |
| | | }, |
| | | { |
| | | label: "æææ¥æ", |
| | | prop: "valid", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "æ£å®å¨æ(天)", |
| | | prop: "cycle", |
| | | width: 130, |
| | | align:"center" |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | prop: "status", |
| | | width: 130, |
| | | align: "center", |
| | | formatData: (params) => { |
| | | if (params === 1) { |
| | | return "ææ"; |
| | | } else if (params === 2) { |
| | | return "龿"; |
| | | } else { |
| | | return null; |
| | | } |
| | | } else { |
| | | console.log("row missing valid or mostDate:", row.valid, row.mostDate); |
| | | } |
| | | return ""; |
| | | }; |
| | | }, |
| | | { |
| | | dataType: "action", |
| | | label: "æä½", |
| | | align: "center", |
| | | width: '130', |
| | | fixed: 'right', |
| | | operation: [ |
| | | { |
| | | name: "éä»¶", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openFilesFormDia(row); |
| | | }, |
| | | }, |
| | | { |
| | | name: "æ¥ç", |
| | | type: "text", |
| | | clickFun: (row) => { |
| | | openCalibrationDia("verifying", row); |
| | | }, |
| | | }, |
| | | ], |
| | | }, |
| | | ]); |
| | | const tableData = ref([]); |
| | | const tableLoading = ref(false); |
| | | const rowClickData = ref([]) |
| | | const filesDia = ref() |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, |
| | | total: 0, |
| | | }); |
| | | const selectedRows = ref([]); |
| | | |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = selection => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref(); |
| | | const calibrationDia = ref(); |
| | | // æå¼éä»¶å¼¹æ¡ |
| | | const openFilesFormDia = (row) => { |
| | | filesDia.value?.openDialog(row,'计éå¨å
·å°è´¦') |
| | | }; |
| | | |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const dbRowClick = (row)=>{ |
| | | rowClickData.value?.openDialog(row) |
| | | } |
| | | |
| | | // éç½®æç´¢æ¡ä»¶ |
| | | const handleReset = () => { |
| | | searchForm.value.recordDate = ""; |
| | | searchForm.value.code = ""; |
| | | searchForm.value.status = ""; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = obj => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentListPage({ ...searchForm.value, ...page }) |
| | | .then(res => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }) |
| | | .catch(err => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }; |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | selectedRows.value = selection; |
| | | }; |
| | | const formDia = ref() |
| | | const calibrationDia = ref() |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æå¼æ£å®æ ¡åå¼¹æ¡ |
| | | const openCalibrationDia = (type, row) => { |
| | | nextTick(() => { |
| | | calibrationDia.value?.openDialog(type, row); |
| | | }); |
| | | }; |
| | | // æ¥è¯¢å表 |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map(item => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentDelete(ids) |
| | | .then(res => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download( |
| | | "/measuringInstrumentLedger/export", |
| | | {}, |
| | | "计éå¨å
·å°è´¦.xlsx" |
| | | ); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | // éç½®æç´¢æ¡ä»¶ |
| | | const handleReset = () => { |
| | | searchForm.value.recordDate = ""; |
| | | searchForm.value.code = ""; |
| | | searchForm.value.status = ""; |
| | | page.current = 1; |
| | | getList(); |
| | | }; |
| | | const pagination = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getList(); |
| | | }; |
| | | const getList = () => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentListPage({ ...searchForm.value, ...page }).then((res) => { |
| | | tableLoading.value = false; |
| | | tableData.value = res.data.records; |
| | | page.total = res.data.total; |
| | | }).catch((err) => { |
| | | tableLoading.value = false; |
| | | }) |
| | | }; |
| | | |
| | | // æå¼å¼¹æ¡ |
| | | const openForm = (type, row) => { |
| | | nextTick(() => { |
| | | formDia.value?.openDialog(type, row) |
| | | }) |
| | | }; |
| | | // æå¼æ£å®æ ¡åå¼¹æ¡ |
| | | const openCalibrationDia = (type, row) => { |
| | | nextTick(() => { |
| | | calibrationDia.value?.openDialog(type, row) |
| | | }) |
| | | } |
| | | |
| | | const handleDelete = () => { |
| | | let ids = []; |
| | | if (selectedRows.value.length > 0) { |
| | | ids = selectedRows.value.map((item) => item.id); |
| | | } else { |
| | | proxy.$modal.msgWarning("è¯·éæ©æ°æ®"); |
| | | return; |
| | | } |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å é¤ï¼æ¯å¦ç¡®è®¤å é¤ï¼", "å é¤æç¤º", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | tableLoading.value = true; |
| | | measuringInstrumentDelete(ids) |
| | | .then((res) => { |
| | | proxy.$modal.msgSuccess("å 餿å"); |
| | | getList(); |
| | | }) |
| | | .finally(() => { |
| | | tableLoading.value = false; |
| | | }); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/measuringInstrumentLedger/export", {}, "计éå¨å
·å°è´¦.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | proxy.$modal.msg("已忶"); |
| | | }); |
| | | }; |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | :deep(.el-table .warning-row) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | :deep(.el-table .warning-row:hover > td) { |
| | | background-color: #f9d5d5 !important; |
| | | } |
| | | :deep(.el-table .el-table__body tr.warning-row td) { |
| | | background-color: #fef0f0 !important; |
| | | } |
| | | |
| | | </style> |
| | |
| | | align="center" |
| | | > |
| | | <template #default="scope"> |
| | | {{ getRuntimeDurationDisplay(scope.row) }} |
| | | {{ scope.row.runtimeDuration || '-' }} |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, onMounted, onUnmounted, computed } from 'vue' |
| | | import dayjs from 'dayjs' |
| | | import { ref, onMounted, computed } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { |
| | | VideoPlay, |
| | |
| | | |
| | | return filtered |
| | | }) |
| | | |
| | | // è¿è¡ä¸æ ç»ææ¶é´æ¶ï¼è¿è¡æ¶é¿ééå½åæ¶é´ååï¼ç¨ tick è§¦åæ¨¡æ¿éç® |
| | | const runtimeDisplayTick = ref(0) |
| | | |
| | | /** åå端å¯è½ä½¿ç¨çå¼å§/ç»ææ¶é´å段 */ |
| | | const pickStartTime = (row) => row?.startRuntimeTime ?? row?.startTime ?? row?.start_time |
| | | const pickEndTime = (row) => row?.endRuntimeTime ?? row?.endTime ?? row?.end_time |
| | | |
| | | /** |
| | | * è§£ææ¥å£/å端åå
¥çåç±»æ¶é´ï¼æ¶é´æ³ãISO å符串ãyyyy-MM-dd HH:mm:ssãJackson æ°ç» [y,M,d,h,m,s]ãå«ä¸æç toLocaleString ç |
| | | */ |
| | | const parseDeviceTime = (input) => { |
| | | if (input === null || input === undefined || input === '') return null |
| | | if (typeof input === 'number' && !Number.isNaN(input)) { |
| | | const d = dayjs(input) |
| | | return d.isValid() ? d.toDate() : null |
| | | } |
| | | if (Array.isArray(input)) { |
| | | const [y, mo, day, h = 0, mi = 0, se = 0] = input |
| | | if (y == null || y === '') return null |
| | | const d = dayjs() |
| | | .year(Number(y)) |
| | | .month(Number(mo || 1) - 1) |
| | | .date(Number(day || 1)) |
| | | .hour(Number(h) || 0) |
| | | .minute(Number(mi) || 0) |
| | | .second(Number(se) || 0) |
| | | return d.isValid() ? d.toDate() : null |
| | | } |
| | | const s = String(input).trim() |
| | | if (!s || s === '-') return null |
| | | let d = dayjs(s) |
| | | if (d.isValid()) return d.toDate() |
| | | d = dayjs(s.replace(/-/g, '/')) |
| | | if (d.isValid()) return d.toDate() |
| | | d = dayjs(s.replace(/\//g, '-')) |
| | | if (d.isValid()) return d.toDate() |
| | | return null |
| | | } |
| | | |
| | | const formatDurationMs = (durationMs) => { |
| | | if (durationMs == null || Number.isNaN(durationMs) || durationMs < 0) return '-' |
| | | const hours = Math.floor(durationMs / (1000 * 60 * 60)) |
| | | const minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60)) |
| | | if (hours === 0 && minutes === 0) return 'ä¸è¶³1åé' |
| | | return `${hours}å°æ¶${minutes}åé` |
| | | } |
| | | |
| | | const hasMeaningfulEnd = (endRaw) => |
| | | endRaw !== null && |
| | | endRaw !== undefined && |
| | | String(endRaw).trim() !== '' && |
| | | String(endRaw).trim() !== '-' |
| | | |
| | | const formatStoredDuration = (row) => { |
| | | const rd = row?.runtimeDuration |
| | | if (rd === null || rd === undefined) return '' |
| | | const t = String(rd).trim() |
| | | return t === '' || t === '-' ? '' : String(rd) |
| | | } |
| | | |
| | | /** è¿è¡ä¸ï¼å§ç»ç¨ãå½åæ¶é´ - å¼å§æ¶é´ãï¼å·²åæ¢ï¼ä¼å
æ¥å£ runtimeDurationï¼å¦åç¨ç»æ-å¼å§ï¼æ ç»æå¯çå·²åæ¶é¿æå¨ææ¨ç® */ |
| | | const getRuntimeDurationDisplay = (row) => { |
| | | void runtimeDisplayTick.value |
| | | const start = parseDeviceTime(pickStartTime(row)) |
| | | if (!start) { |
| | | return formatStoredDuration(row) || '-' |
| | | } |
| | | |
| | | const statusStr = String(row?.status ?? '').trim() |
| | | const isRunning = statusStr === 'è¿è¡ä¸' || statusStr === '1' |
| | | const endRaw = pickEndTime(row) |
| | | const hasEnd = hasMeaningfulEnd(endRaw) |
| | | |
| | | // æ ç»ææ¶é´ï¼è¿è¡ä¸ä¸å®å¨æç®ï¼å·²åæ¢åä¼å
å±ç¤ºåç«¯å·²åæ¶é¿ï¼æ²¡æåæå½åæ¶é´æ¨ç® |
| | | if (!hasEnd) { |
| | | if (isRunning) return formatDurationMs(Date.now() - start.getTime()) |
| | | const stored = formatStoredDuration(row) |
| | | if (stored) return stored |
| | | return formatDurationMs(Date.now() - start.getTime()) |
| | | } |
| | | |
| | | if (isRunning) { |
| | | return formatDurationMs(Date.now() - start.getTime()) |
| | | } |
| | | |
| | | const end = parseDeviceTime(endRaw) |
| | | const stored = formatStoredDuration(row) |
| | | if (stored) return stored |
| | | if (end) return formatDurationMs(end.getTime() - start.getTime()) |
| | | return '-' |
| | | } |
| | | |
| | | // æ£æ¥è®¾å¤æ¯å¦è¶
æ¶æªå¯å¨ |
| | | const isOverdue = (device) => { |
| | |
| | | device.endRuntimeTime = currentTime |
| | | // 计ç®è¿è¡æ¶é¿ |
| | | if (device.startRuntimeTime) { |
| | | const startTime = parseDeviceTime(device.startRuntimeTime) |
| | | const endTime = parseDeviceTime(currentTime) |
| | | if (startTime && endTime) { |
| | | device.runtimeDuration = formatDurationMs(endTime.getTime() - startTime.getTime()) |
| | | } |
| | | const startTime = new Date(device.startRuntimeTime) |
| | | const endTime = new Date(currentTime) |
| | | const duration = endTime - startTime |
| | | const hours = Math.floor(duration / (1000 * 60 * 60)) |
| | | const minutes = Math.floor((duration % (1000 * 60 * 60)) / (1000 * 60)) |
| | | device.runtimeDuration = `${hours}å°æ¶${minutes}åé` |
| | | } |
| | | } |
| | | const params = { |
| | |
| | | |
| | | |
| | | |
| | | const POLL_MS = 60 * 1000 |
| | | const RUNTIME_TICK_MS = 30 * 1000 |
| | | let listPollTimer = null |
| | | let runtimeTickTimer = null |
| | | |
| | | // ç»ä»¶æè½½æ¶æåæ°æ®ï¼å¹¶æ¯åéå·æ°ä¸æ¬¡å表ï¼è¿è¡ä¸æ¶é¿æ¯ 30 ç§å·æ°æ¾ç¤º |
| | | // ç»ä»¶æè½½æ¶åå§åæ°æ® |
| | | onMounted(() => { |
| | | getList() |
| | | listPollTimer = setInterval(() => { |
| | | getList() |
| | | }, POLL_MS) |
| | | runtimeTickTimer = setInterval(() => { |
| | | runtimeDisplayTick.value++ |
| | | }, RUNTIME_TICK_MS) |
| | | }) |
| | | |
| | | onUnmounted(() => { |
| | | if (listPollTimer != null) { |
| | | clearInterval(listPollTimer) |
| | | listPollTimer = null |
| | | } |
| | | if (runtimeTickTimer != null) { |
| | | clearInterval(runtimeTickTimer) |
| | | runtimeTickTimer = null |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | |
| | | <template> |
| | | <FormDialog v-model="visible" |
| | | :title="computedTitle" |
| | | :operation-type="operationType" |
| | | width="800px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose"> |
| | | <el-form :model="form" |
| | | label-width="100px"> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="id ? 'ç¼è¾è®¾å¤æ¥ä¿®' : 'æ°å¢è®¾å¤æ¥ä¿®'" |
| | | width="800px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æå±åºå"> |
| | | <el-tree-select |
| | | v-model="form.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="è¯·éæ©æå±åºå" |
| | | style="width: 100%" |
| | | @change="handleAreaChange" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-select v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | filterable |
| | | :disabled="operationType === 'view'"> |
| | | <el-option v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | :label="item.deviceName" |
| | | :value="item.id"></el-option> |
| | | <el-select |
| | | v-model="form.deviceLedgerIds" |
| | | filterable |
| | | clearable |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | placeholder="请å
éæ©åºåï¼åéæ©è®¾å¤" |
| | | style="width: 100%" |
| | | @change="setDeviceModels" |
| | | > |
| | | <el-option |
| | | v-for="item in deviceOptions" |
| | | :key="item.id" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | disabled /> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="èªå¨å¸¦åºè§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®æ¥æ"> |
| | | <el-date-picker v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | clearable |
| | | style="width: 100%" |
| | | :disabled="operationType === 'view'" /> |
| | | <el-date-picker |
| | | v-model="form.repairTime" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | type="date" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®äºº"> |
| | | <el-input v-model="form.repairName" |
| | | placeholder="请è¾å
¥æ¥ä¿®äºº" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®æ¥ä¿®é¡¹ç®"> |
| | | <el-input v-model="form.machineryCategory" |
| | | placeholder="请è¾å
¥æ¥ä¿®æ¥ä¿®é¡¹ç®" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="12"> |
| | | <el-form-item label="维修人"> |
| | | <el-input v-model="form.maintenanceName" |
| | | placeholder="请è¾å
¥ç»´ä¿®äººå§å" |
| | | :disabled="operationType === 'view'" /> |
| | | <el-input v-model="form.repairName" placeholder="请è¾å
¥æ¥ä¿®äºº" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="id"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="æ¥ä¿®ç¶æ"> |
| | | <el-select v-model="form.status" |
| | | disabled> |
| | | <el-option label="å¾
ç»´ä¿®" |
| | | :value="0"></el-option> |
| | | <el-option label="å·²éªæ¶" |
| | | :value="1"></el-option> |
| | | <el-option label="失败" |
| | | :value="2"></el-option> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ç»´ä¿®" :value="0" /> |
| | | <el-option label="å®ç»" :value="1" /> |
| | | <el-option label="失败" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <!-- éªæ¶ä¿¡æ¯å±ç¤º --> |
| | | <el-row v-if="id && (form.status === 1 || form.status === 3)"> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éªæ¶äºº"> |
| | | <el-input v-model="form.acceptanceName" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="12"> |
| | | <el-form-item label="éªæ¶æ¶é´"> |
| | | <el-input v-model="form.acceptanceTime" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éªæ¶å¤æ³¨"> |
| | | <el-input v-model="form.acceptanceRemark" |
| | | type="textarea" |
| | | :rows="2" |
| | | disabled /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="æ
éç°è±¡"> |
| | | <el-input v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | :disabled="operationType === 'view'" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row v-if="operationType !== 'view'" |
| | | :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éä»¶" |
| | | prop="attachmentIds"> |
| | | <FileUpload v-model:file-list="form.storageBlobDTOs" |
| | | :disabled="operationType === 'view'" /> |
| | | <el-input |
| | | v-model="form.remark" |
| | | :rows="2" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import { ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { nextTick, ref, unref } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { |
| | | addRepair, |
| | | editRepair, |
| | | getRepairById, |
| | | } from "@/api/equipmentManagement/repair"; |
| | | import { |
| | | getDeviceAreaTree, |
| | | getDeviceAreaTreeWithDevices, |
| | | } from "@/api/equipmentManagement/deviceArea"; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®å¼¹çª", |
| | | }); |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®å¼¹çª", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const operationType = ref(""); // add, edit, view |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const userStore = useUserStore(); |
| | | const areaOptions = ref([]); |
| | | const deviceOptions = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | |
| | | const computedTitle = computed(() => { |
| | | if (operationType.value === "add") return "æ°å¢è®¾å¤æ¥ä¿®"; |
| | | if (operationType.value === "edit") return "ç¼è¾è®¾å¤æ¥ä¿®"; |
| | | if (operationType.value === "view") return "è®¾å¤æ¥ä¿®è¯¦æ
"; |
| | | return ""; |
| | | }); |
| | | const { form, resetForm } = useFormData({ |
| | | areaId: undefined, |
| | | deviceLedgerId: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | repairTime: dayjs().format("YYYY-MM-DD"), |
| | | repairName: userStore.nickName, |
| | | remark: undefined, |
| | | status: 0, |
| | | }); |
| | | |
| | | const userStore = useUserStore(); |
| | | const deviceOptions = ref([]); |
| | | const fileList = ref([]); |
| | | const loadAreaTree = async () => { |
| | | const { data } = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(data) ? data : []; |
| | | }; |
| | | |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | }; |
| | | const normalizeIdList = (value) => { |
| | | if (Array.isArray(value)) { |
| | | return value |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (typeof value === "string") { |
| | | return value |
| | | .split(",") |
| | | .map((item) => Number(item.trim())) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (value !== undefined && value !== null && value !== "") { |
| | | const numericValue = Number(value); |
| | | return Number.isFinite(numericValue) ? [numericValue] : []; |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | repairTime: dayjs().format("YYYY-MM-DD"), // æ¥ä¿®æ¥æï¼é»è®¤å½å¤© |
| | | repairName: userStore.nickName, // æ¥ä¿®äºº |
| | | remark: undefined, // æ
éç°è±¡ |
| | | status: 0, // æ¥ä¿®ç¶æ |
| | | machineryCategory: undefined, |
| | | storageBlobDTOs: [], |
| | | maintenanceName: undefined, // 维修人 |
| | | }); |
| | | const getNodeDevices = (node) => { |
| | | const candidates = [ |
| | | node?.deviceList, |
| | | node?.devices, |
| | | node?.deviceLedgerList, |
| | | node?.deviceLedgers, |
| | | node?.ledgerList, |
| | | node?.ledgers, |
| | | ]; |
| | | return candidates.find((item) => Array.isArray(item)) || []; |
| | | }; |
| | | |
| | | const setDeviceModel = deviceId => { |
| | | const option = deviceOptions.value.find(item => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | }; |
| | | const normalizeDevice = (item) => ({ |
| | | ...item, |
| | | id: item.id ?? item.deviceLedgerId, |
| | | deviceName: item.deviceName ?? item.name, |
| | | deviceModel: item.deviceModel ?? item.model, |
| | | }); |
| | | |
| | | const setForm = data => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | form.machineryCategory = data.machineryCategory; |
| | | form.storageBlobDTOs = data.storageBlobVOs || []; |
| | | form.maintenanceName = data.maintenanceName; |
| | | form.acceptanceName = data.acceptanceName; |
| | | form.acceptanceTime = data.acceptanceTime; |
| | | form.acceptanceRemark = data.acceptanceRemark; |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...form }) |
| | | : await addRepair(form); |
| | | if (code == 200) { |
| | | ElMessage.success(`${id.value ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | const collectDevices = (node) => { |
| | | const currentDevices = getNodeDevices(node).map(normalizeDevice); |
| | | const childDevices = (node?.children || []).flatMap((child) => |
| | | collectDevices(child) |
| | | ); |
| | | const deviceMap = new Map(); |
| | | [...currentDevices, ...childDevices].forEach((item) => { |
| | | if (item?.id !== undefined && item?.id !== null) { |
| | | deviceMap.set(Number(item.id), item); |
| | | } |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openAdd = async () => { |
| | | id.value = undefined; |
| | | operationType.value = "add"; |
| | | visible.value = true; |
| | | fileList.value = []; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | }; |
| | | |
| | | const openEdit = async editId => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | operationType.value = "edit"; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | const openView = async viewId => { |
| | | const { data } = await getRepairById(viewId); |
| | | id.value = viewId; |
| | | operationType.value = "view"; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadDeviceName(); |
| | | setForm(data); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openAdd, |
| | | openEdit, |
| | | openView, |
| | | }); |
| | | return Array.from(deviceMap.values()); |
| | | }; |
| | | |
| | | const findAreaNode = (nodes, areaId) => { |
| | | for (const node of nodes || []) { |
| | | if (Number(node.id) === Number(areaId)) { |
| | | return node; |
| | | } |
| | | const target = findAreaNode(node.children, areaId); |
| | | if (target) { |
| | | return target; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const loadDevicesByArea = async (areaId) => { |
| | | if (!areaId) { |
| | | deviceOptions.value = []; |
| | | return; |
| | | } |
| | | const { data } = await getDeviceAreaTreeWithDevices(); |
| | | const treeData = Array.isArray(data) ? data : []; |
| | | const currentNode = findAreaNode(treeData, areaId); |
| | | deviceOptions.value = currentNode ? collectDevices(currentNode) : []; |
| | | }; |
| | | |
| | | const syncDeviceFields = (deviceIds) => { |
| | | const selectedIds = normalizeIdList(deviceIds); |
| | | const selectedDevices = selectedIds |
| | | .map((deviceId) => |
| | | deviceOptions.value.find((item) => Number(item.id) === Number(deviceId)) |
| | | ) |
| | | .filter(Boolean); |
| | | |
| | | form.deviceLedgerIds = selectedIds; |
| | | form.deviceLedgerId = selectedIds[0]; |
| | | form.deviceLedgerIdsStr = selectedIds.join(","); |
| | | form.deviceName = selectedDevices |
| | | .map((item) => item.deviceName) |
| | | .filter(Boolean) |
| | | .join(","); |
| | | form.deviceModel = selectedDevices |
| | | .map((item) => item.deviceModel || "-") |
| | | .join(","); |
| | | }; |
| | | |
| | | const setDeviceModels = (deviceIds) => { |
| | | syncDeviceFields(deviceIds); |
| | | }; |
| | | |
| | | const setForm = (data) => { |
| | | form.areaId = data.areaId; |
| | | form.deviceLedgerIds = normalizeIdList( |
| | | data.deviceLedgerIds ?? data.deviceLedgerIdsStr ?? data.deviceLedgerId |
| | | ); |
| | | form.deviceLedgerId = form.deviceLedgerIds[0]; |
| | | form.deviceLedgerIdsStr = |
| | | data.deviceLedgerIdsStr ?? form.deviceLedgerIds.join(","); |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.repairTime = data.repairTime; |
| | | form.repairName = data.repairName; |
| | | form.remark = data.remark; |
| | | form.status = data.status; |
| | | }; |
| | | |
| | | const handleAreaChange = async (areaId) => { |
| | | form.deviceLedgerId = undefined; |
| | | form.deviceLedgerIds = []; |
| | | form.deviceLedgerIdsStr = undefined; |
| | | form.deviceName = undefined; |
| | | form.deviceModel = undefined; |
| | | await loadDevicesByArea(areaId); |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | syncDeviceFields(form.deviceLedgerIds); |
| | | const payload = { |
| | | ...form, |
| | | deviceLedgerId: form.deviceLedgerIds[0], |
| | | deviceLedgerIds: [...form.deviceLedgerIds], |
| | | deviceLedgerIdsStr: form.deviceLedgerIds.join(","), |
| | | deviceModel: form.deviceModel || "-", |
| | | }; |
| | | const { code } = id.value |
| | | ? await editRepair({ id: unref(id), ...payload }) |
| | | : await addRepair(payload); |
| | | if (code === 200) { |
| | | ElMessage.success(`${id.value ? "ç¼è¾" : "æ°å¢"}æ¥ä¿®æå`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openAdd = async () => { |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadAreaTree(); |
| | | deviceOptions.value = []; |
| | | }; |
| | | |
| | | const openEdit = async (editId) => { |
| | | const { data } = await getRepairById(editId); |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadAreaTree(); |
| | | setForm(data); |
| | | await loadDevicesByArea(form.areaId); |
| | | syncDeviceFields(form.deviceLedgerIds); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | openAdd, |
| | | openEdit, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-form :model="filters" |
| | | :inline="true"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-input v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input v-model="filters.deviceModel" |
| | | style="width: 240px" |
| | | placeholder="è¯·éæ©è§æ ¼åå·" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.deviceModel" |
| | | style="width: 240px" |
| | | placeholder="è¯·éæ©è§æ ¼åå·" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ
éç°è±¡"> |
| | | <el-input v-model="filters.remark" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.remark" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥æ
éç°è±¡" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="维修人"> |
| | | <el-input v-model="filters.maintenanceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.maintenanceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ç»´ä¿®äºº" |
| | | clearable |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="æ¥ä¿®æ¥æ"> |
| | | <el-date-picker v-model="filters.repairTimeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" /> |
| | | <el-date-picker |
| | | v-model="filters.repairTimeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©æ¥ä¿®æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ç»´ä¿®æ¥æ"> |
| | | <el-date-picker v-model="filters.maintenanceTimeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" /> |
| | | <el-date-picker |
| | | v-model="filters.maintenanceTimeStr" |
| | | type="date" |
| | | placeholder="è¯·éæ©ç»´ä¿®æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="getTableData">æç´¢</el-button> |
| | | <el-button type="primary" @click="getTableData">æç´¢</el-button> |
| | | <el-button @click="resetFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <el-text class="mx-1" |
| | | size="large">è®¾å¤æ¥ä¿®</el-text> |
| | | <el-text class="mx-1" size="large">è®¾å¤æ¥ä¿®</el-text> |
| | | <div> |
| | | <el-button type="success" |
| | | icon="Van" |
| | | @click="addRepair"> |
| | | <el-button type="success" icon="Van" @click="addRepair"> |
| | | æ°å¢æ¥ä¿® |
| | | </el-button> |
| | | <el-button @click="handleOut"> |
| | | å¯¼åº |
| | | </el-button> |
| | | <el-button type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))"> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage"> |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | > |
| | | <template #statusRef="{ row }"> |
| | | <el-tag v-if="row.status === 2" |
| | | type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" |
| | | type="success">å®ç»</el-tag> |
| | | <el-tag v-if="row.status === 3" |
| | | type="info">å¾
éªæ¶</el-tag> |
| | | <el-tag v-if="row.status === 0" |
| | | type="warning">å¾
ç»´ä¿®</el-tag> |
| | | <el-tag v-if="row.status === 2" type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" type="success">å®ç»</el-tag> |
| | | <el-tag v-if="row.status === 0" type="warning">å¾
ç»´ä¿®</el-tag> |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" |
| | | link |
| | | @click="viewRepair(row.id)"> |
| | | 详æ
|
| | | </el-button> |
| | | <el-button type="primary" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="editRepair(row.id)"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editRepair(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button type="success" |
| | | link |
| | | :disabled="row.status !== 0" |
| | | @click="addMaintain(row)"> |
| | | <el-button |
| | | type="success" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="addMaintain(row)" |
| | | > |
| | | ç»´ä¿® |
| | | </el-button> |
| | | <el-button type="warning" |
| | | link |
| | | :disabled="row.status !== 3" |
| | | @click="openAcceptance(row)"> |
| | | éªæ¶ |
| | | </el-button> |
| | | <el-button type="danger" |
| | | link |
| | | :disabled="row.status === 1 || row.status === 3" |
| | | @click="delRepairByIds(row.id)"> |
| | | <el-button |
| | | type="danger" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="openFileDialog(row)"> |
| | | éä»¶ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | <RepairModal ref="repairModalRef" |
| | | @ok="getTableData" /> |
| | | <MaintainModal ref="maintainModalRef" |
| | | @ok="getTableData" /> |
| | | <AcceptanceModal ref="acceptanceModalRef" |
| | | @ok="getTableData" /> |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | :record-type="'device_repair'" |
| | | :record-id="recordId" /> |
| | | <RepairModal ref="repairModalRef" @ok="getTableData"/> |
| | | <MaintainModal ref="maintainModalRef" @ok="getTableData"/> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | onMounted, |
| | | getCurrentInstance, |
| | | computed, |
| | | ref, |
| | | defineAsyncComponent, |
| | | } from "vue"; |
| | | import { usePaginationApi } from "@/hooks/usePaginationApi"; |
| | | import { getRepairPage, delRepair } from "@/api/equipmentManagement/repair"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import { ElMessageBox, ElMessage } from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import MaintainModal from "./Modal/MaintainModal.vue"; |
| | | import AcceptanceModal from "./Modal/AcceptanceModal.vue"; |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | import { onMounted, getCurrentInstance, computed } from "vue"; |
| | | import {usePaginationApi} from "@/hooks/usePaginationApi"; |
| | | import {getRepairPage, delRepair} from "@/api/equipmentManagement/repair"; |
| | | import RepairModal from "./Modal/RepairModal.vue"; |
| | | import {ElMessageBox, ElMessage} from "element-plus"; |
| | | import dayjs from "dayjs"; |
| | | import MaintainModal from "./Modal/MaintainModal.vue"; |
| | | |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®", |
| | | }); |
| | | defineOptions({ |
| | | name: "è®¾å¤æ¥ä¿®", |
| | | }); |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const {proxy} = getCurrentInstance(); |
| | | |
| | | // æ¨¡ææ¡å®ä¾ |
| | | const repairModalRef = ref(); |
| | | const maintainModalRef = ref(); |
| | | const acceptanceModalRef = ref(); |
| | | // æ¨¡ææ¡å®ä¾ |
| | | const repairModalRef = ref(); |
| | | const maintainModalRef = ref(); |
| | | |
| | | // è¡¨æ ¼å¤éæ¡éä¸é¡¹ |
| | | const multipleList = ref([]); |
| | | // è¡¨æ ¼å¤éæ¡éä¸é¡¹ |
| | | const multipleList = ref([]); |
| | | |
| | | // è¡¨æ ¼é©å |
| | | const { |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | // è¡¨æ ¼é©å |
| | | const { |
| | | filters, |
| | | columns, |
| | | dataList, |
| | | pagination, |
| | | getTableData, |
| | | resetFilters, |
| | | onCurrentChange, |
| | | } = usePaginationApi( |
| | | getRepairPage, |
| | | { |
| | | deviceName: undefined, |
| | |
| | | maintenanceTimeStr: undefined, |
| | | }, |
| | | [ |
| | | { |
| | | label: "æå¨åºå", |
| | | prop: "areaName", |
| | | }, |
| | | { |
| | | label: "设å¤åç§°", |
| | | align: "center", |
| | |
| | | label: "æ¥ä¿®æ¥æ", |
| | | align: "center", |
| | | prop: "repairTime", |
| | | formatData: cell => dayjs(cell).format("YYYY-MM-DD"), |
| | | formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"), |
| | | }, |
| | | { |
| | | label: "æ¥ä¿®äºº", |
| | | align: "center", |
| | | prop: "repairName", |
| | | }, |
| | | { |
| | | label: "æ
éç°è±¡", |
| | | align: "center", |
| | | prop: "remark", |
| | | }, |
| | | { |
| | | label: "维修人", |
| | | align: "center", |
| | | prop: "maintenanceName", |
| | | }, |
| | | { |
| | | label: "ç»´ä¿®ç»æ", |
| | | align: "center", |
| | | prop: "maintenanceResult", |
| | | }, |
| | | { |
| | | label: "ç»´ä¿®æ¥æ", |
| | | align: "center", |
| | | prop: "maintenanceTime", |
| | | formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""), |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "320px", |
| | | width: "300px", |
| | | }, |
| | | ] |
| | | ); |
| | | ); |
| | | |
| | | // type === 1 ç»´ä¿® 2æ¥ä¿®é´ |
| | | const handleDateChange = (value, type) => { |
| | | filters.maintenanceTimeStr = null; |
| | | filters.c = null; |
| | | if (type === 1) { |
| | | if (value) { |
| | | filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } else { |
| | | if (value) { |
| | | filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | // type === 1 ç»´ä¿® 2æ¥ä¿®é´ |
| | | const handleDateChange = (value, type) => { |
| | | filters.maintenanceTimeStr = null |
| | | filters.c = null |
| | | if (type === 1) { |
| | | if (value) { |
| | | filters.maintenanceTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | getTableData(); |
| | | }; |
| | | } else { |
| | | if (value) { |
| | | filters.repairTimeStr = dayjs(value).format("YYYY-MM-DD"); |
| | | } |
| | | } |
| | | getTableData(); |
| | | }; |
| | | |
| | | // æå¼éä»¶å¼¹çª |
| | | const recordId = ref(0); |
| | | const fileDialogVisible = ref(false); |
| | | // å¤éååä»ä¹ |
| | | const handleSelectionChange = (selectionList) => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | | |
| | | const openFileDialog = async row => { |
| | | recordId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }; |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | // å¤éååä»ä¹ |
| | | const handleSelectionChange = selectionList => { |
| | | multipleList.value = selectionList; |
| | | }; |
| | | // æ°å¢æ¥ä¿® |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | | }; |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1); |
| | | // ç¼è¾æ¥ä¿® |
| | | const editRepair = (id) => { |
| | | repairModalRef.value.openEdit(id); |
| | | }; |
| | | |
| | | // æ°å¢ç»´ä¿® |
| | | const addMaintain = (row) => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | | const changePage = ({page, limit}) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | // åè¡å é¤ |
| | | const delRepairByIds = async (ids) => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const idsArray = Array.isArray(ids) ? ids : [ids]; |
| | | const hasFinished = idsArray.some(id => { |
| | | const record = dataList.value.find(item => item.id === id); |
| | | return record && record.status === 1; |
| | | }); |
| | | |
| | | // æ°å¢æ¥ä¿® |
| | | const addRepair = () => { |
| | | repairModalRef.value.openAdd(); |
| | | }; |
| | | if (hasFinished) { |
| | | ElMessage.warning('ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½'); |
| | | return; |
| | | } |
| | | |
| | | // 详æ
æ¥ç |
| | | const viewRepair = id => { |
| | | repairModalRef.value.openView(id); |
| | | }; |
| | | |
| | | // ç¼è¾æ¥ä¿® |
| | | const editRepair = id => { |
| | | repairModalRef.value.openEdit(id); |
| | | }; |
| | | |
| | | // æ°å¢ç»´ä¿® |
| | | const addMaintain = row => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | | // æå¼éªæ¶å¼¹çª |
| | | const openAcceptance = row => { |
| | | acceptanceModalRef.value.open(row); |
| | | }; |
| | | |
| | | const changePage = ({ page, limit }) => { |
| | | pagination.currentPage = page; |
| | | pagination.pageSize = limit; |
| | | onCurrentChange(page); |
| | | }; |
| | | |
| | | // åè¡å é¤ |
| | | const delRepairByIds = async ids => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const idsArray = Array.isArray(ids) ? ids : [ids]; |
| | | const hasFinished = idsArray.some(id => { |
| | | const record = dataList.value.find(item => item.id === id); |
| | | return record && record.status === 1; |
| | | }); |
| | | |
| | | if (hasFinished) { |
| | | ElMessage.warning("ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½"); |
| | | return; |
| | | ElMessageBox.confirm("确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const {code} = await delRepair(ids); |
| | | if (code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | ElMessageBox.confirm("确认å 餿¥ä¿®æ°æ®, æ¤æä½ä¸å¯é?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }).then(async () => { |
| | | const { code } = await delRepair(ids); |
| | | if (code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | getTableData(); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | // å¯¼åº |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/device/repair/export", {}, "è®¾å¤æ¥ä¿®.xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.info("已忶"); |
| | | }); |
| | | }; |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | onMounted(() => { |
| | | getTableData(); |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | |
| | | </el-form> |
| | | <template #footer> |
| | | <span class="dialog-footer"> |
| | | <el-button type="primary" @click="submitForm" :loading="formLoading">ç¡®å®</el-button> |
| | | <el-button @click="dialogVisible = false" :disabled="formLoading">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitForm" :loading="formLoading">ç¡®å®</el-button> |
| | | </span> |
| | | </template> |
| | | </el-dialog> |
| | |
| | | <template> |
| | | <FormDialog v-model="visible" |
| | | :title="'设å¤ä¿å
»'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose"> |
| | | <el-form :model="form" |
| | | label-width="100px"> |
| | | <FormDialog |
| | | v-model="visible" |
| | | :title="'设å¤ä¿å
»'" |
| | | width="500px" |
| | | @confirm="sendForm" |
| | | @cancel="handleCancel" |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-form-item label="å®é
ä¿å
»äºº"> |
| | | <el-input v-model="form.maintenanceActuallyName" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº"></el-input> |
| | | <el-input |
| | | v-model="form.maintenanceActuallyName" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº" |
| | | ></el-input> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
ä¿å
»æ¥æ"> |
| | | <el-date-picker v-model="form.maintenanceActuallyTime" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | clearable |
| | | style="width: 100%" /> |
| | | <el-date-picker |
| | | v-model="form.maintenanceActuallyTime" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | format="YYYY-MM-DD HH:mm:ss" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="datetime" |
| | | clearable |
| | | style="width: 100%" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
»ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ä¿å
»" |
| | | :value="0"></el-option> |
| | | <el-option label="å®ç»" |
| | | :value="1"></el-option> |
| | | <el-option label="失败" |
| | | :value="2"></el-option> |
| | | <el-option label="å¾
ä¿å
»" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
ȍȾ"> |
| | | <el-input v-model="form.maintenanceResult" |
| | | placeholder="请è¾å
¥ä¿å
ȍȾ" |
| | | type="text" /> |
| | | <el-input |
| | | v-model="form.maintenanceResult" |
| | | placeholder="请è¾å
¥ä¿å
ȍȾ" |
| | | type="text" /> |
| | | </el-form-item> |
| | | <el-form-item label="设å¤å¤ä»¶"> |
| | | <el-select v-model="form.sparePartsIds" |
| | | :loading="loadingSparePartOptions" |
| | | placeholder="è¯·éæ©è®¾å¤å¤ä»¶" |
| | | multiple |
| | | filterable> |
| | | <el-option v-for="item in sparePartOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" /> |
| | | <el-select v-model="form.sparePartsIds" :loading="loadingSparePartOptions" placeholder="è¯·éæ©è®¾å¤å¤ä»¶" multiple filterable> |
| | | <el-option |
| | | v-for="item in sparePartOptions" |
| | | :key="item.id" |
| | | :label="item.name" |
| | | :value="item.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item v-if="selectedSpareParts.length" |
| | | label="é¢ç¨æ°é"> |
| | | |
| | | <el-form-item v-if="selectedSpareParts.length" label="é¢ç¨æ°é"> |
| | | <div style="width: 100%"> |
| | | <div v-for="item in selectedSpareParts" |
| | | :key="item.id" |
| | | style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;"> |
| | | <div |
| | | v-for="item in selectedSpareParts" |
| | | :key="item.id" |
| | | style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;" |
| | | > |
| | | <div style="flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> |
| | | {{ item.name }} |
| | | <span v-if="item.quantity !== null && item.quantity !== undefined" |
| | | style="color: #909399;"> |
| | | <span v-if="item.quantity !== null && item.quantity !== undefined" style="color: #909399;"> |
| | | ï¼åºåï¼{{ item.quantity }}ï¼ |
| | | </span> |
| | | </div> |
| | | <el-input-number v-model="sparePartQtyMap[item.id]" |
| | | :min="1" |
| | | :max="item.quantity !== null && item.quantity !== undefined ? Number(item.quantity) : undefined" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 180px" /> |
| | | <el-input-number |
| | | v-model="sparePartQtyMap[item.id]" |
| | | :min="1" |
| | | :max="item.quantity !== null && item.quantity !== undefined ? Number(item.quantity) : undefined" |
| | | :step="1" |
| | | controls-position="right" |
| | | style="width: 180px" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </el-form-item> |
| | | <el-form-item label="éä»¶"> |
| | | <FileUpload v-model:file-list="form.storageBlobDTOs" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { addMaintenance } from "@/api/equipmentManagement/upkeep"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { ElMessage } from "element-plus"; |
| | | import { computed, ref, nextTick, getCurrentInstance } from "vue"; |
| | | import { getSparePartsList } from "@/api/equipmentManagement/spareParts.js"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import { addMaintenance } from "@/api/equipmentManagement/upkeep"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import dayjs from "dayjs"; |
| | | import useUserStore from "@/store/modules/user"; |
| | | import { ElMessage } from "element-plus"; |
| | | import {computed, ref} from "vue"; |
| | | import {getSparePartsList} from "@/api/equipmentManagement/spareParts.js"; |
| | | |
| | | defineOptions({ |
| | | name: "ä¿å
»æ¨¡ææ¡", |
| | | }); |
| | | defineOptions({ |
| | | name: "ä¿å
»æ¨¡ææ¡", |
| | | }); |
| | | |
| | | const emits = defineEmits(["ok"]); |
| | | const emits = defineEmits(["ok"]); |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | // ä¿å计åä¿å
»è®°å½çid |
| | | const planId = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const userStore = useUserStore(); |
| | | // ä¿å计åä¿å
»è®°å½çid |
| | | const planId = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | const userStore = useUserStore(); |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | maintenanceActuallyName: undefined, // å®é
ä¿å
»äºº |
| | | maintenanceActuallyTime: undefined, // å®é
ä¿å
»æ¥æ |
| | | maintenanceResult: undefined, // ä¿å
ȍȾ |
| | | status: 0, // ä¿å
»ç¶æ |
| | | sparePartsIds: [], |
| | | storageBlobDTOs: [], |
| | | }); |
| | | const { form, resetForm } = useFormData({ |
| | | maintenanceActuallyName: undefined, // å®é
ä¿å
»äºº |
| | | maintenanceActuallyTime: undefined, // å®é
ä¿å
»æ¥æ |
| | | maintenanceResult: undefined, // ä¿å
ȍȾ |
| | | status: 0, // ä¿å
»ç¶æ |
| | | sparePartsIds: [], |
| | | }); |
| | | |
| | | const sparePartOptions = ref([]); |
| | | const loadingSparePartOptions = ref(true); |
| | | const sparePartQtyMap = ref({}); |
| | | const sparePartOptions = ref([]) |
| | | const loadingSparePartOptions = ref(true) |
| | | const sparePartQtyMap = ref({}) |
| | | |
| | | const selectedSpareParts = computed(() => { |
| | | const ids = Array.isArray(form.sparePartsIds) ? form.sparePartsIds : []; |
| | | const set = new Set(ids.map(i => String(i))); |
| | | return (sparePartOptions.value || []).filter(p => set.has(String(p.id))); |
| | | }); |
| | | const selectedSpareParts = computed(() => { |
| | | const ids = Array.isArray(form.sparePartsIds) ? form.sparePartsIds : []; |
| | | const set = new Set(ids.map((i) => String(i))); |
| | | return (sparePartOptions.value || []).filter((p) => set.has(String(p.id))); |
| | | }); |
| | | |
| | | const setForm = data => { |
| | | form.maintenanceActuallyName = |
| | | data.maintenanceActuallyName ?? userStore.nickName; |
| | | form.maintenanceActuallyTime = data.maintenanceActuallyTime |
| | | const setForm = (data) => { |
| | | form.maintenanceActuallyName = |
| | | data.maintenanceActuallyName ?? userStore.nickName; |
| | | form.maintenanceActuallyTime = |
| | | data.maintenanceActuallyTime |
| | | ? dayjs(data.maintenanceActuallyTime).format("YYYY-MM-DD HH:mm:ss") |
| | | : dayjs().format("YYYY-MM-DD HH:mm:ss"); |
| | | form.maintenanceResult = data.maintenanceResult; |
| | | form.status = 1; // é»è®¤ç¶æä¸ºå®ç» |
| | | // multiple éæ©å¨è¦æ±æ°ç»ï¼å端常è¿å "1,2,3" |
| | | if (Array.isArray(data?.sparePartsIds)) { |
| | | form.sparePartsIds = data.sparePartsIds |
| | | .map(v => Number(v)) |
| | | .filter(v => Number.isFinite(v)); |
| | | } else if (typeof data?.sparePartsIds === "string") { |
| | | form.sparePartsIds = data.sparePartsIds |
| | | form.maintenanceResult = data.maintenanceResult; |
| | | form.status = 1; // é»è®¤ç¶æä¸ºå®ç» |
| | | // multiple éæ©å¨è¦æ±æ°ç»ï¼å端常è¿å "1,2,3" |
| | | if (Array.isArray(data?.sparePartsIds)) { |
| | | form.sparePartsIds = data.sparePartsIds.map((v) => Number(v)).filter((v) => Number.isFinite(v)); |
| | | } else if (typeof data?.sparePartsIds === "string") { |
| | | form.sparePartsIds = data.sparePartsIds |
| | | .split(",") |
| | | .map(s => Number(String(s).trim())) |
| | | .filter(v => Number.isFinite(v)); |
| | | } else if (typeof data?.sparePartsIds === "number") { |
| | | form.sparePartsIds = [data.sparePartsIds]; |
| | | } else { |
| | | form.sparePartsIds = []; |
| | | } |
| | | form.storageBlobDTOs = data.storageBlobVOs || []; |
| | | }; |
| | | .map((s) => Number(String(s).trim())) |
| | | .filter((v) => Number.isFinite(v)); |
| | | } else if (typeof data?.sparePartsIds === "number") { |
| | | form.sparePartsIds = [data.sparePartsIds]; |
| | | } else { |
| | | form.sparePartsIds = []; |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * @desc ä¿åä¿å
» |
| | | */ |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | // é¢ç¨æ°éæ ¡éª |
| | | if (Array.isArray(form.sparePartsIds) && form.sparePartsIds.length > 0) { |
| | | for (const partId of form.sparePartsIds) { |
| | | const qty = Number(sparePartQtyMap.value?.[partId]); |
| | | if (!Number.isFinite(qty) || qty <= 0) { |
| | | proxy?.$modal?.msgError?.("请填åå¤ä»¶é¢ç¨æ°é"); |
| | | /** |
| | | * @desc ä¿åä¿å
» |
| | | */ |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | // é¢ç¨æ°éæ ¡éª |
| | | if (Array.isArray(form.sparePartsIds) && form.sparePartsIds.length > 0) { |
| | | for (const partId of form.sparePartsIds) { |
| | | const qty = Number(sparePartQtyMap.value?.[partId]); |
| | | if (!Number.isFinite(qty) || qty <= 0) { |
| | | proxy?.$modal?.msgError?.("请填åå¤ä»¶é¢ç¨æ°é"); |
| | | return; |
| | | } |
| | | const part = sparePartOptions.value.find((p) => String(p.id) === String(partId)); |
| | | const stock = part?.quantity; |
| | | if (stock !== null && stock !== undefined && Number.isFinite(Number(stock))) { |
| | | if (qty > Number(stock)) { |
| | | proxy?.$modal?.msgError?.(`å¤ä»¶ã${part?.name || ""}ãé¢ç¨æ°éä¸è½è¶
è¿åºåï¼${stock}ï¼`); |
| | | return; |
| | | } |
| | | const part = sparePartOptions.value.find( |
| | | p => String(p.id) === String(partId) |
| | | ); |
| | | const stock = part?.quantity; |
| | | if ( |
| | | stock !== null && |
| | | stock !== undefined && |
| | | Number.isFinite(Number(stock)) |
| | | ) { |
| | | if (qty > Number(stock)) { |
| | | proxy?.$modal?.msgError?.( |
| | | `å¤ä»¶ã${part?.name || ""}ãé¢ç¨æ°éä¸è½è¶
è¿åºåï¼${stock}ï¼` |
| | | ); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | const data = { |
| | | id: planId.value, |
| | | ...form, |
| | | sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "", |
| | | sparePartsQty: form.sparePartsIds |
| | | ? form.sparePartsIds |
| | | .map(id => sparePartQtyMap.value?.[id] ?? 1) |
| | | .join(",") |
| | | : "", |
| | | sparePartsUseList: form.sparePartsIds |
| | | ? form.sparePartsIds.map(id => ({ |
| | | id, |
| | | quantity: sparePartQtyMap.value?.[id] ?? 1, |
| | | })) |
| | | : [], |
| | | }; |
| | | const { code } = await addMaintenance(data); |
| | | if (code == 200) { |
| | | ElMessage.success("ä¿å
»æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | const data = { |
| | | id: planId.value, |
| | | ...form, |
| | | sparePartsIds: form.sparePartsIds ? form.sparePartsIds.join(",") : "", |
| | | sparePartsQty: form.sparePartsIds |
| | | ? form.sparePartsIds.map((id) => sparePartQtyMap.value?.[id] ?? 1).join(",") |
| | | : "", |
| | | sparePartsUseList: form.sparePartsIds |
| | | ? form.sparePartsIds.map((id) => ({ id, quantity: sparePartQtyMap.value?.[id] ?? 1 })) |
| | | : [], |
| | | } |
| | | const { code } = await addMaintenance(data); |
| | | if (code == 200) { |
| | | ElMessage.success("ä¿å
»æå"); |
| | | emits("ok"); |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | } |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | }; |
| | | |
| | | const fetchSparePartOptions = () => { |
| | | loadingSparePartOptions.value = true; |
| | | // åå¤ä»¶ç®¡ç页ä¸è´ï¼/spareParts/listPage â res.data.records |
| | | getSparePartsList({ current: 1, size: 1000 }) |
| | | .then(res => { |
| | | const fetchSparePartOptions = () => { |
| | | loadingSparePartOptions.value = true; |
| | | // åå¤ä»¶ç®¡ç页ä¸è´ï¼/spareParts/listPage â res.data.records |
| | | getSparePartsList({ current: 1, size: 1000 }) |
| | | .then((res) => { |
| | | if (res.code === 200) { |
| | | sparePartOptions.value = res?.data?.records || []; |
| | | } else { |
| | |
| | | .finally(() => { |
| | | loadingSparePartOptions.value = false; |
| | | }); |
| | | }; |
| | | } |
| | | |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | }; |
| | | const handleCancel = () => { |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | }; |
| | | const handleClose = () => { |
| | | resetForm(); |
| | | sparePartQtyMap.value = {}; |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const open = async (id, row) => { |
| | | planId.value = id; // ä¿å计åä¿å
»è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | fetchSparePartOptions(); |
| | | setForm(row); |
| | | }; |
| | | const open = async (id, row) => { |
| | | planId.value = id; // ä¿å计åä¿å
»è®°å½çid |
| | | visible.value = true; |
| | | await nextTick(); |
| | | fetchSparePartOptions() |
| | | setForm(row); |
| | | }; |
| | | |
| | | defineExpose({ |
| | | open, |
| | | }); |
| | | defineExpose({ |
| | | open, |
| | | }); |
| | | </script> |
| | | |
| | | <style lang="scss" scoped></style> |
| | |
| | | @close="handleClose" |
| | | > |
| | | <el-form :model="form" label-width="100px"> |
| | | <el-form-item label="æå±åºå"> |
| | | <el-tree-select |
| | | v-model="form.areaId" |
| | | :data="areaOptions" |
| | | :props="areaTreeProps" |
| | | node-key="id" |
| | | value-key="id" |
| | | check-strictly |
| | | clearable |
| | | filterable |
| | | placeholder="è¯·éæ©æå±åºå" |
| | | style="width: 100%" |
| | | @change="handleAreaChange" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-select |
| | | v-model="form.deviceLedgerId" |
| | | @change="setDeviceModel" |
| | | placeholder="è¯·éæ©è®¾å¤" |
| | | v-model="form.deviceLedgerIds" |
| | | filterable |
| | | default-first-option |
| | | :reserve-keyword="false" |
| | | clearable |
| | | multiple |
| | | collapse-tags |
| | | collapse-tags-tooltip |
| | | placeholder="è¯·éæ©è®¾å¤" |
| | | style="width: 100%" |
| | | @change="setDeviceModels" |
| | | > |
| | | <el-option |
| | | v-for="(item, index) in deviceOptions" |
| | | :key="index" |
| | | v-for="item in deviceOptions" |
| | | :key="item.id" |
| | | :label="item.deviceName" |
| | | :value="item.id" |
| | | ></el-option> |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="è§æ ¼åå·"> |
| | | <el-input |
| | | v-model="form.deviceModel" |
| | | placeholder="请è¾å
¥è§æ ¼åå·" |
| | | placeholder="èªå¨å¸¦åºè§æ ¼åå·" |
| | | disabled |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
»é¡¹ç®"> |
| | | <el-input |
| | | v-model="form.machineryCategory" |
| | | placeholder="请è¾å
¥ä¿å
»é¡¹ç®" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å½å
¥äºº"> |
| | |
| | | </el-form-item> |
| | | <el-form-item v-if="id" label="ä¿ä¿®ç¶æ"> |
| | | <el-select v-model="form.status"> |
| | | <el-option label="å¾
ä¿ä¿®" :value="0"></el-option> |
| | | <el-option label="å®ç»" :value="1"></el-option> |
| | | <el-option label="失败" :value="2"></el-option> |
| | | <el-option label="å¾
ä¿ä¿®" :value="0" /> |
| | | <el-option label="å®ç»" :value="1" /> |
| | | <el-option label="失败" :value="2" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ä¿å
»äºº"> |
| | | <el-input |
| | | v-model="form.maintenancePerson" |
| | | placeholder="请è¾å
¥ä¿å
»äººå§å" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="计åä¿å
»æ¥æ"> |
| | | <el-date-picker |
| | | style="width: 100%" |
| | | v-model="form.maintenancePlanTime" |
| | | style="width: 100%" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD HH:mm:ss" |
| | | type="date" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥ææ¥æ" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥æ" |
| | | clearable |
| | | /> |
| | | </el-form-item> |
| | | <el-row :gutter="30"> |
| | | <el-col :span="24"> |
| | | <el-form-item label="éä»¶" prop="attachmentIds"> |
| | | <FileUpload v-model:file-list="form.storageBlobDTOs" /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | </FormDialog> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { nextTick, onMounted, ref, unref } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { ElMessage } from "element-plus"; |
| | | import FormDialog from "@/components/Dialog/FormDialog.vue"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import { |
| | | addUpkeep, |
| | | editUpkeep, |
| | | getUpkeepById, |
| | | } from "@/api/equipmentManagement/upkeep"; |
| | | import { ElMessage } from "element-plus"; |
| | | import useFormData from "@/hooks/useFormData"; |
| | | import { getDeviceLedger } from "@/api/equipmentManagement/ledger"; |
| | | import { onMounted } from "vue"; |
| | | import dayjs from "dayjs"; |
| | | import { userListNoPage } from "@/api/system/user.js"; |
| | | import FileUpload from "@/components/AttachmentUpload/file/index.vue"; |
| | | import { |
| | | getDeviceAreaTree, |
| | | getDeviceAreaTreeWithDevices, |
| | | } from "@/api/equipmentManagement/deviceArea"; |
| | | |
| | | defineOptions({ |
| | | name: "设å¤ä¿å
»æ°å¢è®¡å", |
| | |
| | | const id = ref(); |
| | | const visible = ref(false); |
| | | const loading = ref(false); |
| | | |
| | | const areaOptions = ref([]); |
| | | const deviceOptions = ref([]); |
| | | const loadDeviceName = async () => { |
| | | const { data } = await getDeviceLedger(); |
| | | deviceOptions.value = data; |
| | | const userList = ref([]); |
| | | const areaTreeProps = { |
| | | label: "areaName", |
| | | children: "children", |
| | | }; |
| | | |
| | | const { form, resetForm } = useFormData({ |
| | | deviceLedgerId: undefined, // 设å¤Id |
| | | deviceName: undefined, // 设å¤åç§° |
| | | deviceModel: undefined, // è§æ ¼åå· |
| | | maintenancePlanTime: undefined, // 计åä¿å
»æ¥æ |
| | | createUser: undefined, // å½å
¥äºº |
| | | status: 0, //ä¿ä¿®ç¶æ |
| | | machineryCategory: undefined, |
| | | storageBlobDTOs: [], |
| | | maintenancePerson: undefined, // ä¿å
»äºº |
| | | areaId: undefined, |
| | | deviceLedgerId: undefined, |
| | | deviceLedgerIds: [], |
| | | deviceLedgerIdsStr: undefined, |
| | | deviceName: undefined, |
| | | deviceModel: undefined, |
| | | maintenancePlanTime: undefined, |
| | | createUser: undefined, |
| | | status: 0, |
| | | }); |
| | | |
| | | const setDeviceModel = (deviceId) => { |
| | | const option = deviceOptions.value.find((item) => item.id === deviceId); |
| | | form.deviceModel = option.deviceModel; |
| | | const loadAreaTree = async () => { |
| | | const { data } = await getDeviceAreaTree(); |
| | | areaOptions.value = Array.isArray(data) ? data : []; |
| | | }; |
| | | |
| | | /** |
| | | * @desc 设置表åå
容 |
| | | * @param data 设å¤ä¿¡æ¯ |
| | | */ |
| | | const normalizeIdList = (value) => { |
| | | if (Array.isArray(value)) { |
| | | return value |
| | | .map((item) => Number(item)) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (typeof value === "string") { |
| | | return value |
| | | .split(",") |
| | | .map((item) => Number(item.trim())) |
| | | .filter((item) => Number.isFinite(item)); |
| | | } |
| | | if (value !== undefined && value !== null && value !== "") { |
| | | const numericValue = Number(value); |
| | | return Number.isFinite(numericValue) ? [numericValue] : []; |
| | | } |
| | | return []; |
| | | }; |
| | | |
| | | const getNodeDevices = (node) => { |
| | | const candidates = [ |
| | | node?.deviceList, |
| | | node?.devices, |
| | | node?.deviceLedgerList, |
| | | node?.deviceLedgers, |
| | | node?.ledgerList, |
| | | node?.ledgers, |
| | | ]; |
| | | return candidates.find((item) => Array.isArray(item)) || []; |
| | | }; |
| | | |
| | | const normalizeDevice = (item) => ({ |
| | | ...item, |
| | | id: item.id ?? item.deviceLedgerId, |
| | | deviceName: item.deviceName ?? item.name, |
| | | deviceModel: item.deviceModel ?? item.model, |
| | | }); |
| | | |
| | | const collectDevices = (node) => { |
| | | const currentDevices = getNodeDevices(node).map(normalizeDevice); |
| | | const childDevices = (node?.children || []).flatMap((child) => |
| | | collectDevices(child) |
| | | ); |
| | | const deviceMap = new Map(); |
| | | [...currentDevices, ...childDevices].forEach((item) => { |
| | | if (item?.id !== undefined && item?.id !== null) { |
| | | deviceMap.set(Number(item.id), item); |
| | | } |
| | | }); |
| | | return Array.from(deviceMap.values()); |
| | | }; |
| | | |
| | | const findAreaNode = (nodes, areaId) => { |
| | | for (const node of nodes || []) { |
| | | if (Number(node.id) === Number(areaId)) { |
| | | return node; |
| | | } |
| | | const target = findAreaNode(node.children, areaId); |
| | | if (target) { |
| | | return target; |
| | | } |
| | | } |
| | | return null; |
| | | }; |
| | | |
| | | const loadDevicesByArea = async (areaId) => { |
| | | if (!areaId) { |
| | | deviceOptions.value = []; |
| | | return; |
| | | } |
| | | const { data } = await getDeviceAreaTreeWithDevices(); |
| | | const treeData = Array.isArray(data) ? data : []; |
| | | const currentNode = findAreaNode(treeData, areaId); |
| | | deviceOptions.value = currentNode ? collectDevices(currentNode) : []; |
| | | }; |
| | | |
| | | const syncDeviceFields = (deviceIds) => { |
| | | const selectedIds = normalizeIdList(deviceIds); |
| | | const selectedDevices = selectedIds |
| | | .map((deviceId) => |
| | | deviceOptions.value.find((item) => Number(item.id) === Number(deviceId)) |
| | | ) |
| | | .filter(Boolean); |
| | | |
| | | form.deviceLedgerIds = selectedIds; |
| | | form.deviceLedgerId = selectedIds[0]; |
| | | form.deviceLedgerIdsStr = selectedIds.join(","); |
| | | form.deviceName = selectedDevices |
| | | .map((item) => item.deviceName) |
| | | .filter(Boolean) |
| | | .join(","); |
| | | form.deviceModel = selectedDevices |
| | | .map((item) => item.deviceModel || "-") |
| | | .join(","); |
| | | }; |
| | | |
| | | const setDeviceModels = (deviceIds) => { |
| | | syncDeviceFields(deviceIds); |
| | | }; |
| | | |
| | | const handleAreaChange = async (areaId) => { |
| | | form.deviceLedgerId = undefined; |
| | | form.deviceLedgerIds = []; |
| | | form.deviceLedgerIdsStr = undefined; |
| | | form.deviceName = undefined; |
| | | form.deviceModel = undefined; |
| | | await loadDevicesByArea(areaId); |
| | | }; |
| | | |
| | | const setForm = (data) => { |
| | | form.deviceLedgerId = data.deviceLedgerId; |
| | | form.areaId = data.areaId; |
| | | form.deviceLedgerIds = normalizeIdList( |
| | | data.deviceLedgerIds ?? data.deviceLedgerIdsStr ?? data.deviceLedgerId |
| | | ); |
| | | form.deviceLedgerId = form.deviceLedgerIds[0]; |
| | | form.deviceLedgerIdsStr = |
| | | data.deviceLedgerIdsStr ?? form.deviceLedgerIds.join(","); |
| | | form.deviceName = data.deviceName; |
| | | form.deviceModel = data.deviceModel; |
| | | form.createUser = Number(data.createUser); |
| | | form.status = data.status; |
| | | form.machineryCategory = data.machineryCategory; |
| | | form.maintenancePerson = data.maintenancePerson; |
| | | if (data.maintenancePlanTime) { |
| | | form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format( |
| | | "YYYY-MM-DD HH:mm:ss" |
| | | ); |
| | | } |
| | | form.storageBlobDTOs = data.storageBlobVOs || []; |
| | | form.maintenancePlanTime = data.maintenancePlanTime |
| | | ? dayjs(data.maintenancePlanTime).format("YYYY-MM-DD HH:mm:ss") |
| | | : undefined; |
| | | }; |
| | | |
| | | // ç¨æ·å表 |
| | | const userList = ref([]); |
| | | |
| | | onMounted(() => { |
| | | loadDeviceName(); |
| | | loadAreaTree(); |
| | | userListNoPage().then((res) => { |
| | | userList.value = res.data; |
| | | }); |
| | |
| | | id.value = editId; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadAreaTree(); |
| | | setForm(data); |
| | | await loadDevicesByArea(form.areaId); |
| | | syncDeviceFields(form.deviceLedgerIds); |
| | | }; |
| | | |
| | | const sendForm = async () => { |
| | | loading.value = true; |
| | | try { |
| | | syncDeviceFields(form.deviceLedgerIds); |
| | | const payload = { |
| | | ...form, |
| | | deviceLedgerId: form.deviceLedgerIds[0], |
| | | deviceLedgerIds: [...form.deviceLedgerIds], |
| | | deviceLedgerIdsStr: form.deviceLedgerIds.join(","), |
| | | deviceModel: form.deviceModel || "-", |
| | | }; |
| | | const { code } = id.value |
| | | ? await editUpkeep({ id: unref(id), ...form }) |
| | | : await addUpkeep(form); |
| | | if (code == 200) { |
| | | ? await editUpkeep({ id: unref(id), ...payload }) |
| | | : await addUpkeep(payload); |
| | | if (code === 200) { |
| | | ElMessage.success(`${id.value ? "ç¼è¾" : "æ°å¢"}计åæå`); |
| | | visible.value = false; |
| | | emits("ok"); |
| | |
| | | visible.value = false; |
| | | }; |
| | | |
| | | const openModal = () => { |
| | | const openModal = async () => { |
| | | id.value = undefined; |
| | | visible.value = true; |
| | | await nextTick(); |
| | | await loadAreaTree(); |
| | | deviceOptions.value = []; |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <el-tabs v-model="activeTab" |
| | | @tab-change="handleTabChange"> |
| | | <!-- ä¿å
»ä»»å¡tab --> |
| | | <el-tab-pane label="ä¿å
»ä»»å¡" |
| | | name="scheduled"> |
| | | <el-tabs v-model="activeTab" @tab-change="handleTabChange"> |
| | | <!-- 宿¶ä»»å¡ç®¡çtab --> |
| | | <el-tab-pane label="宿¶ä»»å¡ç®¡ç" name="scheduled"> |
| | | <div class="search_form"> |
| | | <el-form :model="scheduledFilters" |
| | | :inline="true"> |
| | | <el-form :model="scheduledFilters" :inline="true"> |
| | | <el-form-item label="ä»»å¡åç§°"> |
| | | <el-input v-model="scheduledFilters.taskName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä»»å¡åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getScheduledTableData" /> |
| | | <el-input |
| | | v-model="scheduledFilters.taskName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥ä»»å¡åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getScheduledTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä»»å¡ç¶æ"> |
| | | <el-select v-model="scheduledFilters.status" |
| | | placeholder="è¯·éæ©ä»»å¡ç¶æ" |
| | | clearable |
| | | style="width: 200px"> |
| | | <el-option label="å¯ç¨" |
| | | value="1" /> |
| | | <el-option label="åç¨" |
| | | value="0" /> |
| | | <el-form-item label="æ¯å¦å¯ç¨"> |
| | | <el-select v-model="scheduledFilters.isEnabled" placeholder="è¯·éæ©æ¯å¦å¯ç¨" clearable style="width: 200px"> |
| | | <el-option label="å¯ç¨" :value="1" /> |
| | | <el-option label="ç¦ç¨" :value="0" /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="getScheduledTableData">æç´¢</el-button> |
| | | <el-button type="primary" @click="getScheduledTableData">æç´¢</el-button> |
| | | <el-button @click="resetScheduledFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <el-text class="mx-1" |
| | | size="large">ä¿å
»ä»»å¡</el-text> |
| | | <el-text class="mx-1" size="large">宿¶ä»»å¡ç®¡ç</el-text> |
| | | <div> |
| | | <el-button type="primary" |
| | | icon="Plus" |
| | | @click="addScheduledTask"> |
| | | <el-button type="primary" icon="Plus" @click="addScheduledTask"> |
| | | æ°å¢ä»»å¡ |
| | | </el-button> |
| | | <el-button type="danger" |
| | | icon="Delete" |
| | | :disabled="scheduledMultipleList.length <= 0" |
| | | @click="delScheduledTaskByIds(scheduledMultipleList.map((item) => item.id))"> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="scheduledMultipleList.length <= 0" |
| | | @click="delScheduledTaskByIds(scheduledMultipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | isSelection |
| | | :column="scheduledColumns" |
| | | :tableData="scheduledDataList" |
| | | :page="{ |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="scheduledColumns" |
| | | :tableData="scheduledDataList" |
| | | :page="{ |
| | | current: scheduledPagination.currentPage, |
| | | size: scheduledPagination.pageSize, |
| | | total: scheduledPagination.total, |
| | | }" |
| | | @selection-change="handleScheduledSelectionChange" |
| | | @pagination="changeScheduledPage"> |
| | | <template #statusRef="{ row }"> |
| | | <el-tag v-if="row.status === 1" |
| | | type="success">å¯ç¨</el-tag> |
| | | <el-tag v-if="row.status === 0" |
| | | type="danger">åç¨</el-tag> |
| | | @selection-change="handleScheduledSelectionChange" |
| | | @pagination="changeScheduledPage" |
| | | > |
| | | <template #isEnabledRef="{ row }"> |
| | | <el-switch |
| | | v-model="row.isEnabled" |
| | | :active-value="1" |
| | | :inactive-value="0" |
| | | :loading="row.enableSwitchLoading" |
| | | :before-change="() => handleScheduledEnableBeforeChange(row)" |
| | | /> |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <el-button type="primary" |
| | | link |
| | | @click="editScheduledTask(row)"> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | @click="editScheduledTask(row)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button type="danger" |
| | | link |
| | | @click="delScheduledTaskByIds(row.id)"> |
| | | <el-button |
| | | type="danger" |
| | | link |
| | | @click="delScheduledTaskByIds(row.id)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | </el-tab-pane> |
| | | <!-- ä¿å
»è®°å½tabï¼å设å¤ä¿å
»é¡µé¢ï¼ --> |
| | | <el-tab-pane label="ä¿å
»è®°å½" |
| | | name="record"> |
| | | |
| | | <!-- ä»»å¡è®°å½tabï¼å设å¤ä¿å
»é¡µé¢ï¼ --> |
| | | <el-tab-pane label="ä»»å¡è®°å½" name="record"> |
| | | <div class="search_form"> |
| | | <el-form :model="filters" |
| | | :inline="true"> |
| | | <el-form :model="filters" :inline="true"> |
| | | <el-form-item label="设å¤åç§°"> |
| | | <el-input v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.deviceName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥è®¾å¤åç§°" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="计åä¿å
»æ¥æ"> |
| | | <el-date-picker v-model="filters.maintenancePlanTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" /> |
| | | <el-date-picker |
| | | v-model="filters.maintenancePlanTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©è®¡åä¿å
»æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,2)" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
ä¿å
»æ¥æ"> |
| | | <el-date-picker v-model="filters.maintenanceActuallyTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" /> |
| | | <el-date-picker |
| | | v-model="filters.maintenanceActuallyTime" |
| | | type="date" |
| | | placeholder="è¯·éæ©å®é
ä¿å
»æ¥æ" |
| | | size="default" |
| | | @change="(date) => handleDateChange(date,1)" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="å®é
ä¿å
»äºº"> |
| | | <el-input v-model="filters.maintenanceActuallyName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" /> |
| | | <el-input |
| | | v-model="filters.maintenanceActuallyName" |
| | | style="width: 240px" |
| | | placeholder="请è¾å
¥å®é
ä¿å
»äºº" |
| | | clearable |
| | | :prefix-icon="Search" |
| | | @change="getTableData" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" |
| | | @click="getTableData">æç´¢</el-button> |
| | | <el-button type="primary" @click="getTableData">æç´¢</el-button> |
| | | <el-button @click="resetFilters">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | <div class="table_list"> |
| | | <div class="actions"> |
| | | <el-text class="mx-1" |
| | | size="large">ä¿å
»è®°å½</el-text> |
| | | <el-text class="mx-1" size="large">ä»»å¡è®°å½</el-text> |
| | | <div> |
| | | <el-button type="success" |
| | | icon="Van" |
| | | @click="addPlan"> |
| | | <el-button type="success" icon="Van" @click="addPlan"> |
| | | æ°å¢è®¡å |
| | | </el-button> |
| | | <el-button @click="handleOut"> |
| | | å¯¼åº |
| | | </el-button> |
| | | <el-button type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))"> |
| | | <el-button |
| | | type="danger" |
| | | icon="Delete" |
| | | :disabled="multipleList.length <= 0 || hasFinishedStatus" |
| | | @click="delRepairByIds(multipleList.map((item) => item.id))" |
| | | > |
| | | æ¹éå é¤ |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | <PIMTable rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | <PIMTable |
| | | rowKey="id" |
| | | isSelection |
| | | :column="columns" |
| | | :tableData="dataList" |
| | | :page="{ |
| | | current: pagination.currentPage, |
| | | size: pagination.pageSize, |
| | | total: pagination.total, |
| | | }" |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage"> |
| | | <template #maintenanceResultRef="{ row }"> |
| | | <div>{{ row.maintenanceResult || '-' }}</div> |
| | | </template> |
| | | <template #statusRef="{ row }"> |
| | | <el-tag v-if="row.status === 2" |
| | | type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" |
| | | type="success">å®ç»</el-tag> |
| | | <el-tag v-if="row.status === 0" |
| | | type="warning">å¾
ä¿å
»</el-tag> |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <!-- è¿ä¸ªåè½è·æ°å¢ä¿å
»åè½ä¸æ¨¡ä¸æ ·ï¼æå¥æä¹ï¼ --> |
| | | <!-- <el-button |
| | | @selection-change="handleSelectionChange" |
| | | @pagination="changePage" |
| | | > |
| | | <template #maintenanceResultRef="{ row }"> |
| | | <div>{{ row.maintenanceResult || '-' }}</div> |
| | | </template> |
| | | <template #statusRef="{ row }"> |
| | | <el-tag v-if="row.status === 2" type="danger">失败</el-tag> |
| | | <el-tag v-if="row.status === 1" type="success">å®ç»</el-tag> |
| | | <el-tag v-if="row.status === 0" type="warning">å¾
ä¿å
»</el-tag> |
| | | </template> |
| | | <template #operation="{ row }"> |
| | | <!-- è¿ä¸ªåè½è·æ°å¢ä¿å
»åè½ä¸æ¨¡ä¸æ ·ï¼æå¥æä¹ï¼ --> |
| | | <!-- <el-button |
| | | type="primary" |
| | | text |
| | | @click="addMaintain(row)" |
| | | > |
| | | æ°å¢ä¿å
» |
| | | </el-button> --> |
| | | <el-button type="primary" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editPlan(row.id)"> |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button type="success" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="addMaintain(row)"> |
| | | ä¿å
» |
| | | </el-button> |
| | | <el-button type="danger" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)"> |
| | | å é¤ |
| | | </el-button> |
| | | <el-button type="primary" |
| | | link |
| | | @click="openFileDialog(row)"> |
| | | éä»¶ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="editPlan(row.id)" |
| | | > |
| | | ç¼è¾ |
| | | </el-button> |
| | | <el-button |
| | | type="success" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="addMaintain(row)" |
| | | > |
| | | ä¿å
» |
| | | </el-button> |
| | | <el-button |
| | | type="danger" |
| | | link |
| | | :disabled="row.status === 1" |
| | | @click="delRepairByIds(row.id)" |
| | | > |
| | | å é¤ |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | | @click="openFileDialog(row)" |
| | | > |
| | | éä»¶ |
| | | </el-button> |
| | | </template> |
| | | </PIMTable> |
| | | </div> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | <PlanModal ref="planModalRef" |
| | | @ok="getTableData" /> |
| | | <MaintenanceModal ref="maintainModalRef" |
| | | @ok="getTableData" /> |
| | | <FormDia ref="formDiaRef" |
| | | @closeDia="getScheduledTableData" /> |
| | | <FileList v-if="fileDialogVisible" |
| | | v-model:visible="fileDialogVisible" |
| | | :record-type="'device_maintenance'" |
| | | :record-id="currentMaintenanceTaskId" /> |
| | | <PlanModal ref="planModalRef" @ok="getTableData" /> |
| | | <MaintenanceModal ref="maintainModalRef" @ok="getTableData" /> |
| | | <FormDia ref="formDiaRef" @closeDia="getScheduledTableData" /> |
| | | <FileListDialog |
| | | ref="fileListDialogRef" |
| | | v-model="fileDialogVisible" |
| | | :show-upload-button="true" |
| | | :show-delete-button="true" |
| | | :delete-method="handleAttachmentDelete" |
| | | :name-column-label="'éä»¶åç§°'" |
| | | :rulesRegulationsManagementId="currentMaintenanceTaskId" |
| | | @upload="handleAttachmentUpload" /> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { |
| | | ref, |
| | | onMounted, |
| | | reactive, |
| | | getCurrentInstance, |
| | | nextTick, |
| | | computed, |
| | | defineAsyncComponent, |
| | | } from "vue"; |
| | | import { Search } from "@element-plus/icons-vue"; |
| | | import { ElMessage, ElMessageBox } from "element-plus"; |
| | | import PlanModal from "./Form/PlanModal.vue"; |
| | | import MaintenanceModal from "./Form/MaintenanceModal.vue"; |
| | | import FormDia from "./Form/formDia.vue"; |
| | | import { |
| | | getUpkeepPage, |
| | | delUpkeep, |
| | | deviceMaintenanceTaskList, |
| | | deviceMaintenanceTaskDel, |
| | | } from "@/api/equipmentManagement/upkeep"; |
| | | import dayjs from "dayjs"; |
| | | import { ref, onMounted, reactive, getCurrentInstance, nextTick, computed } from 'vue' |
| | | import { Search } from '@element-plus/icons-vue' |
| | | import { ElMessage, ElMessageBox } from 'element-plus' |
| | | import PlanModal from './Form/PlanModal.vue' |
| | | import MaintenanceModal from './Form/MaintenanceModal.vue' |
| | | import FormDia from './Form/formDia.vue' |
| | | import FileListDialog from '@/components/Dialog/FileListDialog.vue' |
| | | import { |
| | | getUpkeepPage, |
| | | delUpkeep, |
| | | deviceMaintenanceTaskList, |
| | | deviceMaintenanceTaskDel, |
| | | deviceMaintenanceTaskChangeEnable, |
| | | } from '@/api/equipmentManagement/upkeep' |
| | | import { |
| | | listMaintenanceTaskFiles, |
| | | addMaintenanceTaskFile, |
| | | delMaintenanceTaskFile, |
| | | } from '@/api/equipmentManagement/maintenanceTaskFile' |
| | | import dayjs from 'dayjs' |
| | | |
| | | const { proxy } = getCurrentInstance(); |
| | | const FileList = defineAsyncComponent(() => |
| | | import("@/components/Dialog/FileList.vue") |
| | | ); |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // Tabç¸å
³ |
| | | const activeTab = ref("scheduled"); |
| | | // Tabç¸å
³ |
| | | const activeTab = ref('scheduled') |
| | | |
| | | // 计åå¼¹çªæ§å¶å¨ |
| | | const planModalRef = ref(); |
| | | // ä¿å
»å¼¹çªæ§å¶å¨ |
| | | const maintainModalRef = ref(); |
| | | // 宿¶ä»»å¡å¼¹çªæ§å¶å¨ |
| | | const formDiaRef = ref(); |
| | | // éä»¶å¼¹çª |
| | | const fileListDialogRef = ref(null); |
| | | const fileDialogVisible = ref(false); |
| | | const currentMaintenanceTaskId = ref(null); |
| | | // 计åå¼¹çªæ§å¶å¨ |
| | | const planModalRef = ref() |
| | | // ä¿å
»å¼¹çªæ§å¶å¨ |
| | | const maintainModalRef = ref() |
| | | // 宿¶ä»»å¡å¼¹çªæ§å¶å¨ |
| | | const formDiaRef = ref() |
| | | // éä»¶å¼¹çª |
| | | const fileListDialogRef = ref(null) |
| | | const fileDialogVisible = ref(false) |
| | | const currentMaintenanceTaskId = ref(null) |
| | | |
| | | // ä¿å
»è®°å½tabï¼å设å¤ä¿å
»é¡µé¢ï¼ç¸å
³åé |
| | | const filters = reactive({ |
| | | deviceName: "", |
| | | maintenancePlanTime: "", |
| | | maintenanceActuallyTime: "", |
| | | maintenanceActuallyName: "", |
| | | }); |
| | | // ä»»å¡è®°å½tabï¼å设å¤ä¿å
»é¡µé¢ï¼ç¸å
³åé |
| | | const filters = reactive({ |
| | | deviceName: '', |
| | | maintenancePlanTime: '', |
| | | maintenanceActuallyTime: '', |
| | | maintenanceActuallyName: '', |
| | | }) |
| | | |
| | | const dataList = ref([]); |
| | | const pagination = ref({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }); |
| | | const multipleList = ref([]); |
| | | const dataList = ref([]) |
| | | const pagination = ref({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }) |
| | | const multipleList = ref([]) |
| | | |
| | | // ä¿å
»ä»»å¡tabç¸å
³åé |
| | | const scheduledFilters = reactive({ |
| | | taskName: "", |
| | | status: "", |
| | | }); |
| | | // 宿¶ä»»å¡ç®¡çtabç¸å
³åé |
| | | const scheduledFilters = reactive({ |
| | | taskName: '', |
| | | isEnabled: undefined, |
| | | }) |
| | | |
| | | const scheduledDataList = ref([]); |
| | | const scheduledPagination = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }); |
| | | const scheduledMultipleList = ref([]); |
| | | const scheduledDataList = ref([]) |
| | | const scheduledPagination = reactive({ |
| | | currentPage: 1, |
| | | pageSize: 10, |
| | | total: 0, |
| | | }) |
| | | const scheduledMultipleList = ref([]) |
| | | |
| | | // ä¿å
»ä»»å¡è¡¨æ ¼åé
ç½® |
| | | const scheduledColumns = ref([ |
| | | { prop: "taskName", label: "设å¤åç§°" }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "ä¿å
»é¡¹ç®", |
| | | prop: "machineryCategory", |
| | | minWidth: 120, |
| | | formatData: cell => cell || "--", |
| | | }, |
| | | { |
| | | prop: "frequencyType", |
| | | label: "颿¬¡", |
| | | minWidth: 150, |
| | | // PIMTable 使ç¨çæ¯ formatDataï¼è䏿¯ Element-Plus ç formatter |
| | | formatData: cell => |
| | | ({ |
| | | DAILY: "æ¯æ¥", |
| | | WEEKLY: "æ¯å¨", |
| | | MONTHLY: "æ¯æ", |
| | | QUARTERLY: "å£åº¦", |
| | | }[cell] || ""), |
| | | }, |
| | | { |
| | | prop: "frequencyDetail", |
| | | label: "å¼å§æ¥æä¸æ¶é´", |
| | | minWidth: 150, |
| | | // åæ ·æ¹ç¨ formatDataï¼PIMTable å
é¨ä¼æåå
æ ¼å¼ä¼ è¿æ¥ |
| | | formatData: cell => { |
| | | if (typeof cell !== "string") return ""; |
| | | let val = cell; |
| | | const replacements = { |
| | | MON: "å¨ä¸", |
| | | TUE: "å¨äº", |
| | | WED: "å¨ä¸", |
| | | THU: "å¨å", |
| | | FRI: "å¨äº", |
| | | SAT: "å¨å
", |
| | | SUN: "卿¥", |
| | | }; |
| | | // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é
项 |
| | | return val.replace( |
| | | /MON|TUE|WED|THU|FRI|SAT|SUN/g, |
| | | match => replacements[match] |
| | | ); |
| | | }, |
| | | }, |
| | | { prop: "maintenancePerson", label: "ä¿å
»äºº", minWidth: 100 }, |
| | | { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, |
| | | { |
| | | prop: "registrationDate", |
| | | label: "ç»è®°æ¥æ", |
| | | minWidth: 100, |
| | | formatData: cell => |
| | | cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-", |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "200px", |
| | | }, |
| | | ]); |
| | | // 宿¶ä»»å¡ç®¡çè¡¨æ ¼åé
ç½® |
| | | const scheduledColumns = ref([ |
| | | { |
| | | label: "æå¨åºå", |
| | | prop: "areaName", |
| | | }, |
| | | { prop: "taskName", label: "设å¤åç§°"}, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | prop: "frequencyType", |
| | | label: "颿¬¡", |
| | | minWidth: 150, |
| | | // PIMTable 使ç¨çæ¯ formatDataï¼è䏿¯ Element-Plus ç formatter |
| | | formatData: (cell) => ({ |
| | | DAILY: "æ¯æ¥", |
| | | WEEKLY: "æ¯å¨", |
| | | MONTHLY: "æ¯æ", |
| | | QUARTERLY: "å£åº¦", |
| | | YEARLY: "æ¯å¹´", |
| | | }[cell] || "") |
| | | }, |
| | | { |
| | | prop: "frequencyDetail", |
| | | label: "å¼å§æ¥æä¸æ¶é´", |
| | | minWidth: 150, |
| | | // åæ ·æ¹ç¨ formatDataï¼PIMTable å
é¨ä¼æåå
æ ¼å¼ä¼ è¿æ¥ |
| | | formatData: (cell) => { |
| | | if (typeof cell !== 'string') return ''; |
| | | let val = cell; |
| | | const replacements = { |
| | | MON: 'å¨ä¸', |
| | | TUE: 'å¨äº', |
| | | WED: 'å¨ä¸', |
| | | THU: 'å¨å', |
| | | FRI: 'å¨äº', |
| | | SAT: 'å¨å
', |
| | | SUN: '卿¥' |
| | | }; |
| | | // ä½¿ç¨æ£å䏿¬¡æ§æ¿æ¢ææå¹é
项 |
| | | return val.replace(/MON|TUE|WED|THU|FRI|SAT|SUN/g, match => replacements[match]); |
| | | } |
| | | }, |
| | | { prop: "registrant", label: "ç»è®°äºº", minWidth: 100 }, |
| | | { prop: "registrationDate", label: "ç»è®°æ¥æ", minWidth: 100 }, |
| | | { |
| | | label: "æ¯å¦å¯ç¨", |
| | | prop: "isEnabled", |
| | | dataType: "slot", |
| | | slot: "isEnabledRef", |
| | | align: "center", |
| | | width: "120px", |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "200px", |
| | | }, |
| | | ]) |
| | | |
| | | // ä¿å
»è®°å½è¡¨æ ¼åé
ç½®ï¼å设å¤ä¿å
»è¡¨æ ¼åï¼ |
| | | const columns = ref([ |
| | | { |
| | | label: "设å¤åç§°", |
| | | align: "center", |
| | | prop: "deviceName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | align: "center", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "计åä¿å
»æ¥æ", |
| | | align: "center", |
| | | prop: "maintenancePlanTime", |
| | | formatData: cell => { |
| | | return cell == null ? "-" : dayjs(cell).format("YYYY-MM-DD"); |
| | | }, |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "createUserName", |
| | | }, |
| | | { |
| | | label: "ä¿å
»é¡¹ç®", |
| | | align: "center", |
| | | prop: "machineryCategory", |
| | | formatData: cell => cell || "--", |
| | | }, |
| | | // { |
| | | // label: "å½å
¥æ¥æ", |
| | | // align: "center", |
| | | // prop: "createTime", |
| | | // formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"), |
| | | // width: 200, |
| | | // }, |
| | | { |
| | | label: "å®é
ä¿å
»äºº", |
| | | align: "center", |
| | | prop: "maintenanceActuallyName", |
| | | }, |
| | | { |
| | | label: "å®é
ä¿å
»æ¥æ", |
| | | align: "center", |
| | | prop: "maintenanceActuallyTime", |
| | | formatData: cell => |
| | | cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-", |
| | | }, |
| | | { |
| | | label: "ä¿å
ȍȾ", |
| | | align: "center", |
| | | prop: "maintenanceResult", |
| | | dataType: "slot", |
| | | slot: "maintenanceResultRef", |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | align: "center", |
| | | prop: "status", |
| | | dataType: "slot", |
| | | slot: "statusRef", |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "350px", |
| | | }, |
| | | ]); |
| | | // ä»»å¡è®°å½è¡¨æ ¼åé
ç½®ï¼å设å¤ä¿å
»è¡¨æ ¼åï¼ |
| | | const columns = ref([ |
| | | { |
| | | label: "æå¨åºå", |
| | | prop: "areaName", |
| | | }, |
| | | { |
| | | label: "设å¤åç§°", |
| | | align: "center", |
| | | prop: "deviceName", |
| | | }, |
| | | { |
| | | label: "è§æ ¼åå·", |
| | | align: "center", |
| | | prop: "deviceModel", |
| | | }, |
| | | { |
| | | label: "计åä¿å
»æ¥æ", |
| | | align: "center", |
| | | prop: "maintenancePlanTime", |
| | | formatData: (cell) => dayjs(cell).format("YYYY-MM-DD"), |
| | | }, |
| | | { |
| | | label: "å½å
¥äºº", |
| | | align: "center", |
| | | prop: "createUserName", |
| | | }, |
| | | // { |
| | | // label: "å½å
¥æ¥æ", |
| | | // align: "center", |
| | | // prop: "createTime", |
| | | // formatData: (cell) => dayjs(cell).format("YYYY-MM-DD HH:mm:ss"), |
| | | // width: 200, |
| | | // }, |
| | | { |
| | | label: "å®é
ä¿å
»äºº", |
| | | align: "center", |
| | | prop: "maintenanceActuallyName", |
| | | }, |
| | | { |
| | | label: "å®é
ä¿å
»æ¥æ", |
| | | align: "center", |
| | | prop: "maintenanceActuallyTime", |
| | | formatData: (cell) => |
| | | cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : "-", |
| | | }, |
| | | { |
| | | label: "ä¿å
ȍȾ", |
| | | align: "center", |
| | | prop: "maintenanceResult", |
| | | dataType: "slot", |
| | | slot: "maintenanceResultRef", |
| | | }, |
| | | { |
| | | label: "ç¶æ", |
| | | align: "center", |
| | | prop: "status", |
| | | dataType: "slot", |
| | | slot: "statusRef", |
| | | }, |
| | | { |
| | | fixed: "right", |
| | | label: "æä½", |
| | | dataType: "slot", |
| | | slot: "operation", |
| | | align: "center", |
| | | width: "350px", |
| | | }, |
| | | ]) |
| | | |
| | | // Tab忢å¤ç |
| | | const handleTabChange = tabName => { |
| | | if (tabName === "record") { |
| | | getTableData(); |
| | | } else if (tabName === "scheduled") { |
| | | getScheduledTableData(); |
| | | // Tab忢å¤ç |
| | | const handleTabChange = (tabName) => { |
| | | if (tabName === 'record') { |
| | | getTableData() |
| | | } else if (tabName === 'scheduled') { |
| | | getScheduledTableData() |
| | | } |
| | | } |
| | | |
| | | // 宿¶ä»»å¡ç®¡çç¸å
³æ¹æ³ |
| | | const getScheduledTableData = async () => { |
| | | try { |
| | | const params = { |
| | | current: scheduledPagination.currentPage, |
| | | size: scheduledPagination.pageSize, |
| | | taskName: scheduledFilters.taskName || undefined, |
| | | isEnabled: scheduledFilters.isEnabled, |
| | | } |
| | | }; |
| | | |
| | | // ä¿å
»ä»»å¡ç¸å
³æ¹æ³ |
| | | const getScheduledTableData = async () => { |
| | | try { |
| | | const params = { |
| | | current: scheduledPagination.currentPage, |
| | | size: scheduledPagination.pageSize, |
| | | taskName: scheduledFilters.taskName || undefined, |
| | | status: scheduledFilters.status || undefined, |
| | | }; |
| | | const { code, data } = await deviceMaintenanceTaskList(params); |
| | | if (code === 200) { |
| | | scheduledDataList.value = data?.records || []; |
| | | scheduledPagination.total = data?.total || 0; |
| | | } |
| | | } catch (error) { |
| | | ElMessage.error("è·å宿¶ä»»å¡å表失败"); |
| | | const { code, data } = await deviceMaintenanceTaskList(params) |
| | | if (code === 200) { |
| | | const records = data?.records || [] |
| | | scheduledDataList.value = records.map((item) => ({ |
| | | ...item, |
| | | isEnabled: Number(item.isEnabled ?? item.status ?? 1), |
| | | enableSwitchLoading: false, |
| | | })) |
| | | scheduledPagination.total = data?.total || 0 |
| | | } |
| | | }; |
| | | } catch (error) { |
| | | ElMessage.error('è·å宿¶ä»»å¡å表失败') |
| | | } |
| | | } |
| | | |
| | | const resetScheduledFilters = () => { |
| | | scheduledFilters.taskName = ""; |
| | | scheduledFilters.status = ""; |
| | | getScheduledTableData(); |
| | | }; |
| | | const resetScheduledFilters = () => { |
| | | scheduledFilters.taskName = '' |
| | | scheduledFilters.isEnabled = undefined |
| | | getScheduledTableData() |
| | | } |
| | | |
| | | const handleScheduledSelectionChange = selection => { |
| | | scheduledMultipleList.value = selection; |
| | | }; |
| | | const handleScheduledSelectionChange = (selection) => { |
| | | scheduledMultipleList.value = selection |
| | | } |
| | | |
| | | const changeScheduledPage = page => { |
| | | scheduledPagination.currentPage = page.page; |
| | | scheduledPagination.pageSize = page.limit; |
| | | getScheduledTableData(); |
| | | }; |
| | | const changeScheduledPage = (page) => { |
| | | scheduledPagination.currentPage = page.page |
| | | scheduledPagination.pageSize = page.limit |
| | | getScheduledTableData() |
| | | } |
| | | |
| | | const addScheduledTask = () => { |
| | | nextTick(() => { |
| | | formDiaRef.value?.openDialog("add"); |
| | | }); |
| | | }; |
| | | const addScheduledTask = () => { |
| | | nextTick(() => { |
| | | formDiaRef.value?.openDialog('add'); |
| | | }); |
| | | } |
| | | |
| | | const editScheduledTask = row => { |
| | | if (row) { |
| | | nextTick(() => { |
| | | formDiaRef.value?.openDialog("edit", row); |
| | | }); |
| | | } |
| | | }; |
| | | const editScheduledTask = (row) => { |
| | | if (row) { |
| | | nextTick(() => { |
| | | formDiaRef.value?.openDialog('edit', row); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | const delScheduledTaskByIds = async ids => { |
| | | try { |
| | | await ElMessageBox.confirm("ç¡®å®å é¤éä¸ç宿¶ä»»å¡åï¼", "æç¤º", { |
| | | type: "warning", |
| | | }); |
| | | const payload = Array.isArray(ids) ? ids : [ids]; |
| | | await deviceMaintenanceTaskDel(payload); |
| | | ElMessage.success("å é¤å®æ¶ä»»å¡æå"); |
| | | getScheduledTableData(); |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | }; |
| | | |
| | | const handleScheduledOut = () => { |
| | | ElMessage.info("导åºå®æ¶ä»»å¡åè½å¾
å®ç°"); |
| | | }; |
| | | |
| | | // ä¿å
»è®°å½ç¸å
³æ¹æ³ï¼å设å¤ä¿å
»é¡µé¢æ¹æ³ï¼ |
| | | const getTableData = async () => { |
| | | try { |
| | | const params = { |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | deviceName: filters.deviceName || undefined, |
| | | maintenancePlanTime: filters.maintenancePlanTime |
| | | ? dayjs(filters.maintenancePlanTime).format("YYYY-MM-DD") |
| | | : undefined, |
| | | maintenanceActuallyTime: filters.maintenanceActuallyTime |
| | | ? dayjs(filters.maintenanceActuallyTime).format("YYYY-MM-DD") |
| | | : undefined, |
| | | maintenanceActuallyName: filters.maintenanceActuallyName || undefined, |
| | | }; |
| | | |
| | | const { code, data } = await getUpkeepPage(params); |
| | | if (code === 200) { |
| | | dataList.value = data.records; |
| | | pagination.value.total = data.total; |
| | | } |
| | | } catch (error) { |
| | | console.log(error); |
| | | } |
| | | }; |
| | | |
| | | const resetFilters = () => { |
| | | filters.deviceName = ""; |
| | | filters.maintenancePlanTime = ""; |
| | | filters.maintenanceActuallyTime = ""; |
| | | filters.maintenanceActuallyName = ""; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const handleSelectionChange = selection => { |
| | | multipleList.value = selection; |
| | | }; |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1); |
| | | }); |
| | | |
| | | const changePage = page => { |
| | | pagination.value.currentPage = page.page; |
| | | pagination.value.pageSize = page.limit; |
| | | getTableData(); |
| | | }; |
| | | |
| | | const addMaintain = row => { |
| | | maintainModalRef.value.open(row.id, row); |
| | | }; |
| | | |
| | | const addPlan = () => { |
| | | planModalRef.value.openModal(); |
| | | }; |
| | | |
| | | const editPlan = id => { |
| | | planModalRef.value.openEdit(id); |
| | | }; |
| | | |
| | | const delRepairByIds = async ids => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const hasFinished = multipleList.value.some(item => item.status === 1); |
| | | if (hasFinished) { |
| | | ElMessage.warning("ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½"); |
| | | return; |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm("确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?", "è¦å", { |
| | | confirmButtonText: "ç¡®å®", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | }); |
| | | |
| | | const { code } = await delUpkeep(ids); |
| | | if (code === 200) { |
| | | ElMessage.success("å 餿å"); |
| | | getTableData(); |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | }; |
| | | |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm("éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼", "导åº", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "åæ¶", |
| | | type: "warning", |
| | | const delScheduledTaskByIds = async (ids) => { |
| | | try { |
| | | await ElMessageBox.confirm('ç¡®å®å é¤éä¸ç宿¶ä»»å¡åï¼', 'æç¤º', { |
| | | type: 'warning', |
| | | }) |
| | | .then(() => { |
| | | proxy.download("/device/maintenance/export", {}, "设å¤ä¿å
».xlsx"); |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.info("已忶"); |
| | | }); |
| | | }; |
| | | const payload = Array.isArray(ids) ? ids : [ids] |
| | | await deviceMaintenanceTaskDel(payload) |
| | | ElMessage.success('å é¤å®æ¶ä»»å¡æå') |
| | | getScheduledTableData() |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | |
| | | const handleDateChange = (date, type) => { |
| | | if (type === 1) { |
| | | filters.maintenanceActuallyTime = date |
| | | ? dayjs(date).format("YYYY-MM-DD") |
| | | : ""; |
| | | } else { |
| | | filters.maintenancePlanTime = date ? dayjs(date).format("YYYY-MM-DD") : ""; |
| | | const handleScheduledEnableBeforeChange = async (row) => { |
| | | if (row.enableSwitchLoading) { |
| | | return false |
| | | } |
| | | const nextValue = Number(row.isEnabled) === 1 ? 0 : 1 |
| | | row.enableSwitchLoading = true |
| | | try { |
| | | const res = await deviceMaintenanceTaskChangeEnable({ |
| | | id: row.id, |
| | | isEnabled: nextValue, |
| | | }) |
| | | if (res?.code !== 200) { |
| | | throw new Error(res?.msg || 'æ´æ°å¤±è´¥') |
| | | } |
| | | getTableData(); |
| | | }; |
| | | ElMessage.success('å¯ç¨ç¶æå·²æ´æ°') |
| | | return true |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || 'å¯ç¨ç¶ææ´æ°å¤±è´¥') |
| | | return false |
| | | } finally { |
| | | row.enableSwitchLoading = false |
| | | } |
| | | } |
| | | |
| | | // æå¼éä»¶å¼¹çª |
| | | const openFileDialog = async row => { |
| | | currentMaintenanceTaskId.value = row.id; |
| | | fileDialogVisible.value = true; |
| | | }; |
| | | const handleScheduledOut = () => { |
| | | ElMessage.info('导åºå®æ¶ä»»å¡åè½å¾
å®ç°') |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // æ ¹æ®é»è®¤æ¿æ´»ç Tab è°ç¨å¯¹åºçæ¥è¯¢æ¥å£ |
| | | if (activeTab.value === "scheduled") { |
| | | getScheduledTableData(); |
| | | } else { |
| | | getTableData(); |
| | | // ä»»å¡è®°å½ç¸å
³æ¹æ³ï¼å设å¤ä¿å
»é¡µé¢æ¹æ³ï¼ |
| | | const getTableData = async () => { |
| | | try { |
| | | const params = { |
| | | current: pagination.value.currentPage, |
| | | size: pagination.value.pageSize, |
| | | deviceName: filters.deviceName || undefined, |
| | | maintenancePlanTime: filters.maintenancePlanTime ? dayjs(filters.maintenancePlanTime).format('YYYY-MM-DD') : undefined, |
| | | maintenanceActuallyTime: filters.maintenanceActuallyTime ? dayjs(filters.maintenanceActuallyTime).format('YYYY-MM-DD') : undefined, |
| | | maintenanceActuallyName: filters.maintenanceActuallyName || undefined, |
| | | } |
| | | }); |
| | | |
| | | const { code, data } = await getUpkeepPage(params) |
| | | if (code === 200) { |
| | | dataList.value = data.records |
| | | pagination.value.total = data.total |
| | | } |
| | | } catch (error) { |
| | | console.log(error); |
| | | |
| | | } |
| | | } |
| | | |
| | | const resetFilters = () => { |
| | | filters.deviceName = '' |
| | | filters.maintenancePlanTime = '' |
| | | filters.maintenanceActuallyTime = '' |
| | | filters.maintenanceActuallyName = '' |
| | | getTableData() |
| | | } |
| | | |
| | | const handleSelectionChange = (selection) => { |
| | | multipleList.value = selection |
| | | } |
| | | |
| | | // æ£æ¥éä¸çè®°å½ä¸æ¯å¦æå®ç»ç¶æç |
| | | const hasFinishedStatus = computed(() => { |
| | | return multipleList.value.some(item => item.status === 1) |
| | | }) |
| | | |
| | | const changePage = (page) => { |
| | | pagination.value.currentPage = page.page |
| | | pagination.value.pageSize = page.limit |
| | | getTableData() |
| | | } |
| | | |
| | | const addMaintain = (row) => { |
| | | maintainModalRef.value.open(row.id, row) |
| | | } |
| | | |
| | | const addPlan = () => { |
| | | planModalRef.value.openModal() |
| | | } |
| | | |
| | | const editPlan = (id) => { |
| | | planModalRef.value.openEdit(id) |
| | | } |
| | | |
| | | const delRepairByIds = async (ids) => { |
| | | // æ£æ¥æ¯å¦æå®ç»ç¶æçè®°å½ |
| | | const hasFinished = multipleList.value.some(item => item.status === 1) |
| | | if (hasFinished) { |
| | | ElMessage.warning('ä¸è½å é¤ç¶æä¸ºå®ç»çè®°å½') |
| | | return |
| | | } |
| | | |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤ä¿å
»æ°æ®, æ¤æä½ä¸å¯é?', 'è¦å', { |
| | | confirmButtonText: 'ç¡®å®', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }) |
| | | |
| | | const { code } = await delUpkeep(ids) |
| | | if (code === 200) { |
| | | ElMessage.success('å 餿å') |
| | | getTableData() |
| | | } |
| | | } catch (error) { |
| | | // ç¨æ·åæ¶å é¤ |
| | | } |
| | | } |
| | | |
| | | const handleOut = () => { |
| | | ElMessageBox.confirm('éä¸çå
容å°è¢«å¯¼åºï¼æ¯å¦ç¡®è®¤å¯¼åºï¼', '导åº', { |
| | | confirmButtonText: '确认', |
| | | cancelButtonText: 'åæ¶', |
| | | type: 'warning', |
| | | }) |
| | | .then(() => { |
| | | proxy.download('/device/maintenance/export', {}, '设å¤ä¿å
».xlsx') |
| | | }) |
| | | .catch(() => { |
| | | ElMessage.info('已忶') |
| | | }) |
| | | } |
| | | |
| | | const handleDateChange = (date, type) => { |
| | | if (type === 1) { |
| | | filters.maintenanceActuallyTime = date ? dayjs(date).format('YYYY-MM-DD') : '' |
| | | } else { |
| | | filters.maintenancePlanTime = date ? dayjs(date).format('YYYY-MM-DD') : '' |
| | | } |
| | | getTableData() |
| | | } |
| | | |
| | | // éä»¶ç¸å
³æ¹æ³ |
| | | // æ¥è¯¢éä»¶å表 |
| | | const fetchMaintenanceTaskFiles = async (deviceMaintenanceId) => { |
| | | try { |
| | | const params = { |
| | | current: 1, |
| | | size: 100, |
| | | deviceMaintenanceId, |
| | | rulesRegulationsManagementId:deviceMaintenanceId |
| | | } |
| | | const res = await listMaintenanceTaskFiles(params) |
| | | const records = res?.data?.records || [] |
| | | const mapped = records.map(item => ({ |
| | | id: item.id, |
| | | name: item.fileName || item.name, |
| | | url: item.fileUrl || item.url, |
| | | raw: item, |
| | | })) |
| | | fileListDialogRef.value?.setList(mapped) |
| | | } catch (error) { |
| | | ElMessage.error('è·åéä»¶å表失败') |
| | | } |
| | | } |
| | | |
| | | // æå¼éä»¶å¼¹çª |
| | | const openFileDialog = async (row) => { |
| | | currentMaintenanceTaskId.value = row.id |
| | | fileDialogVisible.value = true |
| | | await fetchMaintenanceTaskFiles(row.id) |
| | | } |
| | | |
| | | // å·æ°éä»¶å表 |
| | | const refreshFileList = async () => { |
| | | if (!currentMaintenanceTaskId.value) return |
| | | await fetchMaintenanceTaskFiles(currentMaintenanceTaskId.value) |
| | | } |
| | | |
| | | // ä¸ä¼ éä»¶ |
| | | const handleAttachmentUpload = async (filePayload) => { |
| | | if (!currentMaintenanceTaskId.value) return |
| | | try { |
| | | const payload = { |
| | | name: filePayload?.fileName || filePayload?.name, |
| | | url: filePayload?.fileUrl || filePayload?.url, |
| | | deviceMaintenanceId: currentMaintenanceTaskId.value, |
| | | } |
| | | await addMaintenanceTaskFile(payload) |
| | | ElMessage.success('æä»¶ä¸ä¼ æå') |
| | | await refreshFileList() |
| | | } catch (error) { |
| | | ElMessage.error('æä»¶ä¸ä¼ 失败') |
| | | } |
| | | } |
| | | |
| | | // å é¤éä»¶ |
| | | const handleAttachmentDelete = async (row) => { |
| | | if (!row?.id) return false |
| | | try { |
| | | await ElMessageBox.confirm('确认å é¤è¯¥éä»¶ï¼', 'æç¤º', { type: 'warning' }) |
| | | } catch { |
| | | return false |
| | | } |
| | | try { |
| | | await delMaintenanceTaskFile(row.id) |
| | | ElMessage.success('å 餿å') |
| | | await refreshFileList() |
| | | return true |
| | | } catch (error) { |
| | | ElMessage.error('å é¤å¤±è´¥') |
| | | return false |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // æ ¹æ®é»è®¤æ¿æ´»ç Tab è°ç¨å¯¹åºçæ¥è¯¢æ¥å£ |
| | | if (activeTab.value === 'scheduled') { |
| | | getScheduledTableData() |
| | | } else { |
| | | getTableData() |
| | | } |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | .table_list { |
| | | margin-top: unset; |
| | | } |
| | | .actions { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | margin-bottom: 10px; |
| | | } |
| | | </style> |
| | | |
| | | |
| | |
| | | const { VITE_APP_ENV } = env; |
| | | const baseUrl = |
| | | env.VITE_APP_ENV === "development" |
| | | ? "http://1.15.17.182:9048" |
| | | ? "http://192.168.0.226:7005" |
| | | : env.VITE_BASE_API; |
| | | const javaUrl = |
| | | env.VITE_APP_ENV === "development" |